Homeduino …der universelle LAN/WLAN-Arduino für die Hausautomation mit I/O-Shield 1.0

[google-translator] Wichtiger Hinweis: Es gibt mittlerweile eine neue Softwareversion:   Homduino 4.0

Achtung: Mittlerweile gibt es das Homeduino Shield 2.0  siehe hier:
https://www.stall.biz/?project=homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation-mit-io-shield-2-0-2

1  Ausgangssituation
Die Verwendung des Arduino im Hausnetz bietet sich insbesondere deshalb an, weil es eine Vielzahl von preisgünstigen Sensoren und Aktoren gibt und zudem eine riesige Entwicklergemeinde hierfür leistungsfähige Software entwickelt. Natürlich lassen sich eigenständige Steuerungen damit entwickeln, aber im Hinblick auf Hausautomation ist die Einbindung in ein Hausnetz besonders sinnvoll und zukunftssicher. Die folgenden Lösungsansätze konzentrieren sich auf Kombinationen mit der Homematic oder einem RaspberryPi als Steuerungsrechner, aber das System ist so universell ausgelegt, dass auch Integrationen mit anderen Systemen leicht möglich sind.

2  Hardware des Homeduino
Im Folgenden wird  kochrezeptartig das verwendete System beschrieben, so dass auch Anfänger relativ leicht einen Nachbau erfolgreich realisieren können.

Zutatenliste:
1x Arduino MEGA 2560 r3 (bei ebay in China für unter 10€ zu bekommen)
1x Ethernet Shield W5100 (bei ebay in China für unter 6€ zu bekommen)

und optional:

1x WLAN-Repeater/Bridge möglichst mit integriertem USB-Netzteil
(ich verwende den Phicomm M1 , bei Amazon für 12,50€)
1x I/O-Anschluss-Board, entweder selbst bauen oder Bausatz/Platine bei mir anfragen.
(Beschreibung  der ersten Entwicklungsversion hier    http://homematic-forum.de/forum/viewtopic.php?f=31&t=18871#p156004 )

Mittlerweile gibt es ein verbessertes neues I/O-Anschluss-Board mit großenteils fertiggestellter Platine.
Beschreibung hier: https://www.stall.biz/?project=vielseitiges-io-shield-board-2-0-fur-fast-alle-arduinos

Kauf-Interessierte können mich  per email (Kontakt -Button)  ansprechen.
Der Teil-Bausatz kostet 26€ plus 3,90€ Versand nach Deutschland.

 

komponenten

3  Eigenschaften des Homeduino
Mit Verwendung des optionalen I/O-Shields ist ein universeller Anschluss von Sensoren und Aktoren möglich, wie sie für die Heimautomation erforderlich sind. Dazu gehören einfache Anschlussmöglichkeiten für 1-Wire-Sensoren, NTC-Temperaturfühler, Schalter /Reedschalter, Ultraschallsensoren, analogen Gebern, IR-Signalempfängern, 435Mhz-Fernsteuerungen, Displays usw. Darüber hinaus sind natürlich auch alle Arten von Niedervoltrelais bis 24V ohne zusätzliche Treiber anschließbar und auch Niedervolt -Verbraucher bis etwa 2A sind direkt steuerbar. Der elektrische Anschluss erfolgt mittels professioneller 40-poliger WAGO-Klemmleiste, damit ein zuverlässiger Betrieb ohne die beim Arduino häufig anzutreffenden „fliegenden“ Breadboard-Aufbauten möglich ist!

Folie2

 

 

shield_in_hand
Insgesamt stehen mit dem verwendeten I/O-Shield 14 als Ein- oder Ausgänge nutzbare Pins zur Verfügung. Darüberhinaus hat der MEGA 2560 noch weitere I/Os, die aber nur mit zusätzlichen speziellen Anschlüssen verfügbar gemacht werden können. Hier wurde bewusst die Anzahl der I/Os auf 14 begrenzt, damit der Homeduino nicht mit zuvielen Funktionen „überfrachtet“ wird. Stattdessen sollten sehr umfangreiche Steuerungsaufgaben besser auf mehrere Homeduinos verteilt werden. Und zusätzlich kann das IO-Shield auch für die „kleinen“ Arduinos wie der UNO verwendet werden.

Also unser Homeduiono hat mit dem optionalen I/O-Shield bis zu…

>> 6 analoge Eingänge:
– 0 bis +5V oder 0 bis +10V , per Jumper kanalweise umschaltbar
– verwendbar auch als schnelle  digitale I/O mit  für jeden Kanal einzeln einstellbarer Triggerschwelle (!)
– mit einzeln per Jumper zuschaltbaren 10kOhm Pullup-Widerständen z.B. für Standard-NTC- Thermofühler

>> 8 digitale I/Os
– Jeder I/O mit Status LED
– jeder digitale Eingang mit 4k7-Pullup z.B. für 1-Wire-Sensoren
– jeder digitale Ausgang mit Hochstrom-Mosfet -Treiber für Ansteuerung von NV-Relais etc.

Die Anschlussbelegung zeigt folgendes Bild:

board_io_shield
3  LAN/WLAN-Integration im Heimnetz

Der ursprüngliche Plan für den Homeduino war die Verwendung des Arduino YUN oder eines anderen Arduinos mit eigenem WLAN-Shield. Aber nach ersten Versuchen mit dem YUN wurde klar, dass man für diese Lösung auch die  recht komplizierte WLAN-Programmierung mit  in das Homeduino-Sketch  integrieren muss.  Auch ist wegen der direkten Nähe zum heimischen Router oftmals eine drahtgebundene LAN-Kommunikation nicht nur einfacher sondern auch kostengünstiger und zuverlässiger realisierbar.  Nach Abwägung aller  Vor- und Nachteile wurde deshalb eine Lösung mit standardmässigem Ethernet-Shield und einem zusätzlichen eigenständigen WLAN-Adapter oder Repeater realisiert:

Die Basis-Kommunikation mit dem Homeduino erfolgt also über das Ethernet-Shield. Dabei kann man wählen, ob mittels LAN-Leitung und direktem Anschluss an den Router die Daten drahtgebunden (wired) übertragen werden, oder ob mit einem zusätzlichen WLAN-Repeater o.ä. eine drahtlose Anbindung des Arduino an das Heimnetz erfolgen soll. Dies hängt, wie schon gesagt,  natürlich davon ab, ob der Homeduino evtl. in der Nähe des Routers platziert werden kann oder eben nicht.

Als WLAN-Repeater/Router  eignet sich ein PHICOMM M1 besonders gut, weil er nicht nur sehr kostengünstig ist und alle notwendigen Betriebsarten beherrscht, sondern weil er ein integriertes 5V-USB-Netzteil hat (5V, 0,5A). Damit lässt sich der Homeduino wunderbar  mitversorgen, wenn er nicht gerade viele zusätzliche und stromhungrige Verbraucher hat. Das nachfolgende Bild zeigt, wie die einzelnen Komponenten verknüpft werden. Der Homeduino wird einfach mit einer kurzen LAN-Leitung und einer kurzen USB-Leitung mit dem PHICOMM verbunden. Das ist hardwareseitig schon alles!

Softwaremässig müssen die Komponenten dann entsprechend der individuellen Heimnetz-Gegebenheiten eingestellt werden.  Der Phicomm hat von Haus aus die IP :  192.168.0.1   , was leider nicht zu dem Nummerkreis meiner Fritzbox (192.168.178.1) passt. Deshalb muss der PHICOMM-Router zuerst auf eine Adresse im eigenen Heimnetz (z.B. 192.168.178.3)  eingestellt werden (siehe Bedienungsanleitung).

 

 

Folie13

Die Einstellung der weiteren Parameter im PHICOMM ist dann sehr einfach, indem man den sog. Client-Betrieb aktiviert. Zusätzlich ist noch das WLAN-Kennwort des Heimnetz-Routers einzugeben. Das ist schon alles !

Folie14

Wer zusätzlich  noch gerne das eigene WLAN-Netz bezüglich der Reichweite erweitern  möchte, der kann auch statt des Client-Modus den Repeater-Betrieb wählen. Das funktioniert auch sehr gut.

 

4  Software des Homeduino
Die Software des Homeduino, also gewissermassen das Betriebssystem, wurde so gestaltet, dass die Software für alle geplanten Mess- und Steuerungsaufgaben fertig konfiguriert ist. Eine individuelle Anpassung ist kaum notwendig (nur einige Parameter werden individuell gesetzt).
Mit  einfachen  Befehlen wird die Funktion der I/Os bestimmt und programmiert. Bei der Gestaltung der Befehle wurde grosser Wert darauf gelegt, dass man bereits mit einem beliebigen Browser eine Steuerung der I/Os erreichen kann. Die nachfolgende Befehlsliste zeigt eigentlich sehr eindrucksvoll, wie und was man mit dem Homeduino alles steuern und messen kann:

Befehlsliste des Homeduino:  ( mit homeduino IP: 192.168.178.58)

arduino IP: 192.168.178.58

IP-Adresse/?Befehl:Param1:Param2: ...

192.168.178.58/?setpin:4:5:               >> Pins D4,D5 auf HIGH setzen und Pins als Output setzen 

192.168.178.58/?resetpin:7:4:8:           >> Pins D7,D4,D8 auf LOW setzen und Pinsals Output setzen 

192.168.178.58/?digitalin:5:4:            >> Pins D5,D4 lesen und Pins als Input setzen 

192.168.178.58/?analogin:0:5:             >> Pins A0,A5 lesen und Pins auf Analoginput setzen 

192.168.178.58/?pwm_out:4:96:             >> PWM-Signal mit Tastverhältnis 96% an Digitalpin D4 ausgeben 

192.168.178.58/?onewire:6:0:5:1:          >> An D6 die 1-Wire Sensoren Nr.0, Nr.5 und Nr.0 einlesen 

192.168.178.58/?1wire:7:                  >> An D7 den 1-Wire Sensor einlesen 

192.168.178.58/?1wire_address:8:          >> An D8 alle Adressen der 1-Wire Sensoren auslesen 

192.168.178.58/?rf_send:4:4523029:24:     >> An D4 das RF-Telegramm 4523029 mit 24bit-Kodierung ausgeben 

192.168.178.58/?rf_receive:               >> An D3 auf rf-Signal 3s warten und RF-Telegramm anzeigen 

192.168.178.58/?ir_send:nec:1086136543:32 >> An D9 das IR-Telegramm 1086136543 mit 36 bit laenge ausgeben 

192.168.178.58/?ir_receive:               >> An D2 auf IR-Signal 3s warten und IR-Telegramm anzeigen 

192.168.178.58/?ir_rawstore:5:            >> 3sec empfangen und IR-Signal auf Speicherplatz 5 wegspeichern

192.168.178.58/?ir_rawsend:5:             >> sendet IR-Signal von Speicherplatz 5 

192.168.178.58/? 

192.168.178.58/? 

192.168.178.58/?w_data:0:1425:            >> Homeduino-Integervariablen "w_data[0]" mit Wert 1525 setzen 

192.168.178.58/?r_data:4:5:               >> Homeduino-Integervariablen "w_data[4]" und "w_data[5]" auslesen 

192.168.178.58/?dist:6:                   >> Entfernung in cm mit Ultraschallsensor an Pin D6 einlesen 

192.168.178.58/?w_msg:abcdef              >> "abcdef" in Homeduino-String "message" speichern 

192.168.178.58/?set_time:174393838:       >> Homeduino-Zeit (Sekunden seit 1.1.1970) setzen/auslesen 

192.168.178.58/?display:0:3:meldung       >> zeigt auf Display in Position 0 in Zeile 3 den Text "meldung" 

192.168.178.58/?display:                  >> loescht Display komplett

192.168.178.58/?barometer                 >> zeigt Daten vom Barometer-Sensor BMP180 >> 

192.168.178.58/?r_msg:                    >> Homeduino-String "message" auslesen 

192.168.178.58/?ntc_in:0:5:               >> NTC-Temperaturen von Pin A0 und A5 lesen 

192.168.178.58/?help:                     >> Anzeige der Befehlsliste 

192.168.178.58/?ver:                      >> Anzeige der Firmware-Version 

 

 

Die Befehlsliste ist beliebig erweiterbar, bis der Arbeitspeicher des MEGA 2560 erschöpft ist. Aber zur Zeit sind noch viele Reserven vorhanden. ( Begonnen habe ich mit dem UNO, bin dann aber relativ schnell an die Kapazitätsgrenze gestossen!) Die einzelnen Befehle können mit dem Browser abgesetzt werden oder aber von einem Steuerungsrechner wie z.B. der Homematic oder einem Raspberry oder, oder …

5  Programmierung des Arduino
Die „Firmware“ des Homeduinos ist leider nicht ganz so einfach „reinzuladen“, weil erst die Arduino-Entwicklungsumgebung (IDE) mit allen notwendigen Libraries installiert werden muss. Erst dann kann die Homeduino-Software compiliert und hochgeladen werden.

Also hier die „Schritt für Schritt“-Installation:

1. hier die verwendete  Arduino-Version runterladen:  http://downloads.arduino.cc/arduino-1.5.7-windows.exe  und normal  installieren. Getestet habe ich Version 1.5.7 , dabei wurde der USB-Treiber mit installiert. Die Installationsdateien liegen bei Windows standardmässig im Verzeichnis : „c:\Program Files (x86)\Arduino\“

2. in den Unterordner „libraries“ folgende zusätzliche libraries als Unterverzeichnisse kopieren:

3. folgendes Datenpaket holen, entpacken und das Verzeichnis „DallasTemperature“ als Unterverzeichnis im Verzeichnis „libraries“ wegspeichern:
http://www.hacktronics.com/code/DallasTemperature.zip

4. folgendes Datenpaket holen, entpacken und das Verzeichnis „OneWire“ als Unterverzeichnis im Verzeichnis „libraries“ wegspeichern:
http://www.hacktronics.com/code/OneWire.zip

5. folgendes Datenpaket holen, entpacken und das Verzeichnis „RCSwitch“ als Unterverzeichnis im Verzeichnis „libraries“ wegspeichern:
https://rc-switch.googlecode.com/files/RCSwitch.zip

6. folgendes Datenpaket holen, entpacken und das Verzeichnis „Arduino-IRremote-master“ umbenennen und als Unterverzeichnis „IRremote“ im Verzeichnis „libraries“ wegspeichern:
https://github.com/shirriff/Arduino-IRremote/archive/master.zip

7. folgendes Datenpaket holen, entpacken und Verzeichnis“Time“ , „TimeAlarms“ und „DS1307RTC“ im Verzeichnis „libraries“ wegspeichern:
http://playground.arduino.cc/uploads/Code/Time.zip
Leider gibt es mit dieser library noch Compilierfehler. Deshalb mit einem Editor die Datei  DateStrings.cpp  im Time-Verzeichnis öffnen und den Programmcode mit dem verbesserten Programmcode aus dieser Datei ersetzen: https://github.com/dhiltonp/hexbright/blob/master/libraries/Time/DateStrings.cpp. Man kann auch die vorhandenen Datei DateStrings.cpp durch die verbesserte neue ersetzen.

8. folgendes Datenpaket holen, entpacken und Verzeichnis“LiquidCrystal“  im Verzeichnis „libraries“ wegspeichern:
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/LiquidCrystal_V1.2.1.zip
vorher ggf. „alte“ LiquidCrystal-library löschen.

9. folgendes Datenpaket holen, entpacken und daraus das Unterverzeichnis“SFE_BMP180″  im Verzeichnis „libraries“ wegspeichern:
https://github.com/sparkfun/BMP180_Breakout/archive/master.zip

10. ein Verzeichnis „c:\arduino_sketchbook einrichten und in der Arduino-Entwicklungsumgebung diesen Ordner unter Datei/Voreinstellungen als Speicherort für das Sketchbook festlegen. Natürlich kann man das Verzeichnis auch woanders ablegen.

So sieht das Verzeichnis „libraries“ nach dem Herunterladen aller Bibliotheken aus; gelb markiert sind die neuen hinzugefügten Libraries:
libraries_ordner

Damit ist die Entwicklungsumgebung vorbereitet und kann mit arduino.exe gestartet werden. Das Editor-Fenster geht auf und dann mit  „Copy/Paste“  das folgende Arduino_Sketch in den Editor laden und mit „speichern unter“ erst mal im vorher definierten Sketchbook als homeduino_xy sichern. :

 

//Versionsbezeichner "homeduino_21.ino / Stand: 2014.09.13"; 






 
#include <Ethernet.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RCSwitch.h>
#include <IRremote.h>
#include <Time.h>
#include <Wire.h>  
#include <LiquidCrystal_I2C.h>
#include <SFE_BMP180.h>
#include <EEPROM.h>
 
String ver = "homeduino_20.ino / Stand: 2014.09.13"; 
 


byte ip[] = { 192, 168, 178, 58 }; //das ist die IP des Arduino //<<user-eingabe<<
byte gateway[] = { 192, 168, 178, 1 }; //das ist die IP des Routers //<<user-eingabe<<
byte subnet[] = { 255, 255, 255, 0 }; //wie immer //<<user-eingabe<<
byte mac[] = { 0xDE, 0xAF, 0xEE, 0xEF, 0xEE, 0xDE }; //nur 1x im Netz //<<user-eingabe<<
EthernetServer server(80); 
 
byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU //<<user-eingabe<< 
EthernetClient client;
 

boolean reading = false;
boolean valid_command = false;
String command = String(200); 
String befehl = String(20);
String parameter = String(20);
String header = String(20);
 
String ip_adresse = String(15);
int param;
long param1;
int param2;
int param3;
String message = String(60);
boolean test = false;
unsigned long currentMillis;
unsigned long time;
unsigned long last_get;
unsigned long akt_zeit;
unsigned long next_update;
 
float tempNTC;
float B_wert = 3950; //aus dem Datenblatt des NTC //<<user-eingabe<<
float Tn = 298.15; 
float Rv = 10000; 
float Rn = 10000; 
float Rt ; 
 
int data[10];
int datum;
 
int PWM;
 
int onewire_pin;
float temp_tur;
 
int rf_key;
String rfkey;
 
RCSwitch mySwitch = RCSwitch();
 
boolean Ax_alt [6];
boolean ir_enable = 1; 
boolean rf_enable = 1; 
int schaltschwelle_high[]= {1023,1023,1023,510,510,510}; //schaltschwelle der Analogeingänge , //<<user-eingabe<<

int schaltschwelle_low[]= {0,0,0,100,100,100}; //schaltschwelle der Analogeingänge , //<<user-eingabe<<

 
int RECV_PIN = 2; 
IRrecv irrecv(RECV_PIN); 
IRsend irsend; 
decode_results results;
String code_type;
int ir_key;
String irkey;
int decod;
unsigned long val;
int bitss;
unsigned int address;
int rawl; 
String hersteller;

int codeType = -1; 
unsigned long codeValue; 
unsigned int rawCodes[RAWBUF]; 
int codeLen; 
int count;
int STATUS_PIN = 13;
int addr;
 
SFE_BMP180 pressure;
int altitude = 229.0; 
boolean lcd_text_anzeigen; 
 
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  
char status;
double T,P,p0,a;
 


void setup()
{ Serial.begin(9600); //Pins 10,11,12 & 13 fuer ethernet shield verwendet
 Ethernet.begin(mac, ip, gateway, subnet); 
 server.begin(); 
 ip_adresse = String(ip[0]) + "." + String(ip[1]) + "." +String(ip[2]) + "." + String(ip[3]);
 header = "arduino IP: " + ip_adresse + "\n\r";
 
 next_update = now() + 600; 
 last_get = now() +3;
 mySwitch.enableReceive(1); //receiver on interrupt 1 => that is pin D3
 
 if (ir_enable = true) {irrecv.enableIRIn();irrecv.blink13(true);pinMode(9, OUTPUT); 
 digitalWrite(9, HIGH);} 
 if (rf_enable = true) {mySwitch.enableReceive(1);} 
 
 lcd.begin(20,4);         
 lcd.backlight();
 }


void loop()
{ 
 command = ""; //String(100);
 EthernetClient client = server.available();
 if (client) 
 { 
 boolean currentLineIsBlank = true;
 while (client.connected())
 { if (client.available()) 
 { char c = client.read();
 if (reading && c == ' ') reading =false;
 if (c == '?') reading = true; 
 if (reading) 
 { 
 if (command.length() < 100) 
 { 
 command = command + c;
 }
 } 
 if (c == '\n' && currentLineIsBlank) break;
 if (c == '\n') 
 { currentLineIsBlank = true;} else if (c != '\r') 
 { currentLineIsBlank = false;}
 }
 }

pinMode(13, OUTPUT); 
digitalWrite(13, HIGH);
 


int colonPosition = command.indexOf(':');
befehl = command.substring(1,colonPosition);
command = command.substring((colonPosition+1)); 
 
client.print(header);
valid_command = false;

if (befehl == "setpin") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 pinMode(param, OUTPUT);
 digitalWrite(param, HIGH);
 client.print("Pin D" + parameter + " = 1 port is digital output E\n\r"); 
 }
}

if (befehl == "resetpin") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 pinMode(param, OUTPUT);
 digitalWrite(param, LOW);
 client.print("Pin D" + parameter + " = 0 port is digital output E\n\r"); 
 }
}

if (befehl == "digitalin") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 pinMode(param, INPUT);
 digitalWrite(param, HIGH);
 client.print("Pin D" + parameter + " = " + digitalRead(param) + " port is digital input E\n\r");
 }
}

if (befehl == "analogin") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 client.print("Pin A" + parameter + " = " + analogRead(param) + " port is analog input E\n\r");
 }
}

if (befehl == "pwm_out") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false;}; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 PWM = command.toInt();
 pinMode(param, OUTPUT);
 analogWrite(param, PWM); 
 client.print("PWM D" + parameter + " = " + PWM + "% duty cycle at output E\n\r");
 
}
 


if ((befehl == "ir_receive")&& (ir_enable == true)) 
 {valid_command = true; 
 decode_results results;
 irrecv.enableIRIn(); 
 unsigned long time_rf0 = millis();
 unsigned long time_rf1 = millis();
 
 while ((time_rf1 - time_rf0) < 3000)
 { time_rf1 = millis(); 
   if (irrecv.decode(&results))
        {dump(&results);
         client.print(hersteller );

         client.print("-code: ");
         client.print(val);
         client.print("  bits: "); 
         client.print(bitss);
         if ( address >0) {client.print(" opt.adress: ");
                           client.print(address);}
         client.print("   raw pulses: "); 
         client.print(rawl); 
         client.print("  0.5us-ticks\n\r");
         irrecv.resume(); 
        } 
 }
 client.print("end ir_receive :" + command + " \n\r"); 
 }


if (befehl == "ir_send") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 code_type = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));

 colonPosition = command.indexOf(':');
 parameter = command.substring(0,colonPosition);
 param1 = parameter.toInt(); 
 parameter = command.substring((colonPosition+1));
 param2 = parameter.toInt(); 
 
 if (code_type == "nec") {for (int i = 0; i < 1; i++) {
 irsend.sendNEC(param1, param2); 
 delay(40);}}
 
 if (code_type == "sony") {for (int i = 0; i < 3; i++) {
 irsend.sendSony(param1, param2); 
 delay(40);}} 
 
 if (code_type == "rc5") {for (int i = 0; i < 3; i++) {
 irsend.sendRC5(param1, param2); 
 delay(40);}} 
 
 if (code_type == "rc6") {for (int i = 0; i < 3; i++) {
 irsend.sendRC6(param1, param2); 
 delay(40);}} 
 
 client.print("ir_send mit Sendecode :" + command + " \n\r"); 
} 


if (befehl == "ir_rawstore")
 {valid_command = true; 
  colonPosition = command.indexOf(':');
  if (colonPosition > 2) {valid_command = false;}; 
  parameter = command.substring(0,colonPosition);
  param = parameter.toInt(); 
 
  decode_results results;
  irrecv.enableIRIn(); 
  unsigned long time_rf0 = millis();
  unsigned long time_rf1 = millis();
 
  while ((time_rf1 - time_rf0) < 3000)
    {time_rf1 = millis(); 
     if(irrecv.decode(&results))
       { digitalWrite(STATUS_PIN, HIGH);
         storeCode(&results);  

         addr = 200*param + 2*99;
         codeLen = 256* EEPROM.read(addr) + EEPROM.read(addr+1);
         int k = 1;
         for (int i = 1; i <= (codeLen); i++)//zurückspeichern aus EEPROM
           {int addr = 200*param + 2*(i-1);
            rawCodes[i - 1] = 256* EEPROM.read(addr) + EEPROM.read(addr+1);
            if (i % 2) {client.print(" m");} else {client.print(" s");}
            client.print(rawCodes[i - 1],DEC); 
            k= k+1;
            if (k>10) {k=1; client.print("\n\r");
           }
       }
     client.print("\n\r");
     if (codeLen > 98){client.print("zu grosse und fehlerhafte ");}
     client.print("Codelaenge : ");
     client.print(codeLen);
     client.print("\n\r");
 
     irrecv.resume(); 
     digitalWrite(STATUS_PIN, LOW);
    } 
 }
 client.print("end ir_rawstore auf Speicherplatz: " + parameter + " \n\r"); 
}


if (befehl == "ir_rawsend") 
 { valid_command = true; 
   colonPosition = command.indexOf(':');
   if (colonPosition > 2) {valid_command = false;}; 
   parameter = command.substring(0,colonPosition);
   param = parameter.toInt(); 
 
   addr = 200*param + 2*99;
   codeLen= 256* EEPROM.read(addr) + EEPROM.read(addr+1);
   int k = 1;
   for (int i = 1; i <= (codeLen); i++)//zurückspeichern aus EEPROM
     {addr = 200*param + 2*(i-1);
      rawCodes[i - 1] = 256* EEPROM.read(addr) + EEPROM.read(addr+1);
      if (i % 2) {client.print(" m");} else {client.print(" s");}
      client.print(rawCodes[i - 1],DEC); 
      k= k+1;
      if (k>10) {k=1; client.print("\n\r");}
     }
   client.print("\n\r");
   client.print("Codelaenge : ");
   client.print(codeLen);
   client.print("\n\r");
   irsend.sendRaw(rawCodes, codeLen, 38);
   client.print("ir_rawsend von Speicherplatz :" + parameter + " \n\r"); 
 }
 


if (befehl == "rf_send") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 colonPosition = command.indexOf(':');
 parameter = command.substring(0,colonPosition);
 param1 = parameter.toInt(); 
 parameter = command.substring((colonPosition+1));
 param2 = parameter.toInt(); 
 

 mySwitch.enableTransmit(param);






 
 mySwitch.send(param1, param2);
 client.print("rf_send mit Sendecode :" + command + " \n\r"); 
} 


if ((befehl == "rf_receive")&& (rf_enable == true)) 
 { valid_command = true; 

 unsigned long time_rf0 = millis();
 unsigned long time_rf1 = millis();
 while ((time_rf1 - time_rf0) < 3000)
 { time_rf1 = millis();
 if (mySwitch.available()) 
 { int value = mySwitch.getReceivedValue();
 if (value == 0) {client.print("Unknown encoding");} 
 else 
 {client.print("Pin D3 received : ");
 client.print (mySwitch.getReceivedValue() );
 client.print (" / ");
 client.print( mySwitch.getReceivedBitlength() );
 client.print("bit Protocol: ");
 client.println( mySwitch.getReceivedProtocol() + " \n\r" );
 }
 mySwitch.resetAvailable();
 }
 } 
 client.print("end rf_receive :" + command + " \n\r"); 
 } 

if (befehl == "onewire") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 onewire_pin = parameter.toInt();



float tempC[10]; 
 
OneWire oneWire(onewire_pin); 
DallasTemperature sensors(&oneWire);
DeviceAddress TempSensor[] = 
{ 
 { 0x28, 0x37, 0x35, 0xB6, 0x05, 0x00, 0x00, 0x8D }, //<<user-eingabe<<
 { 0x28, 0xA5, 0x0A, 0xDD, 0x05, 0x00, 0x00, 0xBD }, //<<user-eingabe<< 
 { 0x28, 0x31, 0x60, 0xDD, 0x05, 0x00, 0x00, 0x7C }, //<<user-eingabe<<
 { 0x28, 0xA2, 0x4B, 0xB5, 0x05, 0x00, 0x00, 0x90 }, //<<user-eingabe<<
 { 0x10, 0xC7, 0xBA, 0xDD, 0x01, 0x08, 0x00, 0x52 }, //<<user-eingabe<<
 { 0x10, 0x8E, 0xB8, 0xDD, 0x01, 0x08, 0x00, 0x32 }, //<<user-eingabe<<
 { 0x10, 0xC7, 0xBA, 0xDD, 0x01, 0x08, 0x00, 0x52 }, //<<user-eingabe<<
 { 0x10, 0x8E, 0xB8, 0xDD, 0x01, 0x08, 0x00, 0x32 }, //<<user-eingabe<<
 { 0x10, 0xC7, 0xBA, 0xDD, 0x01, 0x08, 0x00, 0x52 }, //<<user-eingabe<<
 { 0x10, 0x8E, 0xB8, 0xDD, 0x01, 0x08, 0x00, 0x32 }, //<<user-eingabe<<
};

 sensors.begin();

 sensors.setResolution(TempSensor[0], 10);
 sensors.setResolution(TempSensor[1], 10);
 sensors.setResolution(TempSensor[2], 10);
 sensors.setResolution(TempSensor[3], 10);
 sensors.setResolution(TempSensor[4], 10);
 sensors.setResolution(TempSensor[5], 10); 
 sensors.setResolution(TempSensor[6], 10);
 sensors.setResolution(TempSensor[7], 10);
 sensors.setResolution(TempSensor[8], 10);
 sensors.setResolution(TempSensor[9], 10);
 

 while (command.length() > 1 ) 
 { colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 sensors.requestTemperatures();
 tempC[param] = sensors.getTempC(TempSensor[param]);
 client.print("onewire T" + parameter + " = " + tempC[param] + " Celsius / pin D" + onewire_pin + " as input \n\r");
 } 
} 


if (befehl == "1wire") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 
 OneWire ds(param); 
 #define DS18S20_ID 0x10
 #define DS18B20_ID 0x28 
 byte i;
 byte present = 0;
 byte data[12];
 byte addr[8];
 if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000; } 
 if (OneWire::crc8( addr, 7) != addr[7]) {temp_tur = -1000; }
 if (addr[0] != DS18S20_ID && addr[0] != DS18B20_ID) {temp_tur = -1000;}
 if (temp_tur > -1000) 
 { ds.reset(); 
 ds.select(addr); 
 ds.write(0x44, 1); 
 delay(850); 
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); 
 for ( i = 0; i < 9; i++) { data[i] = ds.read(); } 
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; 

 }
 client.print("1wire T" + parameter + " = " + temp_tur + " Celsius / pin D" + param + " as input \n\r");
 }
}


if (befehl == "1wire_address") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 
 OneWire ds(param);
 byte address[8];
 int i=0;
 byte ok = 0, tmp = 0;
 client.print("--Suche gestartet--\n\r");
 while (ds.search(address))
 {tmp = 0; 
 if (address[0] == 0x10) { client.print("Device is a DS18S20 : "); tmp = 1;} 
 else { if (address[0] == 0x28) { client.print("Device is a DS18B20 : "); tmp = 1; } 
 }
 if (tmp == 1) 
 {if (OneWire::crc8(address, 7) != address[7]) { client.print("but it doesn't have a valid CRC!\n\r"); }
 else { for (i=0;i<8;i++) 
 { 
 client.print("0x");
 if (address[i] < 9) { client.print("0");}
 client.print(address[i],HEX);
 if (i<7) { client.print(", ");}
 }
 client.print("\n\r");
 ok = 1;
 }
 }
 }
 if (ok == 0){client.print("Keine Sensoren gefunden\n\r"); }
 client.print("--Suche beendet--\n\r");
 }
} 

if (befehl == "w_data") 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 datum = command.toInt();
 data[param] = datum;
 client.print("w_data" + parameter + " = " + datum + " set w_data E\n\r");
}

if (befehl == "r_data") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false;break;}; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 client.print("r_data" + parameter + " = " + data[param]+ " Wert der Variablen E\n\r");
 }
}

if (befehl == "dist") // messung mit ultraschallsensor an "beliebigen pin
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt(); 
 
 long duration, cm; 
 pinMode(param, OUTPUT);
 digitalWrite(param, LOW);
 delayMicroseconds(2);
 digitalWrite(param, HIGH);
 delayMicroseconds(5);
 digitalWrite(param, LOW);
 pinMode(param, INPUT);
 duration = pulseIn(param, HIGH);
 cm = duration /29/2; 
 delay(100);
 
 client.print("ultrasonic an Pin D" + parameter + " = " + cm + " cm E\n\r");
 }
}

if (befehl == "w_msg") 
{ message = command;
 valid_command = true; 
 client.print("w_msg :" + message + "\n\r");
} 

if (befehl == "r_msg") 
{ valid_command = true; 
 client.print("r_msg :" + message + "\n\r");
} 

if (befehl == "ntc_in") 
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; 
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 param = parameter.toInt();
 
 Rt = Rv/((1024.0/analogRead(param))- 1.0);
 tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn +25.0 ;
 client.print("NTC an A" + parameter + " = " + tempNTC + " gradCelsius E\n\r");
 } 
} 

if (befehl == "set_time")
{ valid_command = false; 
 if (command.length() == 0) {time = now();parameter = String(time); valid_command = true;}
 if (command.length() == 11) 
 {valid_command = true;
 parameter = command.substring(0,10);
 time = parameter.toInt(); 
 setTime(time);
 time = now();
 parameter = String(time);}
 client.print("homeduino zeit /s ist: " + parameter + " \n\r");
} 
 



if (befehl == "barometer") 
{ valid_command = true; 
  colonPosition = command.indexOf(':');
  if (colonPosition > 4) {valid_command = false;}; 
   parameter = command.substring(0,colonPosition);
   param = parameter.toInt(); 
 
  if (pressure.begin()) 
     { //client.print("BMP180 gestartet\n\r");
      delay(1000);
      char status;
      double T,P,p0,a;



 
  client.print("Meereshoehe NN : ");
  client.print(parameter);
  client.print(" m\n\r"); 
 
  status = pressure.startTemperature();
  if (status != 0)
  {

    delay(status);
 



    status = pressure.getTemperature(T);
    if (status != 0)
    { 
      client.print("Temperatur     : ");
      client.print(T,1);
      client.print(" gradC \n\r");  
 




      status = pressure.startPressure(3);
      if (status != 0)
      { 
        delay(status);
 





 
        status = pressure.getPressure(P,T);
        if (status != 0)
        { 
          client.print("Druck absolut  : ");
          client.print(P,2);
          client.print(" mb\n\r"); 
 





 
          p0 = pressure.sealevel(P,param); 
 
          client.print("Druck bei NN   : ");
          client.print(p0,2);
          client.print(" mb\n\r"); 
 
        }
        else {client.print("error");}
      }
      else {client.print("error"); }
    }
    else {client.print("error"); }
  }
  else {client.print("error"); }
 
 }  
     else
       {client.print("BMP180 nicht da\n\r");} 
} 



if (befehl == "display") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; }; 
 if (command.length() < 2) {lcd.clear();} 
 parameter = command.substring(0,colonPosition);
 param2 = parameter.toInt(); 
 command = command.substring((colonPosition+1));
 colonPosition = command.indexOf(':');
 if (colonPosition > 1) {valid_command = false; }; 
 parameter = command.substring(0,colonPosition);
 param3 = parameter.toInt(); 
 command = command.substring((colonPosition+1));
 command.replace("%20", " ");


 int m = 0; 
 String zeilennummer;
 while (command.length() > 20)
 {String zeile = command.substring(0,20);
  command = command.substring(20);
  lcd.setCursor(0,(param3 + m));
  zeilennummer = String(param3 + m);
  lcd.print(zeile);
  client.print("lcd_display zeile " + zeilennummer + ": " + zeile + " \n\r");
  m = m+1;
  param2 = 0;
 }
 zeilennummer = String(param3 + m);
 lcd.setCursor(param2,param3 + m);
 lcd.print(command);
 client.print("lcd_display zeile " + zeilennummer + ": " + command + " \n\r"); 
 
} 

if (befehl == "help") 
{ valid_command = true; 
 client.print("IP-Adresse/?Befehl:Param1:Param2: ...\n\r");
 client.print( 
   ip_adresse + "/?setpin:4:5:               >> Pins D4,D5 auf HIGH setzen und Pins als Output setzen \n\r" 
 + ip_adresse + "/?resetpin:7:4:8:           >> Pins D7,D4,D8 auf LOW setzen und Pinsals Output setzen \n\r" 
 + ip_adresse + "/?digitalin:5:4:            >> Pins D5,D4 lesen und Pins als Input setzen \n\r"
 + ip_adresse + "/?analogin:0:5:             >> Pins A0,A5 lesen und Pins auf Analoginput setzen \n\r");
 client.print( 
   ip_adresse + "/?pwm_out:4:96:             >> PWM-Signal mit Tastverhältnis 96% an Digitalpin D4 ausgeben \n\r"
 + ip_adresse + "/?onewire:6:0:5:1:          >> An D6 die 1-Wire Sensoren Nr.0, Nr.5 und Nr.0 einlesen \n\r"
 + ip_adresse + "/?1wire:7:                  >> An D7 den 1-Wire Sensor einlesen \n\r"
 + ip_adresse + "/?1wire_address:8:          >> An D8 alle Adressen der 1-Wire Sensoren auslesen \n\r");
 client.print( 
   ip_adresse + "/?rf_send:4:4523029:24:     >> An D4 das RF-Telegramm 4523029 mit 24bit-Kodierung ausgeben \n\r"
 + ip_adresse + "/?rf_receive:               >> An D3 auf rf-Signal 3s warten und RF-Telegramm anzeigen \n\r"
 + ip_adresse + "/?ir_send:nec:1086136543:32 >> An D9 das IR-Telegramm 1086136543 mit 36 bit laenge ausgeben \n\r"
 + ip_adresse + "/?ir_receive:               >> An D2 auf IR-Signal 3s warten und IR-Telegramm anzeigen \n\r");
 client.print( 
   ip_adresse + "/?ir_rawstore:5:            >> 3sec empfangen und IR-Signal auf Speicherplatz 5 wegspeichern\n\r"
 + ip_adresse + "/?ir_rawsend:5:             >> sendet IR-Signal von Speicherplatz 5 \n\r"
 + ip_adresse + "/? \n\r"
 + ip_adresse + "/? \n\r");
 client.print( 
   ip_adresse + "/?w_data:0:1425:            >> Homeduino-Integervariablen \"w_data[0]\" mit Wert 1525 setzen \n\r"
 + ip_adresse + "/?r_data:4:5:               >> Homeduino-Integervariablen \"w_data[4]\" und \"w_data[5]\" auslesen \n\r"
 + ip_adresse + "/?dist:6:                   >> Entfernung in cm mit Ultraschallsensor an Pin D6 einlesen \n\r"
 + ip_adresse + "/?w_msg:abcdef              >> \"abcdef\" in Homeduino-String \"message\" speichern \n\r");
 client.print( 
   ip_adresse + "/?set_time:174393838:       >> Homeduino-Zeit (Sekunden seit 1.1.1970) setzen/auslesen \n\r"
 + ip_adresse + "/?display:0:3:meldung       >> zeigt auf Display in Position 0 in Zeile 3 den Text \"meldung\" \n\r" 
 + ip_adresse + "/?display:                  >> loescht Display komplett\n\r" 
 + ip_adresse + "/?barometer:229             >> zeigt Daten vom Barometer-Sensor BMP180 bezogen auf Meereshoehe 229m >> \n\r"); 
 client.print( 
   ip_adresse + "/?r_msg:                    >> Homeduino-String \"message\" auslesen \n\r"
 + ip_adresse + "/?ntc_in:0:5:               >> NTC-Temperaturen von Pin A0 und A5 lesen \n\r" 
 + ip_adresse + "/?help:                     >> Anzeige der Befehlsliste \n\r" 
 + ip_adresse + "/?ver:                      >> Anzeige der Firmware-Version \n\r");
 
 }

if (befehl == "ver") 
{ valid_command = true; 
 client.print(ver + "\n\r");
} 

if (valid_command == false) {client.print("no valid command !\n\r");}

client.println(); 
 


 client.stop(); 
 }

pinMode(13, OUTPUT); 
digitalWrite(13, LOW);




if (ir_enable == true) 
 {if (irrecv.decode(&results)) 
 { dump(&results); 
 ir_decode(); 
 irrecv.resume();
 Serial.println(" ir_key : " + irkey ); 
 if (ir_key < 255 )
 {if (client.connect(ccu, 8181)) 
 { String befehl = "GET /xy.exe?antwort=dom.GetObject('homeduino_ir').State(" + irkey + ")";
 client.println(befehl);
 client.println();
 client.stop();
 }
 } 
 }
 }



if (rf_enable == true) 
 { if (mySwitch.available()) 
 { int value = mySwitch.getReceivedValue();
 if (value == 0) {Serial.print("Unknown encoding");} 
 else { Serial.print("Pin D3 received Code : ");
 Serial.print (mySwitch.getReceivedValue() );
 Serial.print (" / ");
 Serial.print( mySwitch.getReceivedBitlength() );
 Serial.print("bit Protocol: ");
 Serial.println( mySwitch.getReceivedProtocol() + " \n\r" );
 rf_decode(); 
 mySwitch.resetAvailable();
 Serial.println(" rf_key : " + rfkey ); 
 if (rf_key < 255 )
 {if (client.connect(ccu, 8181)) 
 { String befehl = "GET /xy.exe?antwort=dom.GetObject('homeduino_rf').State(" + rfkey + ")";
 client.println(befehl);
 client.println();
 client.stop();
 }
 }
 }
 }
 } 






int i = 0;
int messwert;
String kanal;
String logikpegel;
String befehl;
akt_zeit = now();
 
if (akt_zeit > next_update)
 { next_update = next_update +600; 
 while (i < 6) {Ax_alt[i] = !Ax_alt[i]; i=i+1; } 
 i = 0;
 }
 
if (akt_zeit > (last_get+5)) 
{
 if (client.connect(ccu, 8181)) 
 { while (i < 6) 
 { messwert = analogRead(i); 
 if ((messwert < schaltschwelle_low[i]) && (Ax_alt[i] == 1 )) 
 { 
 Ax_alt[i] = 0;
 logikpegel = "0";
 kanal = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('homeduino_a" + kanal +"').State(" + logikpegel + ")"; 
 last_get = now(); 
 client.println(befehl);
 client.println();
 Serial.println("kanal: " + kanal + " logikpegel : " + logikpegel + "\n\r" );
 }
 if ((messwert > schaltschwelle_high[i])&& (Ax_alt[i] == 0 )) 
 { 
 Ax_alt[i] = 1;
 logikpegel = "1";
 kanal = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('homeduino_a" + kanal +"').State(" + logikpegel + ")"; 
 last_get = now(); 
 client.println(befehl);
 client.println();
 Serial.println("kanal: " + kanal + " logikpegel : " + logikpegel + "\n\r" );
 } 
 
 i = i+1; 
 } 
 client.stop(); 
 }
}

}

 
 
 
 

 



void rf_decode() 
{switch(mySwitch.getReceivedValue())
 {
 case 4523029: rf_key = 1; break;
 
 case 4523028: rf_key = 2; break;
 
 case 4539413: rf_key = 3; break;
 
 case 4539412: rf_key = 4; break;
 
 case 4527125: rf_key = 5; break;
 
 case 4527124: rf_key = 6; break;
 
 case 4543509: rf_key = 7; break;
 
 case 4543508: rf_key = 8; break;
 
 case 87296: rf_key = 9; break;
 
 case 12670208: rf_key = 10; break;
 

 
 default: rf_key = 255;
 }
 rfkey = String(rf_key);
 
} 
 



void ir_decode() 
{switch(results.value)
 {
 case 1086165103: ir_key = 1; break;
 
 case 1086128383: ir_key = 2; break;
 
 case 1086161023: ir_key = 3; break;
 
 case 1086144703: ir_key = 4; break;
 
 case 1086177343: ir_key = 5; break;
 
 case 1086136543: ir_key = 6; break;
 
 case 1086169183: ir_key = 7; break;
 
 case 16779273: ir_key = 8; break;
 
 case 16812169: ir_key = 9; break;
 
 case 33718399: ir_key = 10; break;
 

 
 default: ir_key = 255;
 }
 irkey = String(ir_key);
 
}





void dump(void *v) {
decode_results *results = (decode_results *)v;

 

val =(results->value);
bitss = (results->bits);
address = 0;
rawl = (results->rawlen);
decod =(results->decode_type);
switch(decod)
 { case 1: hersteller = "nec"; break;
   case 2: hersteller = "sony"; break;
   case 3: hersteller = "rc5"; break;
   case 4: hersteller = "rc6"; break;
   case 5: hersteller = "dish"; break;
   case 6: hersteller = "sharp"; break;
   case 7: hersteller = "panasonic"; address =(results->panasonicAddress) ;break;
   case 8: hersteller = "jvc"; break;
   case 9: hersteller = "sanyo"; break;
   case 10: hersteller = "mitsubishi"; break;
   case 11: hersteller = "samsung"; break;
   case 12: hersteller = "lg"; break;
   case -1: hersteller = "unknown"; break;
   default: ir_key = 255;
 }
 }
 


void storeCode(decode_results *results)
{count = results->rawlen;
 codeLen = results->rawlen - 1;
 if (codeLen > 98) {codeLen =99;} 


 int k = 1;
 int addr;
 for (int i = 1; i <= codeLen; i++) 
 { if (i % 2) {rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS; Serial.print(" m");}
     else {rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS; Serial.print(" s");}
   Serial.print(rawCodes[i - 1], DEC);
 

   addr = 200*param + 2*(i-1);
   val = rawCodes[i - 1]/256;
   EEPROM.write(addr, val);  
   EEPROM.write(addr+1, rawCodes[i - 1] - val);  
   k= k+1;
   if (k>10) {k=1; Serial.print("\n\r");}
 }

   addr = 200*param + 2*99;
   val = codeLen/256;
   EEPROM.write(addr, val);  
   EEPROM.write(addr+1, codeLen - val);  
   Serial.print("\n\r");
   Serial.print("Codelaenge : ");
   Serial.print(codeLen);
   Serial.print("\n\r");
}

 

In der Arduino-Entwicklungsumgebung das verwendete Board MEGA2560, den Prozessor ATMega1560 und den verwendeten seriellen Port einstellen.

Dann zuerst mal schauen, ob jetzt die Homeduino-Software fehlerfrei kompiliert wird. (mit dem o.k-Haken-Button !). Wenn das fehlerfrei erfolgt, dann ist die Entwicklungsumgebung schon mal in Ordnung :))

Dann in diesem  Homeduino-Sketch die gewünschte feste IP-Adresse im Adressraum des eigenen Routers editieren. Darüberhinaus die Parameter in den Zeilen, die mit  „<<user-eingabe<<“ gekennzeichnet sind, nach den eigenen Bedürfnissen einstellen. Weitere Erläuterungen hierzu weiter unten!

Jetzt noch diesen Sketch sichern als „homeduino_x“ im Ordner „c:\arduino_sketchbook wegspeichern.

Dann mit dem Button „->“ das Programm übersetzen und  in den Homeduino laden.
(Wenn keine Kommunikation über das USB-Kabel erfolgt, dann ggf. über „Werkzeug/Port“ den richtigen seriellen Port des PC einstellen. )
Damit ist der Homeduino programmiert und kann über das Ethernet abgefragt oder gesteuert werden.

Zur ersten Funktionsprüfung gibt man am besten in der Adressleiste des Browsers den help-Befehl ein :

<arduino_IP>/?help:         ( in meiner Umgebung heißt der Befehl: 192.168.178.58/?help:   )

und erhält dann die oben bereits gezeigte Befehlsliste.

Das Programm ist noch in der Entwicklung und wird laufend verbessert und erweitert.
Bitte auf die Versionsnummer und Datum achten!

 

6  Integration in die Hausautomation
Das folgende Bild zeigt die typische Beschaltung des I/O-Shields bei Realisierung von digitalen Ein- und Ausgängen. Die Ausgänge D2 bis D9 sind direkt die Ausgänge des Mikroprozessors und sind dementsprechend wenig belastbar. Deshalb sind 8 leistungsfähige MOSFET-Treiber auf dem I/O-Shield untergebracht, welche  auch „stromhungrige“ Lasten (nach Masse) schalten können. Externe Versorgungsspannungen bis 24V sind dafür verwendbar, um entsprechende Relais, Lampen, LEDs etc. schalten zu können. Die zugehörigen Ausgänge auf dem I/O-Shield sind die mit einem Stern gekennzeichneten Pins D2* bis D9*.

Werden Die Pins D2 bis D9 als Eingänge verwendet, um beispielsweise Schaltersensoren abzufragen, dann sind ggf. mit den Jumpern JP3 entsprechende Pullup-Widerstände (4k7) einzuschalten. Folie1
6.1 Digitale Ausgänge schalten
Das Ein- und Ausschalten der digitalen Ports D2 bis D9 erfolgt per Browser mit den Befehlen …

<ip>/?setpin:2:5:6:8:          >> setzt Pins D2, D5, D6; D8  auf HIGH
<ip>/?resetpin:2:5:6:8:     >> setzt Pins D2, D5, D6; D8  auf LOW

und wird im Browser mit einer entsprechenden Rückmeldung bestätigt.

Aus der Homematic heraus kann die gleiche Aktion mit folgenden HM-Skripten erfolgen: Dazu ist vorher die logische Systemvariable homeduino_fehler zu definieren, welche im Skript gesetzt wird und anzeigt, ob eine erfolgreiche Kommunikation mit dem Homeduino erfolgt.

Mit diesem Skript werden zum Beispiel alle Pins D2 bis D9 auf 1 gesetzt:

var url = "192.168.178.58/?setpin:2:3:4:5:6:7:8:9:";
!Stand 17.07.2014 ##############################
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
!WriteLine(arduino_xml);
integer laenge = arduino_xml.Length();
boolean status = 0;
if (laenge == 0) {dom.GetObject("homeduino_fehler").State(true);quit;} !beenden , wenn laenge =0
dom.GetObject("homeduino_fehler").State(false);

 

… und hiermit alle Pins D2 bis D9  auf 0 gesetzt:

var url = "192.168.178.58/?resetpin:2:3:4:5:6:7:8:9:";
!Stand 17.07.2014 ##############################
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
!WriteLine(arduino_xml);
integer laenge = arduino_xml.Length();
boolean status = 0;
if (laenge == 0) {dom.GetObject("homeduino_fehler").State(true);quit;} !beenden , wenn laenge =0
dom.GetObject("homeduino_fehler").State(false);

Das folgende  einfache WebUI-Testprogramm soll die Arbeitsweise beim Setzen und Rücksetzen der Pins verdeutlichen. Im Programm werden beispielsweise alle 2 min die beiden Skripte zeitversetzt aufgerufen, welche die Pins dann einschalten und nach 15 sec wieder  ausschalten.

 

Webui_toggle

 

6.2 Digitale Eingange abfragen
Das Einlesen  der digitalen Ports D2 bis D9 erfolgt per Browser mit dem Befehl …
<ip>/?readpin:2:5:6:8:          >> liest  Pins D2, D5, D6; D8  und zeigt den Status im Browser mit einer entsprechenden Meldung.

Für das Einlesen in die Homematic sind vorher entsprechende boolsche Systemvariable für jeden abzufragenden Port anzulegen. Im folgenden Beispiel sind dies …
homeduino_D6; homeduino_D7; homeduino_D8; homeduino_D9; und natürlich  homeduino_fehler

 

var url = "192.168.178.58/?digitalin:6:7:8:9:";
!Stand 17.07.2014 ###################################
!hier ist die Abfrage mit system.Exec
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
!WriteLine(arduino_xml);
 
integer laenge = arduino_xml.Length();
if (laenge == 0) {dom.GetObject("homeduino_fehler").State(true);quit;} !beenden , wenn laenge =0
dom.GetObject("homeduino_fehler").State(false);
 
while (laenge >38)
 { integer wort_position = arduino_xml.Find("D");
    arduino_xml = arduino_xml.Substr(wort_position+1, (laenge - wort_position-1));
    laenge = arduino_xml.Length();
    string daten = arduino_xml.Substr(0, 6);
    !WriteLine("daten:" + daten);
    string pin = arduino_xml.Substr(0,2);
    integer pinn = pin.ToInteger();
    pin = pinn.ToString();
    !WriteLine("pin:" + pin);
    string daten = arduino_xml.Substr(4, 2);
    !WriteLine("daten:" + daten);
    integer pegel = daten.ToInteger();
    boolean status = false;
    if (pegel > 0) {status = true;}
    pin = "homeduino_D" +pin;
    !WriteLine(pin);
    !WriteLine(status);
    dom.GetObject(pin).State(status);
 }

 

6.3 Analoge Eingänge abfragen
Mit dem I/O-Shield können die verfügbaren sechs Analogeingänge des Homeduinos in drei analogen Betriebsarten verwendet werden. Die Einstellung erfolgt mit den Jumpern JP1 und JP2.
– kein Jumper gesetzt: Eingangsspannungsbereich ist 0 (000)  bis +5V (1023)
– JP1 gesetzt: 10KOhm-Pullup-Widerstand eingeschaltetet, so dass entsprechende Sensoren z.B. NTCs  verwendet werden können: Messbereich 0 bis +5V
– JP2 gesetzt: Eingangsspannungsbereich ist 0 (000)  bis +10V (1023)

Folie2

 

Das Einlesen  der analogen Eingänge A0  bis A5  erfolgt per Browser mit dem Befehl …
<ip>/?analogin:0:4:5:          >> liest  Pins A0;A4;A5  und zeigt den Wert  im Browser mit einer entsprechenden Meldung.

Für das Einlesen in die Homematic sind vorher entsprechende  Systemvariable vom Typ Zahl für jeden abzufragenden Eingang  anzulegen. Im folgenden Beispiel sind dies …
homeduino_A0; homeduino_A4; homeduino_A5;

var url = "192.168.178.58/?analogin:0:4:5:";
!###################################
!hier ist die Abfrage mit system.Exec
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
!WriteLine(arduino_xml);
 
integer laenge = arduino_xml.Length();
if (laenge == 0) {quit;}                !beenden , wenn laenge =0
while (laenge >38)
 { integer wort_position = arduino_xml.Find("A");
    arduino_xml = arduino_xml.Substr(wort_position+1, (laenge - wort_position-1));
    laenge = arduino_xml.Length();
    string daten = arduino_xml.Substr(0, 6);
    !WriteLine("daten:" + daten);
    string pin = arduino_xml.Substr(0,2);
    integer pinn = pin.ToInteger();
    pin = pinn.ToString();
    !WriteLine("pin:" + pin);
    string daten = arduino_xml.Substr(4, 4);
    !WriteLine("daten:" + daten);
    integer pegel = daten.ToInteger();
    if (pegel >999 ) {pegel  = 999;}
    pin = "homeduino_A" +pin;
    !WriteLine(pin);
    !WriteLine(pegel);
    dom.GetObject(pin).State(pegel);
 }

 

6.4 Analoge Eingänge mit einstellbarer Triggerschwelle

Für die Erkennung von wichtigen Ereignissen wie Rauchmeldungen oder Alarmmeldungen kann man eine zyklische Abfrage (z.B. jede Minute) durch die Homematic vergessen, weil die Reaktion sofort erfolgen muß. Deshalb sind schnelle Trigger- und Auslösemöglichkeiten extrem wichtig.
Beim Homeduino wurden deshalb für jeden analogen Eingang individell einstellbare HIGH- und LOW-Triggerschwellen programmiert, die bei Über- oder Unterschreiten per Direktzugriff die für jeden Analogeingang korrespondierende Systemvariable in der Homematic sofort setzt oder rücksetzt. Das hat riesige Vorteile , wenn man zum Beispiel analoge Sensoren hat, die bei Erreichen bestimmter Werte sofort eine Reaktion auslösen sollen. Ein analoger Regenmelder  oder  ein Rauchmelder wären solche Geräte.

Die Einstellung der Schaltschwellen kann nicht per Browserbefehl erfolgen , sondern im Homeduino Sketch.  Dazu wird das folgende Integer-Array entsprechend mit Werten eingestellt: (hier der betreffende Auszug aus dem Homeduino Sketch)

int schaltschwelle_high[]= {250,1023,1023,1023,1023,510};                     

int schaltschwelle_low[]= {200,0,0,0,0,100};                                               

In dem Beispiel sind die Triggerschwellen für den Analogeingang AD0 auf die Werte   200 (LOW) und 250 (HIGH) eingestellt.  Das heißt, dass bei Eingangswerten kleiner 200 das Triggersignal LOW ist und bei Analogwerten größer 250 entsprechend HIGH ist. Die Analogeingänge 1 bis 4 haben in dem Besipiel mit den Werten 0 und 1023 die Triggerfunktion ausgeschaltet, weil das Analogsignal ja nicht kleiner als 0  und nicht größer als 1023 wird. Der Analogeingang AD5 hat die Triggerschwellen 100 bzw. 510.

Aber wie kommt nun das Triggersignal in die Homematic ??

Ganz einfach! Es werden nur für die Analogeingänge, welche die Triggerfunktionalität bekommen sollen, einfache logische Systemvariablen angelegt. Diese müssen die Namen haben  homeduino_a0  bis  homeduino_a5.
Ohne irgendwelche zusätzlichen Skripte werden diese Systemvariablen dann automatisch und sofort gesetzt oder zurückgesetzt, wenn die entsprechenden Triggerschwellen über- oder unterschritten werden.

Damit kann man nun nahezu verzugsfrei irgendwelche Aktoren schalten, wenn an den analogen Eingängen die Triggerschwellen überschritten werden. Hier ein einfaches Programm, das eine Lampe mit dem analogen Signal am Analogeingang A1 ein- oder ausschaltet:

WebUI_trigger


6.5 Analoges PWM-Signal ausgeben

Für manche Anwendungen benötigt man ein pulsweitenmoduliertes Signal (PWM) oder analoge Spannungen . Die Generierung von solchen PWM-Signalen ist mit demHomeduino sehr einfach möglich. An den digitalen Ausgängen kann das PWM-Signal abgefgriffen werden, um beispielsweise angeschlossene LEDs oder Lampen zu dimmen. Aber man kann mit diesem Signal auch variable Gleichpannungen erzeugen. Dazu ist ein einfacher geeignet dimensionierter Tiefpass (RC-Glied) notwendig, womit man eine analoge Ausgangsspannung von 0 bis 5V erzeugen kann. Abhängig von der Auslegung des RC-Gliedes ist ein hochohmiger nachfolgender Messverstärker zur Entkopplung notwendig.

Direkt mit dem Pulsweitensignal (PWM) lassen sich  Lampen oder LEDs modulieren bzw. dimmen. Die PWM-Frequenz ist etwa 500Hz!

Folie3

6.6 Temperaturmessung mit NTC
Eine Temperaturmessung mit einem Thermistor oder NTC-Widerstanssensor ist besonders einfach, weil keinerlei Zusatzbauteile in Verbindung mit dem I/O-Shield benötigt werden. Der Sensor sollte ein 10 kOhm-Typ sein. In Kombination mit dem mittels Jumper JP1 zugeschalteten Vorwiderstand von ebenfalls 10KOhm entsteht ein Spannungsteiler, dessen Spannung einem analogen Eingang zugeführt wird.

Die Berechnung der Temperatur in °C erfolgt im Homeduino mit der exponentellen Widerstandskurve des NTC-Widerstandes. Die dabei verwendeten Kennwerte und Rechenfunktionen sind dem zugehörigen Programmteil des Homeduino-Sketch  zu entnehmen. Für die typischen Standard-NTC-Sensoren sind meistens  keine Anpassungen notwendig.

Die verwendete Berechnungsformel ist :   tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn ;  mit   B_wert = 3950;

Folie12

Das Einlesen  der Temperaturen   erfolgt per Browser mit dem Befehl …
<ip>/?ntc_in:4:5:          >> liest  Temperaturen der NTCs an den Pins A4* und A5*  und zeigt den Temperaturwert Wert  im Browser mit einer entsprechenden Meldung.

Für das Einlesen in die Homematic sind vorher entsprechende  Systemvariable vom Typ Zahl für jeden abzufragenden Eingang  anzulegen. Im folgenden Beispiel sind dies …
homeduino_A4; homeduino_A5;

 

var url = "192.168.178.58/?ntc_in:4:5:";
!###################################
!hier ist die Abfrage mit system.Exec
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
!WriteLine(arduino_xml);
 
integer laenge = arduino_xml.Length();
if (laenge == 0) {quit;}                !beenden , wenn laenge =0
while (laenge >38)
 { integer wort_position = arduino_xml.Find("A");
    arduino_xml = arduino_xml.Substr(wort_position+1, (laenge - wort_position-1));
    laenge = arduino_xml.Length();
    string daten = arduino_xml.Substr(0, 6);
    !WriteLine("daten:" + daten);
    string pin = arduino_xml.Substr(0,2);
    integer pinn = pin.ToInteger();
    pin = pinn.ToString();
    !WriteLine("pin:" + pin);
    string daten = arduino_xml.Substr(4, 5);
    !WriteLine("daten:" + daten);
    integer pegel = daten.ToFloat();
 
    pin = "homeduino_A" +pin;
    !WriteLine(pin);
    !WriteLine(pegel);
    dom.GetObject(pin).State(pegel);
 }

 

6.7 Temperaturmessung mit 1Wire-Sensoren DS 18B20
Die 1-Wire-Sensoren von Dallas DS18B20 sind ideal für die Temperaturmessung, weil sie bereits kalibriert sind und eine digitale Temperaturinformation abgeben. Sie können einzeln an einen beliebigen digitalen Eingang geschaltet werden oder aber auch zu Gruppen bis 20(?) Sensoren parallelgeschaltet. Hierzu gibt es im Internet eine Vielzahl an Informationen, die hier aber nicht nochmal dargestellt werden müssen.  Erfahrungsmässig ist ein dreipoliger Anschluss der Sensoren (+5V, Masse, Signal) oft robuster und weniger störanfällig, als eine zweiadrige Sensorkopplung. Der  zweiadrige Betrieb ( plus und Masse zusammen geschaltetet)  funktioniert aber bei nicht allzu langen Leitungen auch ganz gut.  Die Sensoren können beliebig an alle verfügbaren  digitalen Ports D2 bis D9 angeschlossen werden.

Folie7

Die Software erkennt in dieser Betriebsart bei Abfrage mit dem Browser automatisch die Sensoradresse und gibt direkt den Temperaturwert aus. Ein Ermittlung der individuellen Sensoradresse ist in diesem Fall nicht notwendig. Wichtig ist das Zuschalten des 4k7-Pullup-Widerstandes mit den Jumpern  JP3 entsprechend dem verwendeten Dateneingang.

Das Einlesen  der Temperaturen   erfolgt per Browser mit dem Befehl …
<ip>/?1wire:2:3:          >> liest  Temperaturen der einzelnen 1-Wire Sensoren an den Pins D2 und D3 und zeigt den Temperaturwert (in °C) im Browser mit einer entsprechenden Meldung.

1wire_browser

Für das Einlesen in die Homematic sind vorher entsprechende  Systemvariable vom Typ Zahl für jeden abzufragenden Eingang  anzulegen. Im folgenden Beispiel sind dies …
homeduino_W2; homeduino_W3;

HM Skript   
var url = "192.168.178.58/?1wire:2:3:";
!###################################
!hier ist die Abfrage mit system.Exec
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
!WriteLine(arduino_xml);
 
integer laenge = arduino_xml.Length();
if (laenge == 0) {quit;}                !beenden , wenn laenge =0
while (laenge >38)
 { integer wort_position = arduino_xml.Find("T");
    arduino_xml = arduino_xml.Substr(wort_position+1, (laenge - wort_position-1));
    laenge = arduino_xml.Length();
    string daten = arduino_xml.Substr(0, 6);
    !WriteLine("daten:" + daten);
    string pin = arduino_xml.Substr(0,2);
    integer pinn = pin.ToInteger();
    pin = pinn.ToString();
    !WriteLine("pin:" + pin);
    string daten = arduino_xml.Substr(4, 5);
    !WriteLine("daten:" + daten);
    integer pegel = daten.ToFloat();
 
    pin = "homeduino_W" +pin;
    !WriteLine(pin);
    !WriteLine(pegel);
    dom.GetObject(pin).State(pegel);
 }

Folie8

Möchte man mehrere 1Wire-Sensoren parallelschalten und an einen Port anschliessen,  dann muss vorher die Adresse jedes einzelnen Sensors bekannt sein oder ermittelt werden.  Die Ermittlung der Adresse eines oder mehrerer  Sensoren kann einfach per Befehlseingabe im Browser erfolgen:

<ip>/?1wire_address:5:              >> zeigt  im Browser die Adressen der 1Wire-Sensoren an Pin D5

1wire_address

Diese Informationen der einzelnen parallel geschalteten Sensoren  müssen dann in ein spezielles Datenfeld im Homeduino-Sketch eingetragen werden. Das Homeduino-Sketch ist für bis zu 10 Sensoren ausgelegt, die parallelgeschaltzet  an einem der Ports D2 bis D9 angeschlossen sind. Das folgende Beispiel zeigt ausschnittartig die Adressen meiner verwendeten 1Wire-Sensoren im HM-Skript:

HM-Skript   
OneWire oneWire(onewire_pin); 
DallasTemperature sensors(&oneWire);
DeviceAddress TempSensor[] = 
{ 
 { 0x28, 0x37, 0x35, 0xB6, 0x05, 0x00, 0x00, 0x8D }, //<<user-eingabe<<
 { 0x28, 0xA5, 0x0A, 0xDD, 0x05, 0x00, 0x00, 0xBD }, //<<user-eingabe<< 
 { 0x28, 0x31, 0x60, 0xDD, 0x05, 0x00, 0x00, 0x7C }, //<<user-eingabe<<
 { 0x28, 0xA2, 0x4B, 0xB5, 0x05, 0x00, 0x00, 0x90 }, //<<user-eingabe<<
 { 0x10, 0xC7, 0xBA, 0xDD, 0x01, 0x08, 0x00, 0x52 }, //<<user-eingabe<<
 { 0x10, 0x8E, 0xB8, 0xDD, 0x01, 0x08, 0x00, 0x32 }, //<<user-eingabe<<
 { 0x10, 0xC7, 0xBA, 0xDD, 0x01, 0x08, 0x00, 0x52 }, //<<user-eingabe<<
 { 0x10, 0x8E, 0xB8, 0xDD, 0x01, 0x08, 0x00, 0x32 }, //<<user-eingabe<<
 { 0x10, 0xC7, 0xBA, 0xDD, 0x01, 0x08, 0x00, 0x52 }, //<<user-eingabe<<
 { 0x10, 0x8E, 0xB8, 0xDD, 0x01, 0x08, 0x00, 0x32 }, //<<user-eingabe<<
};

Die Messung bzw. Abfrage der Temperaturen kann dann mit dem Browser mit folgendem Befehl erfolgen:

/?onewire:8:0:1:2:3:                       >> An Digitalpin D8 werden die 1-Wire Sensoren Nr.0 bis  Nr 3 eingelesen

und man erhält das folgende Ergebnis:

1wire_result

Für das Einlesen in die Homematic sind vorher entsprechende  Systemvariable vom Typ Zahl für jeden abzufragenden Sensor  anzulegen. Im folgenden Beispiel sind dies …

fehlt noch!

 

6.8 Infrarot-FB-Receiver (Fernbedienungscodes empfangen) , IR-Gateway

Die Realisierung einer Infrarot-Fernbedienung ist mit dem Homeduino besonders einfach. Man benötigt dafür lediglich einen IR-Empfänger, der als fertiges Modul schon alles Notwendige integriert hat. Leider gibt es auf dem Markt ein Unzahl von verschiedenen Codes und Trägerfrequenzen für die Modulation des IR-Signals. Aber meistens wird eine Trägerfrequenz von 38KHz verwendet, so dass entsprechende IR-Module sinnvollerweise für diese Frequenz ausgelegt sein sollten.
Ich habe den Typ HS0038B verwendet; der kostet weniger als 1 €. Aber es gibt noch eine Vielzahl von Alternativen, die sicher auch gut funktionieren. Immer aber die unterschiedliche Pinbelegung berücksichtigen !
Der Anschluss erfolgt über 3 Leitungen an das Homeduino-IO-Shield wie auf dem nachfolgenden Bild gezeigt.

Achtung: Nur der Eingang D2 ist hierfür geeignet !!

Folie11

 

Die Anbindung an die Homematic ist relativ einfach! Hier die Schritte:

1.  Dazu muß im Homeduino Sketch die IR-Funktion auch freigeschaltet sein. Hierzu wird die folgende Zeile  so verwendet :

boolean ir_enable = 1;  

2.  Dann legt man in der Homematic die Systemvariable homeduino_ir vom Typ Zahl an

3.  Im Homeduino Sketch werden dann die IR-Codes abgelegt, die beim Empfang dann dekodiert werden und als Zahl sofort an die Systemvariable homeduino_ir übermittelt wird. Hier ist der betreffende Auszug aus dem Homeduino Sketch:

void ir_decode()
{switch(results.value)
{
case 1086165103: fb_key = 1; break;

case 1086128383: fb_key = 2; break;

case 1086161023: fb_key = 3; break;

case 1086144703: fb_key = 4; break;

case 1086177343: fb_key = 5; break;

case 1086136543: fb_key = 6; break;

case 1086169183: fb_key = 7; break;

case 1086152863: fb_key = 8; break;

case 1086185503: fb_key = 9; break;

case 1086132463: fb_key = 10; break;

default: fb_key = 255;
}
fbkey = String(fb_key);

}

Die IR-Codes sind dezimal 10-stellige Zahlen, die jeweils einer Tastenkombination der IR-Fernbedienung zugeordnet ist. Ich habe in diesem Beispiel 10 Tasten programmiert, aber man kann bis über 200 Tasten programmieren. Aber wer will das schon 😉

Wie kommen wir nun an die IR-Codes meiner Fernbedienung(en) ??

Dazu  verwendet man einen Browser und benutzt den Befehl:

192.168.178.58/?ir_receive: >> An D2 auf IR-Signal 3s warten und IR-Telegramm anzeigen

Wenn die so ermittelten IR-Codes in das Homeduino Sketch eingetragen sind, kann man nun ganz einfach HM-Programme schreiben, um mit der IR-Fernbedienung beispielsweise eine Lampe zu schalten :

webUI_ir_fb

So kann man nun mehrere Fernbedienungen „anlernen“  und mit diesen dann alle möglichen Homematic-Funktionen genauso wie mit der HM-Fernbedienung schalten und walten .

6.9 Infrarot-LED-Transmitter (Fernbedienungscodes senden)

Umgekehrt möchte man vielleicht auch andere Geräte, die bisher nur mit einer IR-Fernbedienung eingeschaltet werden konnten, direkt über Infrarot von der Homematic steuern. Mit einer oder zwei Infrarot-LEDs geht das perfekt. Die Hardware muß entsprechend den beiden nächsten Bildern verschaltet werden und die LED auf den/die Empfänger gerichtet werden.

Folie10

Folie9

Wegen der Vielzahl von verschiedenen firmenspezifischen Normen ist das Aussenden eines IR-Signals zum Betätigen irgendwelcher Funktionen per Infrarot eine schwierige Angelegenheit. Die entsprechenden Sendecodes  mit Bitlänge kann man wie im Abschnitt vorher ermitteln  und kann dann entweder mit dem Browser und dem Befehl…

192.168.178.58/?ir_send:nec:1086136543:32    >> An D9 das IR-Telegramm 1086136543 mit 36 bit laenge  ausgeben

den IR-Code aussenden oder man macht dies aus der Homematic heraus mit einem HMSkript. Zusätzlich zu dem eigentlichen IR-Code sind noch Informationen des Herstellers (NEC funktioniert meistens) und die Länge des Senetelegramms (meistens 32 bit) in dem Befehl zu berücksichtigen. Am besten läßt sich der ausgesendet Code der individuellen Fernbedienung mit dem Hilfsprogramm IRrecvDump auf der seriellen Konsole ausgeben. Das Programm findet man bei den Beispielen unter IRremote. In diesem Programm zu Beginn die Pinnummer der IR-Receivers eintragen :   int RECV_PIN = 2;

Das zugehörige HM-Skript zum Aussenden eines IR-Codes ist einfach:

 

 

var url = "192.168.178.58/?ir_send:nec:1086136543:32:";
!Stand 29.07.2014 ##############################
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
!WriteLine(arduino_xml);
integer laenge = arduino_xml.Length();
boolean status = 0;
if (laenge == 0) {dom.GetObject("homeduino_fehler").State(true);quit;} !beenden , wenn laenge =0
dom.GetObject("homeduino_fehler").State(false);

 

 

6.10  „Unbekannte“ Infrarot-Signale  im RAW-Modus senden und empfangen

verwendete Befehle:   ir-rawstore und ir_rawsend

 

Beschreibung fehlt noch

 

 

 

6.11  Drahtlose Funkfernbedienung  ( u.a. zur Ansteuerung von Funkschaltsteckdosen )
Für TV und Multimedia mit direkter Sichtverbindung zwischen Bediener  und Gerät sind natürlich IR-Fernbedienungen die erste Wahl. Für die drahtlose Steuerung von Steckdosen , Lampen etc werden aber fast nur funkgesteuerte Fernbedienungen (meist 433MHz) verwendet. Dafür gibt es im Internet äusserst preiswerte Empfänger und Sender , die entsprechend den folgenden Bildern an das Homeduino-IO-Shield angeschaltet werden. (Weltweit Suchen bei ebay nach „rf receiver transmitter arduino“) . Ein komplettes Kit bestehend aus Empfänger und Sender kostet nur ungefähr 1.50 € !!

Entsprechend der beiden nächsten Bilder werden Empfänger und Sender angeschlossen. Und natürlich muß im Homeduino Sketch auch diese Funktion freigeschaltet sein mit:

boolean rf_enable = 1;                

Folie5

Folie4

Die Programmierung erfolgt analog zur Programmierung der IR-Fernbedienung . Die sog. RF-Codes werden ermittelt  mit dem Browserbefehl:

192.168.178.58/?rf_receive:           >> An D3 auf rf-Signal 3s warten und RF-Telegramm anzeigen

Diese  RF-Codes werden dann eingetragen in das Homeduino Sketch:

void ir_decode()
{switch(results.value)
{
case 1086165103: fb_key = 1; break;

case 1086128383: fb_key = 2; break;

case 1086161023: fb_key = 3; break;

case 1086144703: fb_key = 4; break;

case 1086177343: fb_key = 5; break;

case 1086136543: fb_key = 6; break;

case 1086169183: fb_key = 7; break;

case 1086152863: fb_key = 8; break;

case 1086185503: fb_key = 9; break;

case 1086132463: fb_key = 10; break;

default: fb_key = 255;
}
fbkey = String(fb_key);

}

In der Homematic wird nun eine Systemvariable homeduino_rf vom Type Zahl angelegt, die den empfangenen Code mit der entsprechenden Zahl signalisiert.

Das WebUI-Programm zur Steuerung von Lampen etc. ist genauso wie bei der IR-Fernbedienung.

Auch die Aussendung von RF-Codes zur Ansteuerung von Funksteckdosen erfolgt genauso wie oben beim Infrarot schon beschrieben.

 

6.12 Ultraschall-Enfernungsmessung

Beschreibung fehlt noch!

Folie6

6.13 LCD-Display mit I2C

Funktion schon integriert. Beschreibung fehlt noch!  Befehle  dafür:  display

 

6.14  Barometer Sensor BMP 180

Funktion schon integriert. Beschreibung fehlt noch!  Befehle  dafür:  barometer

 


7  Bauanleitung  für das universelle I/O-Shield

Mittlerweile gibt es ein verbessertes neues I/O-Anschluss-Board mit großenteils fertiggestellter Platine.
Beschreibung hier: https://www.stall.biz/?project=vielseitiges-io-shield-board-2-0-fur-fast-alle-arduinos

Kauf-Interessierte können mich  per email (Kontakt -Button)  ansprechen.
Der Teil-Bausatz kostet 26€ plus 3,90€ Versand nach Deutschland.

Haftungs- und Sicherheitshinweise

Beim Nachbau müssen natürlich alle wichtigen einschlägigen Sicherheitsvorschriften für den Umgang mit gefährlichen Spannungen  eingehalten werden. Fundierte theoretische und praktische Fachkenntnisse der Elektrotechnik und für den Umgang mit gefährlichen Spannungen sind unverzichtbar!!

Durch eine unsachgemäße Installation gefährden Sie ihr Leben und das Leben ihrer Mitmenschen! Darüberhinaus riskieren Sie erhebliche Sachschäden , welche durch Brand etc. hervorgerufen werden können ! Für alle Personen- und Sachschäden durch falsche Installation etc. ist nicht der Hersteller sondern nur der Betreiber verantwortlich.

Ich verweise hier unbedingt auf  die  „Sicherheitshinweise und Haftungsausschluss„-Seite dieses Blogs.

 

 

 

 

 

 

 

 

Fähigkeiten

Gepostet am

14. September 2014