Seite auswählen
Homeduino 4.0 … das universelle Sensor- und Aktormodul für die Hausautomation

Homeduino 4.0 … das universelle Sensor- und Aktormodul für die Hausautomation

Update 19.03.2017:  angepasste 8181-Requests für neue CCU2-Firmware

 

Was ist der Homeduino?

Der Homeduino ist ein Selbstbauprojekt , mit dem der interessierte Hausautomatisierer mit einfachen Mitteln preiswerte und sehr leistungsfähige Module für die Automatisierung im Haus selbst zusammenstellen kann. Mittlerweile nutzen einige Hundert Nachbauer die Vorteile des Homeduino, indem viele Funktionen, die meist mit Homematic-Komponenten nicht darstellbar sind, mit dem Homeduino relativ einfach realisiert werden können. Neben Standardfunktionen wie einfache analoge oder digitale Ein- und Ausgabe von Signalen werden  mit dem Homeduino auch komplexe Module wie beispielsweise Ultraschall-Entfernungssensoren, Onewire-Temperatursensoren, Infrarot-Fernbedienung, Impulsgeber, RFID-Module, Displays und vieles mehr  unterstützt. Und da die zugehörige Software  hier veröffentlicht ist, kann jeder für seine individuellen Aufgabenstellungen relativ leicht Anpassungen vornehmen. Entsprechende Anregungen sind dafür im Internet reichlich vorhanden, weil die Basis des Homeduino  der bekannte Arduino ist, welcher weltweit eine riesige sehr aktive Entwicklergemeinde hat .

Es macht einfach Spaß, mit dem Homeduino das Haus zu automatisieren ! :D

Mit sehr preiswerten  Arduino-Shields und den hier im Shop verfügbaren IO-Shields läßt sich ein leistungsfähiges IO-Modul für die Ergänzung der Homematic aber auch für andere Automatisierungslösungen im Haus aufbauen. Man muß dafür kein Arduino-Freak sein und auch keinerlei Kenntnisse mit der Homematic-Skriptsprache haben. Lediglich ein paar Komponenten kaufen, zusammenbauen  und die hier verfügbare kostenlose Software auf seine persönlichen Belange anpassen, in den Arduino laden und fertig.

Ergebnis ist ein universell konfigurierbarer Homeduino für die einfache (skriptfreie :D ) Verwendung mit der Homematic, mit dem man nahezu alle Mess- und Steueraufgaben für die Hausautomation erledigen kann.

Was kann der Homeduino?

Mit dem hier beschriebenen Homeduino 4.0  sind nun im Vergleich zu den vorherigen Versionen viele neue  Funktionalitäten hinzu gekommen:  Ein LCD-Display, mit dem man die Eingangssignale einfach ansehen kann,  Impulszähler, um Gas- Wasser und Stromzähler auszuwerten und vieles mehr, was bereits in den Vorgängerversionen beschrieben wurde. Mehr dazu auf meiner Webseite in diesen Artikeln:

https://www.stall.biz/project/homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation-mit-io-shield-2-0-2

https://www.stall.biz/project/der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic

https://www.stall.biz/project/io-shield-plus-neue-version-mehr-inputs-und-integriertes-wlan

https://www.stall.biz/project/homeduino-3-0-das-ultimative-io-modul-fuer-die-hausautomation

Darüberhinaus sind auf dieser Webseite noch weitere Beschreibungen zum  Homeduino und zur Hausautomation vorhanden. Herumstöbern in den verschiedenen Artikeln beantwortet viele offene Fragen.

Die technischen Daten des Homeduino hängen davon ab, welche Shields und Module kombiniert werden. Mehr dazu weiter unten. Für eine Kombination mit meinem IO-Shield-Plus ergeben sich beispielsweise folgende Möglichkeiten:

Insgesamt 24  digital und analog nutzbare Funktionsports  werden nach außen auf Schraubklemmen geführt  . Diese Inputs sind individuell aufgeteilt nutzbar als…

  •  24   digitale Inputs
  •     4   Impulszähler direkt oder über Optokoppler (S0-Schnittstellen) ,
    (in Verbindung mit dem CC3000 sind nur 3 Impulseingänge verfügbar)
  •    8   analoge Inputs  mit Eingangsspannung alle von 0 bis 5V oder 0 bis 1V (wenn Uref umgeschaltet wird )
  •    8   NTC-Temperatursensoren 10kOhm  mit über Jumper zuschaltbarem 10kOhm-Widerstand
  •  24   1Wire-Temperatursensoren  DS18B20
  •  24   DHT-22 digitale Temperatur- und Feuchtesensoren
  •  24   Ultraschallsensoren
  • 2      RFID-Module RM6300
  •  LAN-Verbindung zur CCU mit optionalem Ethernet W5100 Shield
  • WLAN-Verbindung zur CCU mit optionalem WIFI-Modul CC3000  oder ESP8266-01
  • LCD Keypad Shield als 2-zeilige LCD-Anzeige mit Tastereingabe
  • TFT Touch Display zur mehrzeiligen Signalanzeige und Touch-Bedienung

Wenn zusätzlich noch das IO-Shield20 verwendet wird, (was natürlich möglich ist), dann ergeben sich noch weitere IOs, die aber hier im Detail nicht beschrieben werden. Ich verweise auf die o.a. Links.

Die aktuelle Homeduino 4.0-Software unterstützt sowohl das IO-Shield20 für das standardmäßige UNO-Pinout als auch das Erweiterungsboard IO-Shield-Plus nur für das MEGA2560 Pinout.

Wie baut man den Homeduino?

Die meisten Komponenten für den Homeduino werden fertig gekauft, lediglich die IO-Shields sind als Bausatz hier im Shop verfügbar. Dieser Bausatz ist größtenteils fertig und kann auch von einem weniger versierten Elektroniker zusammengebaut werden.

Hier die Einkaufsliste der notwendigen oder optionalen Module:

– Arduino MEGA 2560 R3

– Ethernet Shield W5100 , nicht das Ethernet- Shield mit dem ENC28J60-Chip verwenden !!

– LCD-Keypad-Shield z.B. von DFrobot  https://www.dfrobot.com/wiki/index.php?title=Arduino_LCD_KeyPad_Shield_%28SKU:_DFR0009%29

2.4“ TFT LCD Shield  z.B. bei  ebay weltweit  suchen mit 2.4“ TFT arduino  oder hier anschauen https://www.youtube.com/watch?v=ipvepLgWo6Q

– Homeduino-I/O-Shield-plus   käuflich als Bausatz hier:  https://www.stall.biz/produkt/io-shield-plus-neue-version

– Homeduino IO-Shield20    käuflich als Bausatz hier:  https://www.stall.biz/?product=io-shield-2-0

– CC3000-Modul  käuflich im Internet bei verschiedenen Anbietern.   http://www.adafruit.com/products/1469
Mehr dazu in meinem Artikel:   https://www.stall.biz/project/io-shield-plus-mehr-inputs-und-integriertes-wlan

Netzteil entweder als USB-Netzteil 5V/1A oder als 7.5V/1A-Netzteil für die Stromversorgungsbuchse des MEGA2560

Welche Module wie zusammengestellt werden, das hängt von den individuellen Zielsetzungen ab. Der nächste Abschnitt gibt dazu die Hilfestellung beim Zusammenstecken der „Legosteine“.

Wie baut man den Homeduino?

Als erstes muß man sich überlegen, was man mit dem Gerät steuern und messen möchte und  wie man mit der Homematic bzw. der CCU  datentechnisch kommunizieren möchte. Mit „Draht“ über das LAN oder drahtlos über WLAN oder oft auch Wifi  genannt. Für den Anfang ist die LAN-Kommunikation sicher günstiger, weil einfacher und robuster!

Das nachfolgende Bild zeigt die möglichen Kombinationen der einzelnen Module:

Folie15

Der MEGA2560 ist das „Herz“ des Homeduino. Im Gegensatz zu anderen Arduinos ist er sehr leistungsfähig und äußerst preisgünstig .Beispielsweise kann man ihn über ebay weltweit in Asien bereits mit USB-Kabel schon unter 9€ kaufen.

Die Kommunikation erfolgt entweder über LAN oder WLAN.  Als LAN Schnittstelle wird ein Ethernet Shield W5100 verwendet:  in China  für unter 6€ erhältlich. Dieses Shield verwendet  unglücklicherweise zur Steuerung der SD-Karte auf der Platine den Pin D4,  der beim Homeduino mit dem TFT-Display und LCD-Display benötigt wird. Diesen Pin einfach nach außen biegen geht nicht, weil dann das D4-Signal nicht an die oben liegende Display-Platine weiter geleitet wird. Deshalb muß mit dem Dremel o.ä. Werkzeug vorsichtig die D4- Signalleitung auf dem W5100-Shield unterbrochen werden. Das folgende Bild zeigt  die Unterseite des Shields mit der Unterbrechungsstelle.

Anmerkung: Die Unterbrechung kann einfacher an der Stelle der Pfeilspitze durchgeführt werden. Die von mir gewählte Stelle ist nicht günstig!

Folie14_1

Als alternative WLAN Schnittstelle kann man zusätzlich einen WLAN-Repeater  nehmen ( so wie hier : https://www.stall.biz/project/homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation-mit-io-shield-2-0-2  ) oder gleich ein Wifi-Modul mit dem CC3000-Chip einsetzen.  Käuflich über beispielsweise ebay weltweit mit Suchbegriff CC3000 WiFi Breakout module . Kostet etwa 20€. Aber Achtung, es gibt Module mit unterschiedlichem Pinout. Genau das Modul wie in diesem Artikel bestellen:   https://www.stall.biz/project/io-shield-plus-mehr-inputs-und-integriertes-wlan

Zum Anschluss der Sensoren, Aktoren und Module ist ein geeignetes Anschluss-Board notwendig. Dies kann man in meinem Shop erwerben. Entweder man verwendet dafür nur das IO-Shield-plus (Preis 24€ plus Versand)  oder man verwendet bei noch mehr „Anschlussbedarf“ zusätzlich das IO-Shield20 (Preis 26€ plus Versand).

Auf die Anzeige der Messwerte könnte man grundsätzlich verzichten, da ja die Messwerte in der Homematic verfügbar sind. Aber die Möglichkeit einer  Anzeige der Meßwerte bereits im Homeduino ist doch von großem Nutzen. Deshalb sollte man eine Anzeige „spendieren“. Möglich sind aktuell entweder eine 2-zeilige Anzeige (2×16) mit 6 Steuertasten für unter 4€ (Suchbegriff LCD Keypad Shield    oder ein kleines 240×320 Grafik-Display  mit Touch-Panel. Bei ebay weltweit mit 2.4″ TFT LCD suchen. Diese Module kosten unter 5€ sind aber trotz gleichen Aussehens mit unterschiedlichem Grafikchip im Markt  und müssen ggf. softwaremäßig angepasst werden. Also genau das Bild der Display-Platine vor dem Kauf mit meinem verwendeten Display vergleichen!

Für die weiteren Erläuterungen wurde nun folgende Modul-Konstellation entsprechend nachfolgendem Bild zusammengestellt:

Folie16

Die Boards steckt man einfach zusammen und erhält einen robusten Aufbau, den man in ein geeignetes Gehäuse einbauen kann. Versorgt wird das Gerät beispielsweise mit einem preisgünstigen 5V/1A  USB Netzteil über die USB-Buchse oder über die Stromversorgungsbuchse mit 7,5/1A . Die Sensorsignale werden dabei einfach an den auf dem Homeduino I/O-Shields verfügbaren Schraubklemmen angeschlossen. Die Funktion der einzelnen Eingänge wird einerseits mit den Jumpern auf dem Homeduino I/O-Shield festgelegt und andererseits kann man in dem verwendeten  Homeduino-Sketch bestimmte Port-Eigenschaften programmieren, die individell jeder Anwender festlegen kann. Oder man nimmt einfach die im Sketch voreingestellten Eigenschaften und muß dann eigentlich gar nichts mehr anpassen!

Folie6

Unten ist immer der MEGA2560. Darauf wird auf die hinteren Pins das IO-Shield-Plus gesteckt.  Auf die vorden Pins kommt das IO-Shield20 und/oder  das Ethernet-Shield W5100. Die Modifikation ist weiter unten beschrieben. Ganz oben steckt man das LCD-Keypad-Shield oder das TFT-Touch-Display.  Dabei ist beim LCD Keypad Shield besonders zu beachten, daß Pin D10  nicht eingesteckt bzw. nach außen gebogen ist. Das folgende Bild zeigt die Unterseite des LCD-Keypad Shields:

Folie17

Die verschiedenen Sensoren werden an die Schraubklemmen der Homeduino I/O-Shields angeschlossen. Dabei sind die speziellen Eigenschaften der Sensoren zu beachten und entsprechende Jumper zu setzen. Dies wird weiter unten erklärt bzw. dies ist in den Beiträgen der IO-Shields genauer erläutert.

Wichtig ist auch noch, daß man mit Isolierband o.ä. die metallischen Stecker auf den Shields (z.B. LAN-Buchse) so isiolieren muß, daß Kurzschlüsse zwischen den Shields ausgeschlossen sind. Manchmal kann beim „Turmbau“ der Shields auch das Einfügen von Stiftleisten zur Verlängerung der Pins notwendig sein, insbesondere wenn bei manchen Shields die Pins zu kurze Beine haben. Wie beispielsweise sehr oft bei den Display-Shields!

Bei der Lösung mit dem WLAN-Modul CC300 kann man das LAN Shield W5100 weglassen und steckt stattdessen das CC300-Modul in die dafür vorgesehene Fassung des IO-Shield-Plus. Also ganz einfach, wie man auf folgendem Bild erkennen kann.

 

 Wie kommt die Software in den Homeduino?

1. Installation der Arduino 1.8.1 Entwicklungsumgebung (IDE) für Windows

– die verwendete  Arduino-Version als zip-File runterladen: Arduino-Webseite und in ein neu erstellte Verzeichnis arduino-.1.8.1 entpacken.

– Folgende zusätzliche libraries runterladen oder diese Zip-Datei entpacken und in den vorhandenen Unterordner arduino-.1.8.1/libraries  die zusätzlichen Libraries als Unterverzeichnisse reinkopieren.

– Wenn noch nicht vorhanden ein Unterverzeichnis arduino-1.8.1/sketchbook anlegen und die Arduino Entwicklungsumgebung mit Öffnen der Datei arduino.exe aufrufen. über den  Reiter Datei/Voreinstellungen den Speicherort des Unterordners sketchbook eingeben.  In diesem Verzeichnis wird u.a. das Homeduino 4.0 Programm gespeichert.

– Die Kopplung des Arduino mit dem PC erfolgt über die USB-Schnittstelle, die nach Treiberinstallation  als serielle Schnittstelle  COM x  in der Arduino IDE erkannt wird. Dafür muß ggf. der richtige Treiber installiert sein. Hier gibt´s die aktuellen sog FTDI-Treiber : Treiber für die FTDI Schnittstelle des Arduino

2. Installation der Homeduino 4.0 Software

In der Arduino IDE wird eine neue Datei aufgerufen und per copy&paste das folgende Homeduino4.0-Sketch geladen und unter dem aktuellen Programmnamen im Sketchordner abgespeichert :

Damit weniger Probleme beim Installieren der jeweiligen Hardware-Konfiguration auftreten, sind nachfolgend verschiedene Versionen als Download verfügbar:

Hier ist die LAN-Version mit 2.4“ TFT Touch Display oder 2-zeiligem LCD-Display,  voreingestellt ist das 2.4“-TFT-Display:

Download alt:  hduino412_LAN

Update 19.03.2017: hduino414_LAN  >> geänderte 8181-Requests für neue CCU2_Firmware 2.17.7

und hier als WLAN-Version:

Download alt:  hduino412_WLAN

Update 19.03.2017: hduino414_WLAN  >> geänderte 8181-Requests für neue CCU2_Firmware 2.17.7

Ggf. die aktuelle Ergänzung der libraries in den library-Ordner reinkopieren.
Danach kann die Software compiliert  und über die USB-Schnittstelle auf den Homeduino übertragen werden.

Wegen der vielseitigen Verwendbarkeit des Homeduinos muß die Software auf die individuellen Bedürfnisse angepasst werden.

Dazu muß man im Listing alle Zeilen, die eine sog. user-Eingabe erfordern, sich genau ansehen und entsprechende Eintragungen machen.

Dies müßte mit den Kommentaren eigentlich gut möglich sein. Weiter unten werden bei den Erklärungen zum Anschluß von Sensoren und Modulen weitere Informationen zur speziellen Anpassung und Parametrisierung der Homeduino-Software gegeben.  Hier der betreffende Textblock im Listing:

tab1

Tab2

Für den hier konfigurierten Homeduino mit W5100-Ethernet-Shield, einem IO-Shield-Plus und einem TFT-Touch-Display müssen schon eine ganze Reihe von Pins für die Steuerung dieser Shields reserviert werden. Das macht man in der Tabelle oben mit Kennzahlen. Abhängig von der Kennzahl bekommt jeder Pin mit dieser Tabelle seine Funktion zugeteilt. Dabei haben wir Pins von D0 bis D73 in der Tabelle. Pins mit analogen Funktione wie beispielsweise A0 bis A15  haben auch einen korrespondierenden digitalen Namen D54 bis D69. Pins , die an Anschlussklemmen nicht verfügbar sind oder für interne Funktionen benötigt werden sind mit der Zahl 0 gekennzeichnet. Für die Steuerung des W5100-Shields werden die Pins D10 und D20 bis D22 mit der Kennzahl 20 reserviert. Das TFT-Display belegt eine Vielzahl von Pins: Dazu werden D2 bis D9  und D54 bis D58 mit der Kennzahl 31 für die Verwendung dieses Displays reserviert. Alle anderen restlichen 28 Pins, hier im Beispiel mit Kennzahl 1 als digitalen Input gekennzeichnet, sind für viele Aufgaben der Hausautomation frei verfügbar !

3.Anlernen an die Homematic-CCU

Das Anlernen an die CCU ist eigentlich schon gemacht mit dem Eintrag der IP-Adresse der CCU im Homeduino-Sketch.  Umgekehrt muß in der CCU eine Systemvariable homeduino_xyz_IP  vom Typ Zeichenkette angelegt werden, in die der Homeduino dann automatisch seine aktuelle IP-Adresse speichert. Damit weiß dann auch später die CCU , an welche IP-Adresse  sie z.B.Ausgabebefehle zum setzen der Ports schicken muß.

Um die verschiedenen Sensordaten in die CCU zu bekommen sind keinerlei Abfragen oder Skripts notwendig. Für jeden für die Hausautomation verwendeten Eingangskanal wird einfach eine entsprechende Systemvariable mit einem bestimmten Namen angelegt. Der Name ist beispielsweise homeduino_xyz_D62 . Dabei ist xyz eine individuelle Kennung dieses Homeduinos und D62 der verwendete Port, von dem die Systemvariable aktualisiert wird. Ggf. können mehr oder weniger Systemvariablen definiert werden, je nach Art und Anzahl der wirklich verwendeten Anschlüsse.

Beispiel: Verwendung D62 als digitalen Eingang:
Will man diesen Port als digitalen Eingang nutzen, dann muß erst oben in der Tabelle bei D62 eine 1 eingetragen sein. In der CCU wird dazu eine Systemvariable homeduino_xyz_D62 als Logikwert erstellt. Das ist schon alles, damit der Homeduino automatisch die Systemvariable aktualisiert, sobald sich am Homeduino der Logikwert am Eingang D62 ändert.

Beispiel: Verwendung D62 als analogen Eingang:
Will man diesen Port als analogen Eingang nutzen, dann muß erst oben in der Tabelle bei D62 eine 10 eingetragen sein. In der CCU wird dazu eine Systemvariable homeduino_xyz_D62 als Werteliste erstellt. Dann wird automatisch der Wert dieser Systemvariablen aktualisiert, sobald sich am Homeduino der Analogwert am Eingang D62 ändert.

Beispiel: Verwendung D62 als Eingang für einen NTC-Temperatursensor:
Kennziffer 11 wird eingestellt und eine Systemvariable homeduino_xyz_D62 vom Typ Werteliste und der Maßeinheit °C  enthält den aktuellen Temperaturwert.

Die so definierte Systemvariable wird automatisch entsprechend dem zugehörigen Eingangssignal aktualisiert. Damit aber nicht dauernd „Traffic“ entsteht, wird nur bei einer softwareseitig vorgegeben Veränderung des Eingangssignals die Systemvariable aktualisiert. Bei oftmals nur langsam veränderlichen Temperatursignalen reduziert sich dadurch das Datenaufkommen dramatisch. Trotzdem reagiert das System sofort, wenn Änderungen der Eingangssignale vorhanden sind! Damit sind auch schnellere Steuer und Regelvorgänge mit der Homematic möglich, wie z.B. die temperaturabhängige Steuerung der Zirkulationspumpe, Erkennung von Lichtschranken und Bewegungsmeldern etc.

Die Systemvariablen lassen sich auf der CCU jetzt  einfach in WebUI-Programmen nutzen. Werden mehrere Homeduinos verwendet , dann erhält jeder Homeduino eine andere Kennung xyz.

4. Programmieren der Display-Anzeige

Im Homeduino-Sketch müssen auch noch die Anzeigetexte entweder für die 2×16 LCD-Anzeige oder für die 6×16 TFT_Anzeige programmiert werden. Jede Anzeigezeile besteht immer aus 16 Zeichen, von denen die ersten 11 Zeichen für den Text und die restlichen 5 Zeichen für die Daten verwendet werden. Mit einer Tabelle im Listing erfolgt die Programmierung der Texte:

Tab3

Tab4

Angezeigt werden immer nur Ports, die auch mit einer Messaufgabehaben  . D.h. in der Tabelle ganz oben (iomodus)  sind dies die Ports mit Kennziffern ungleich 0 ! Die Portds, die aktuell nicht benutzt sind, werden in der Anzeige übersprungen.  Also angezeigt werden nur die Kanäle, die auch in Benutzung sind.

Bei Verwendung des 2-zeiligen LCD-Displays ist das Rollieren der Zeileninhalte mit den im  Bild erkennbaren Tastern einfach möglich:

lcd_mitAnzeige

Im nächsten Bild sieht man die links die 2.4“-TFT-Anzeige mit den 6 Zeilen.  Unten wird in einer kleinen Statusanzeige die aktuelle IP-Adresse des Homeduinos angezeigt. Mit Fingerdruck auf die gwünschte Zeile, kann der angezeigte Zeileninhalt verändert werden. Druck auf den Zeilenanfang zeigt einen Port vorher an, Druck auf das Zeilenende  zeigt einen Port höher an. So kann man das angzeigte Zeilenmenue mit den Messwerten individuell an seine persönlichen Wünsche anpassen.

tft_mittouch

Leider gibt es bei den 2.4“-Displays verschiedene Versionen im Markt, die unterschiedliche Controller haben.  Anzeige und  Touchscreen haben verschiedene Orientierungen, so daß entweder das Bild auf dem Kopf steht oder der Touchscreen nicht zum Displaybild passt. Man kann dazu die Orientierung des Displays mit Kennziffern von 0 bis 3 jeweils um 90° verdrehen im Sketch in Zeile 287: #define tft_rotation 3  bis das Bild so orientiert ist, wie auf folgendem Bild:

Wenn der Touchscreen nicht paßt bzw. die Kontaktpunkte nicht stimmen, dann das Terminalfenster öffnen und mit einem nicht zu spitzen Stift die Eichpunkte A, B, C antasten. Die entsprechenden Koordinaten px und py werden dann angezeigt sollten etwa wie die Werte in meinem Bild sein. Bei größeren Abweichungen sind in den Sketch-Zeilen 298 bis 300 die Werte zu korrigieren.

Ich selbst verwende u.a. ein großes 3.95“-Display mit 480×320 Pixel und dem Controller ILI9488, welches mittlerweile sehr preiswert angeboten wird.
Stichworte  bei ebay und Co: 3.95 tft display. Hier die Rückseiten der beiden Displays im Vergleich:

DSCF4747

Allerdings paßt die aktuelle Library nicht. Dazu die beiden Adafruit-Verzeichnisse löschen und durch diese neuen Verzeichnisse ersetzen:   tft395_lib

Wie werden Sensoren und Aktoren am Homeduino IO-Shield-Plus angeschlossen ?

Im Folgenden wird mit Anschlußplänen erläutert , wie die verschiedenen Sensoren und Aktoren über das Anschlußboard IO-Shield-Plus  angeschlossen werden. Falls zusätzlich das IO-Shield20 (für das Standard UNO-Pinout) verwendet wird, dann sind die ähnlichen Erläuterungen in diesem Artikel zu berücksichtigen: https://www.stall.biz/project/der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic

So gibt man digitale Signale aus   

Die Ausgabe von digitalen Signalen kann an den gleichen Pins D14…D29 und D62 … D69 erfolgen, vorausgesetzt die Ports wurden in der Homeduino-Software mit der Kennzahl ‚2‘ als Outputs deklariert. Jumper für die Pullups und die Schutzwiderstände können nach Bedarf für jeden Output einzeln gesetzt werden. Der Schutzwiderstand kann gleichzeitig als Vorwiderstand für eine LED zur Statusanzeige des Outputpins verwendet werden. Im Bild ist das für den Port D69 dargestellt:

Folie23

Die Ansteuerung kann aus der Homematic mit einem einfachen Skript erfolgen:

!hiermit wird der Pin D29 auf 0 oder 1 gesetzt.                                
!Wichtig voher muß im Homeduino Sketch der Pin 29 die Kennzahl '2' haben 
string setpin = "D29:0";    !D29:0 setzt D29 auf 0,     D29:1 setzt auf 1
string IP = dom.GetObject("homeduino_xyz_IP").Value();  !Holt IP_adresse des Homeduino
!WriteLine(IP);
var send_data = "http://" + IP + "/?" + setpin; !Befehl zusammensetzen
!WriteLine(send_data);
string stdout;     !und Befehl ausgeben
string stderr;
!verwendung CUxD
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#send_data#"'");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
stdout = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
 
!fehler behandlung fehlt noch
!boolean fehler = 1;
!if (stdout.Length() >0) {fehler =0;} 
!dom.GetObject("CUxD.CUX2801001:1.SYSLOG").State("eine Statusmeldung");

Das folgende WebUI-Testprogramm zeigt beispielhaft, wie man mit einem virtuellen Taster test:1 den digitalen Output zwischen o/1 umschaltet:

testprogramm_output

Zum  Testen kann man auch mit dem Browser sehr einfach die digitalen Outputs setzen oder rücksetzen: In die Adressleiste des Browsers einfach den Befehl eingeben:

<IP>/?D69:1    setzt den Port D69 auf 1 oder mit   <IP>/?D69:0   wird Port auf 0 gesetzt.  Die IP-Adresse des Homeduino ist im TFT-Display unten angezeigt oder man schaut sich den Inhalt der Systemvariablen homeduino_xyz_IP an.

So schließt man digitale Sensoren an

Digitale Sensoren kann man an insgesamt 24 Ports des IO-Shield-Plus anschließen, siehe folgendes Bild:

Folie22

Dabei können die analogen Ports auch als digitale Inputs gleichermaßen verwendet werden, wenn natürlich in der Homeduino-Software diese Ports auch als digitaler Input mit der Kennzahl ‚1‘ deklariert sind. Jeder Port hat einen Schutzwiderstand von 470 Ohm zwischen Prozessorpin und Schraubklemme. Damit wird der Ausgang einerseits kurzschlußfest, man kann ihn aber, falls notwendig, mit einem Jumper (schwarzer Jumper)  überbrücken. Zudem hat jeder Port noch einen Pullup-Widerstand, damit beispielsweise einfache Schaltersensoren ohne Zusatzbauteile  angeklemmt werden können. Auch den Pullup-Widerstand von 10KOhm kann man individuell für jeden Portpin per Jumper (schwarzer Jumper ) zuschalten. Schaltsignale müssen 5V-Pegel haben, aber u.U. können  auch 3,3V-Signale sauber erkannt werden.

In der CCU wird für jeden verwendeten digitalen Eingang eine logische Systemvariable angelegt. Entsprechend dem Eingangssignal am korrespondierenden Input  wird automatisch die Systemvariable aktualisiert, wenn eine Statusveränderung erfolgt ist. Für den digitalen Eingang D69 muß beispielsweise  in der CCU die Systemvariable homeduino_xyz_D69 angelegt sein. Das ist schon die ganze Programmierung.

Oftmals ist es sinnvoll Geräte und Sensoren über potentialfreie Eingänge anzuschließen. Hierfür können  4 Inputs alternativ über Optokoppler potentialfrei angesteuert werden. Insbesondere Impulsgeber von Strom- Gas- und Wasserzähler sind oft mit einer sog. S0-Schnittstelle ausgerüstet, die an die Optokoppler potrentialfrei angeschlossen werden können. Schalter- und Tastersensoren können an alle verfügbaren Ports angeschlossen werden. Die zugehörigen 10kOhm-Pullup-Widerstände sind dann mit den entsprechenden Jumpern (im Bild grün)  zu aktivieren. Die 470Ohm-Schutzwiderstände können eingeschaltet bleiben; deshalb müssen keine Überbrückungsjumper (schwarz) gesetzt werden.

 

Folie23

So schließt man analoge Sensoren an

Für die analogen Signale sind 8 Ports vorhanden. Der Signalbereich ist 0… +5V; die Eingänge sind hochohmig, so daß der Schutzwiderstand eingeschaltet werden kann (schwarzer Jumper). Größere Analogspannung können durch einfache Spannungsteilung realisiert werden.

Folie24

 

So schließt man NTC-Temperatursensoren an

NTC-Widerstände sind zur Temperaturmessung sehr preisgünstig und einfach in der Handhabung. Für „normale“ Anwendungen eignen  sich 10kOhm-NTCs besonders, weil sie verbreitet sind und kostengünstig auch im Gehäuse konfektioniert zu kaufen sind. Die 10kOhm-Sensoren können direkt an die analogen Ports angeschlossen werden, wenn die 10kOhm-Pullups mit den Jumpern zugeschaltet sind. Das folkgende Bild zeigt die entsprechende Konfiguration:

So schließt man 1Wire Temperatursensoren an

Sog. 1Wire-Sensoren sind für die Temperaturmessung besoinders vorteilhaft, weil sie bereits geeicht sind und der Temperaturwert vom integrierten Chip direkt als Digitalsignal ausgegeben wird. Einzelheiten zur Verwendung sollen hier nicht weiter erklärt werden, dazu gibt es im Internet unter beispielsweise dem Stichwort DS18B20 viele Informationen. Beim Homeduino wird je Port nur ein Sensor angeschlossen und nicht mehrere parallel. Das hat den Vorteil , daß softwaremäßig auf eine Identifizierung verzichtet werden kann und der Sensor „einfach nur angeschlossen“ wird. Den Rest erledigt die Homeduino-Software!

Angeschlossen werden kann ein typischer 1Wire Temperatursensor DS18B20 über zwei oder 3 Drähte entsprechend dem folgenden Anschlussbild. Empfohlen wird der m.E. zuverlässigere 3.Draht-Anschluss. Insgesamt sind 24 Sensoren anschließbar, allerdings geht bei einer großen Sensorzahl die Zeit für einen gesamten Programmdurchluf deutlich hoch, so daß jeder einzelne Kanal seltener abgefragt werden kann. Genaue Erfahrungen mit so vielen 1Wire-Sensoren liegen mir nicht vor, aber mit bis zu 6 Sensoren ist eine Abtastung im 10-Sekundenbereich möglich. Aber meistens ändern sich Temperatruren doch recht langsam. Im Vergleich zu den Abtastraten der Homematic-Temperatursensoren mit etwa 3min Abtastzeit ist die Abtastfrequenz hier sehr hoch.

Folie28

So schließt man DHT22 Temperatur- und Feuchtesensoren an

Die weit verbreiteten digitalen Temperatusensoren DHT22 oder auch SHT22 können mit dem Homeduino auch sehr einfach abgefragt werden. Zwar können auch bis zu 24 Sensoren angeschlossen werden, allerdfings sollte man die relativ langsame Datenübertragung bei diesen Sensoren berücksichtigen. Der Anschluss erfolgt einfach nach folgendem Schema:

Folie28

Auf dem Display wird nur die Temperatur angezeigt. Aber der Sensor mißt ja zusätzlich auch die Luftfeuchte. Dieser Wert wird automatisch an die CCU mit übertragen. Wenn der Sensor beispielsweise an D29 angeschlossen ist, dann heißt die zugehörige Systemvariable der CCU  homeduino_xyz_D29  vom Typ Zahl . Diese Systemvariable empfängt dann die Temperatur. Die Feuchte wird an eine ebenfalls zu definierende Systemvariable  homeduino_xyz_D29_1  gesendet. Also einfach eine weitere Systemvariable mit dem Anhängsel  _1  auf der CCU festlegen.

Mehr Infos zu den verschiedenen Sensoren findet man auch hier: https://www.stall.biz/project/der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic

 So schließt man Ultraschall-Entfernungssensoren an

Die Ultraschallsensoren vom Typ SR04 gibt es im Internet als fertiges Modul bereits für 1€. Sie sind ideal, um Entfernungen von schallreflektiven  Gegenständen zwischen 0 und  450cm zu messen. Im Homeduino wurde die maximale Entfernung auf 200cm begrenzt, weil mit zunehmender Entfernung das Signal „sehr variabel“ wird, was wegen der Änderungen des Messignals dann auch zu einem (zu ) regen Telegrammverkehr mit der CCU führt. Man kann die Meßhäufigkeit reduzieren, indem man die Änderungsschwelle von standardmäßig 2cm vergrößert. Die entsprechende  Variable im Homeduino Sketch heißt float delta_us = 2 .

Man kann an den Homeduino bis zu 8 SR04-Sensoren direkt (ohne die 150Ohm Schutzwiderstände, Jumper 4-5) an die Pins D2 bis D9 anschliessen. Die Software ist so ausgelegt, daß neben der Spannungsversorgung nur eine Datenleitung zum Sensor notwendig ist. Dazu sind aber die zwei mittleren Anschlusspins zu verbinden. (siehe nächstes Bild)

 So schließt man  I2C-Sensoren an:

Die serielle Kommunikation nach dem sog. I2C-Standard wird sehr gern zum universellen Anschluss von verschiedensten meist sehr intelligenten Sensoren verwendet. Benötigt werden dafür nur zwei Leitungen SDA und SCL, die am IO-Shield-Plus an den Anschlüssen D20 (SDA)  und D21 (SCL)  direkt verfügbar ist. Normalerweise  wird der I2C-Bus mit 3,3V-Signalpegeln betrieben, aber der 5V- MEGA „versteht“ auch die kleineren Signalspannungen. Problematisch ist das aber für einige I2C-Sensoren, die dann die 5V-Signale vom Arduino nicht vertragen. Deshalb immer vorher vergewissern, ob die I2C-Sensoren mit nur 3,3 oder oder auch mit 5V betreibbar sind. Eventuell sind Pegelwandler notwendig, die man für wenig Geld kaufen kann. Die hier verwendeten I2C-Sensoren können ohne Zusatzelemente direkt an 5V betrieben werden. Notwendig sind dann noch für die Spannungsversorgung der I2C-Module die entsprechenden zusätzlichen zwei Leitungen.

Der I2C-Bus ist ein Datenbus für kurze möglichst kapazitätsarme Leitungen. Solange man bei den Leitungslängen unter 2m bleibt, dürfte das kein Problem sein. Längere Leitungen muß man einfach probieren oder den Takt runtersetzen. (Wie das geht , müßte man googeln)
Normalerweise benötigt der I2C-Bus auch sog. Pullup-Widerstände. Diese sind aber in den hier verwendeten Sensoren bereits eingebaut.

Anschluss Barometersensor BMP180:
Der verwendete Sensor BMP180 ist der Nachfolgesensor des BMP085. Der Sensor selbst hat normalerweise eine Versorgungsspannung von 3,3V . Aber auf dem hier verwendeten Modul ist ein Spannungsregler integriert, so dass ein Betrieb mit 5V möglich ist. Also unbedingt auf den folgenden Bildern den Modultyp vergleichen. Ansonsten kauft man die 3V-Version und beschädigt so das Modul sofort bei Inbetriebnahme! Mehr zu diesem tollen Sensor hier :  http://www.bosch-presse.de/presseforum/details.htm?txtID=5192
Den genauen Anschluss des Sensors zeigt das nachfolgende Bild:

Anschluss Lichtsensor BH1750:
Die Messung der Helligkeit kann in einfacher Form mit einem  lichtabhängigen Widerstand (LDR), erfolgen. Diese Bauelemente sind in vielen Dämmerungsschaltern und Bewegungsmeldern verbaut und verrichten für „normale“ Verhältnisse ihre Funktion recht gut. Sie sind einfach anzuwenden und sehr preiswert.
Leider hat aber die Umgebungshelligkeit eine riesige Dynamik zwischen „rabenschwarzer“ Nacht und Helligkeit in der prallen Sonne!
Diese Webseite zeigt das recht anschaulich: http://s6z.de/cms/index.php/arduino/sensoren/15-umgebungslichtsensor-bh1750
Für höhere  Ansprüche an die Lichtintensitätsmessung ist deshalb die Verwendung des I2C-Sensors BH1750 anzuraten. Auch dieses Modul ist mit 5V betreibbar und kann genauso einfach wie der Barometersensor an den I2C-Bus angeschlossen werden. Dabei kann der Sensor BH1750  alleine oder zusammen mit  dem BMP180 am I2C-Bus betrieben werden. (wie im Bild oben gezeigt)

So schließt man einen oder zwei RFID Reader an

Mittlerweile gibt es für den Arduino eine Vielzahl von sehr preiswerten RFID-Readermodulen, die meistens mit einer Frequenz von 125Khz oder 13Mhz laufen. Sie verwenden oft den SPI-Bus und blockieren damit mehrere Pins. Beim Homeduino  wurde deshalb  die serielle Datenübertagung gewählt, für die nur ein serieller Port notwendig ist. Insgesamt belegt man dann mit einem Reader nur einen seriellen Port mit RX und TX-Leitung (auch wenn die TX-Leitung nicht verwendet wird).

Als RFID-Reader kommt ein Modul RDM6300 zur Anwendung. Die Suche bei Ebay mit dem Suchbegriff RDM6300 führt schnell zu sehr günstigen Angeboten unter 4€ !
Das RDM6300 Modul arbeitet mit 125Khz und hat eine Sende/Empfangsspule mit dabei.

Folie21

Ausgelöst wird der RFID-Reader mit dem sog. FOB oder TAG , welcher eine unverwechselbare Codierung enthält. Dieser Code ist ist eine 10-stellige Dezimalzahl, die man im Bild auf dem FOB erkennen kann. Relevant sind nur die letzten 7 Stellen, weshalb diese auch nur im Homeduino angezeigt und verarbeitet werden.

Die Hard- und Software des Homeduinos ermöglicht den Anschluss von zwei RFID-Readern (RFID2 am seriellen Port 2  und RFID3 am seriellen Port 3), die man beispielsweise für die Haustür und die Garage einsetzen kann. Beide Reader nutzen die gleiche Datenbasis der freigegebenen Benutzer.

Die Hardware:
Der Anschluß an den Homeduino erfogt über das IO-Shield-Plus. Die verwendeten Anschlussklemmen und die Verschaltung ist im folgenden Bild dargestellt:

Folie20

Der Reader RFID2 wird mit seiner Datenleitung(TX) an D17 (RX2) angeschlossen. Ein weiterer RFId3-Reader kann entsprechend mit D15 verbunden werden. Falls ein elektrischer Türöffner verwendet werden soll, dann ist ein Relais mit einem Transistortreiber an die Datenleitungen D23 und D22 anzuschließen. Man kann in der Homeduino Software konfigurieren, welcher RFID-Reader welchen Türöffner öffnen soll.

Die Software im Homeduino:
Dioe Konfiguration der RFID-Reader erfolgt in der Homeduino-Software einfach nur mit Kennzahlen in den bekannten Variablentabellen.  Zuerst muß den verwendeten Pins die RFID-Funktion zugeordnet werden. Hier der relevante Auszug aus dem Listing:

rfid_liste

Bei Verwendung von zwei Readern bekommen die Ports D14 bis D17 die Kennzahl 12 ; wenn Öffner verwendet werden dann muß zusätzlich D22 und /oder  D23 auf 12 gesetzt werden.

Die Programmierung der Zugangsliste ist sehr einfach, indem man den FOB-Nummern die entsprechenden Namen zuordnet. Die folgende Liste ist eigentlich selbsterklärend:

rfid_userliste

Insgesamt können 20 FOBs verwendet werden, was für die meisten heimischen Anwendungen sicher ausreicht. Eingegeben wird nur die 7-stellige Nummer ohne die Nullen vorneweg. Als Namen nicht mehr als 8 Zeichen verwenden, weil sonst das Display „überläuft“. Zusätzlich zum Namen kann man mit einer Kennzahl nocch festlegen, ob die betreffende Person über den/die Türöffner Zugang bekommen soll oder nicht. Wenn man die Nummer des FOBs nicht kennt, dann einfach kurz auf den Reader legen, um die Kennzahl dann anzuzeigen. Im Versuchsaufbau sieht das dann so aus:

rfid_mitFob

Die LED rechts im Bild zeigt den Türöffnerstatus an. Sie kann ohne Vorwiderstand an die entsprechenden Ausgänge D22 oder D23 wngeschlossen werden, wenn die zughörigen beiden Jumper nicht gesteckt sind.  In diesem Fall fungiert der 470Ohm Schutzwiderstand als Vorwiderstand für die LED.

Die Software in der CCU
Die Programmierung in der CCU ist ganz einfach, weil der Name der eintretenden Person einfach an eine zugehörige Systemvariable vom Typ Zeichenkette übermittelt wird. Dabei wird der richtige Name übertragen; nur wenn ein unbekannter FOB zugang haben will, dann wird die Nummer des FOB übermittelt.

Man legt folgende Systemvariablen an …

rfid_variablen

… und kann dann immer den letzten FOB bzw. den Namen der zugehörigen Person.

Eine Dekodierung der Namen auf der CCU macht wenig Sinn, weil die Antwortzeiten der CCU bis zum Türöffnen viel zu groß sind. Zudem sollte ich die Zugangssteuerung unabhängig von der CCU sein, weil die sehr wichtige Funktion des Türöffnens mit der CCU zu unzuverlässig scheint.  Aktuell ist das parallele Öffnen mit der CCU noch nicht enthalten, aber das ist geplant!

Viel Erfolg und Spaß mit dem Homduino 4.0 !

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.

IO-Shield-Plus (neue Version)  … mehr Inputs und integriertes WLAN

IO-Shield-Plus (neue Version) … mehr Inputs und integriertes WLAN

Vorgeschichte:

Auf dieser Webseite sind verschiedene Bauanleitungen mit Verwendung der äußerst vielseitigen und preiswerten Arduino-Module im Zusammenspiel mit der  Homematic vorgestellt. Zur einfachen Anwendung auch für den weniger versierten Elektroniker ist ein sehr praktisches Anschlußboard IO-Shield20  entstanden.  In Verbindung mit der kostenlosen Homeduino Software  lassen sich damit eine Vielzahl von Sensoren über einfache Schraubklemmen anschließen und die Sensorsignale über LAN oder WLAN an die Homematic übertragen. . Mehr dazu hier:

https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic

https://www.stall.biz/?project=vielseitiges-io-shield-board-2-0-fur-fast-alle-arduinos

https://www.stall.biz/project/homeduino-3-0-das-ultimative-io-modul-fuer-die-hausautomation

Der Vorteil bei Verwendung des IO-Shield-Plus als Homeduino-Sensormodul ist, daß auf der Homematic keinerlei komplizierte Skripte o.ä. installiert werden müssen. Lediglich ist für jede Meßgröße eine entsprechende Systemvariable in der CCU festzulegen. Die Aktualisierung mit den Meßwerten aus dem Homeduino erfolgt automatisch, aber nur wenn  sich der Meßwert ändert. Damit entsteht ein sehr geringer Traffic im Netz, was insbesondere bei vielen Homeduinos von Vorteil ist.

Warum ein weiteres IO-Shield ?

Das hier vorgestellte  IO-Shield-Plus ist nicht ein Ersatz für das bisherige IO-Shield20, sondern eine wichtige Ergänzung. Dabei spielt eine wesentliche Rolle, daß für die Verwendung von weiteren Shields beispielsweise zur  LCD-Anzeige und zur Bereitstellung des WLAN oft recht viele Pins des Standard-Arduino-Pinouts für den Betrieb des Shields belegt werden. Für die eigentliche Automatisierungsaufgabe bleiben dann oft nur wenige Funktionspins übrig. Aber gerade beim MEGA2560 sind ja noch viele IO´s auf dem hinteren Teil der Platine verfügbar, die mit diesem Erweiterungsshield an Schraubklemmen verfügbar gemacht werden können. Vorne lassen sich  dann Shields beispielsweise für ein alphanumerisches Display oder ein Touch-Display aufstecken. Weiter unten sind Beispiele für typische Konfigurationen.

Eigenschaften des IO-Shield-Plus

Das IO-Shield-Plus wird mit Stiftleisen auf die hinteren Pins des MEGA2560 aufgesteckt. Mittels Schraubklemmen lassen sich verschiedene Sensoren anschließen. Für die  WLAN-Module sind Steckplätze vorhanden. Man kann dort das sehr leistungsfähige Wifi-Modul CC3000 von Texas Instruments und das besonders preisgünstige Modul ESP8266-01 einstecken. Das folgende Bild  zeigt das IO-Shield-Plus von der Bestückungsseite:

platine_1

Alle Inputs sind mit 470Ohm-Widerständen gegen Kurzschluß geschützt.  Ein 3,3V-Spannungsregler versorgt aktuell das Wifi-Modul, kann aber auch zur Versorgung von anderen 3.3V-Verbrauchern verwendet werden. Für den Anschluß der potentialfreien S0-Schnittstellen sind 4 Optokoppler ebenfalls auf der Platine. Mit Jumpern kann für jeden Port ein 10kOhm-Pullup-Widerstand zugeschaltet werden (im Schemabild unten als schwarzer Juzmper gekennzeichnet). Ein 470Ohm Reihen-Widerstand ist als Schutzwiderstand in jeder Portzuleitung vorhanden, der aber per Jumper überbrückt werdeb kann (im Schemabild unten als grüner Juzmper gekennzeichnet). Bei Verwendung des Ports als Ausgang kann dieser Widerstand auch  als Vorwiderstand für eine LED o.ä.verwendet werden.

Hier die Eigenschaften des IO-Shield-Plus im Detail:

  •   insgesamt 24  digital und analog nutzbare Funktionsports  werden insgesamt nach außen auf Schraubklemmen geführt  . Diese Inputs sind individuell aufgeteilt nutzbar als…
  •  24   digitale Inputs
  •     4   Impulseingänge direkt oder über Optokoppler (S0-Schnittstellen) ,
    (in Verbindung mit dem CC3000 sind nur 3 Impulseingänge verfügbar)
  •    8   analoge Inputs  mit Eingangsspannung alle von 0 bis 5V oder 0 bis 1V (wenn Uref umgeschaltet wird )
  •    8   NTC-Temperatursensoren 10kOhm  mit über Jumper zuschaltbarem 10kOhm-Widerstand
  •  24   1Wire-Temperatursensoren  DS18B20
  •  24   DHT-22 digitale Temperatursensoren
  •  24   Ultraschallsensoren

Da IO-Shield-Plus hat eine Größe von 100mm x 65mm und kann mit den Stiften auf der Unterseite direkt auf die entsprechenden Buchsenleisen des MEGA2560 aufgesteckt werden. Dabei läßt sich das Shield alleine betreiben aber auch in Kombination mit dem universellen IO-Shield20:

Folie4

 Anwendungsmöglichkeiten

Natürlich läßt sich das Shield ganz normal in einem StandAlone-Arduino betreiben, um etwas zu steuern und zu regeln. Aber bei der Auslegung des IO–Shield-Plus wurde besonderer Wert auf eine einfache Anbindung über WLAN an die CCU der Homematic gelegt. Deswegen sind Stecksockel für geeignete Wifi-Module auf dem Board, so daß sehr einfach eine WLAN-Funktionalität erreicht werden kann. Damit bleibt der „normale“ Steckplatz für andere Shields frei und somit eröffnen sich flexible Kombinationsmöglichkeiten mit vielen Standard-Shields. Die folgenden Bilder sollen dazu einen Eindruck verschaffen:

Folie5

 

Folie6

 

Installation des WLAN-Moduls CC3000

Als Wifi-Module können der CC3000 von Texas Instruments verwendet werden, aber auch der sehr preisgünstige Chip ESP8266-01 eines chinesischen Herstellers. Die Steuerung des CC3000 erfolgt über die sog. SPI-Schnittstelle, welche  auf dem MEGA2560 mit den Datenpins D50 bis D53 verfügbar ist. Zusätzlich werden noch die Pins D46 und D18 verwendet. Dabei ist zu beachten, daß der D18 im IO-Angebot des IO-Shields-Plus  nicht mehr für eine Zählerfunktion o.ä. verwendet werden kann.

Das CC3000-Modul ist als sog. Breakout in einschlägigen meist chinesischen Internet-Shops bereits für etwa 20€ verfügbar. Suchbegriff z.B. bei Aliexpress oder ebay „cc3000  breakout“.

Das Breakout-Modul ist nahezu fertig; es muß lediglich die mitgelieferte Stiftleiste eingelötet werden. Dabei hat man die Wahl, die Stiftleisten auf der  Rückseite oder der Bestückungsseite einzulöten. Dementsprechend zeigt das Modul später im eingesteckten Zustand auf dem Board nach hinten oder nach vorn. Ich habe die Stifte auf der Rückseite eingelötet:

cc3000_hand

Zusammenbau des IO-Shield-Plus

Das IO-Shield-Plus ist  in meinem Shop als Bausatz erhältlich. https://www.stall.biz/produkt/io-shield-plus-neue-version  Das Board ist bereits mit allen Widerständen, Kondensatoren usw. bestückt. Lediglich einige Steckleisten müssen zugeschnitten und verlötet werden. Dies ist auch für den  weniger versierten Elektroniker gut machbar. Das folgende Bild zeigt den Lieferumfang:

teile

Zur Hilfestellung beim Zusammenbau gibt´s hier auch eine Bauanleitung.

 Anschlussschema

Der Anschluss der Sensoren und Module erfolgt im wesentlichen mit den vielen verfügbaren Schraubklemmen. Für alle Ports sind noch per (schwarzem) Jumper zuschaltbare 10kOhm-Pullups vorhanden, was beispielsweise für die einfache Applikation von 10kOhm-NTC-Thermosensoren hilfreich ist. Auch typische Sensoren mit Pullup-Bedarf wie der digitale Temperatursensor DS18B20  kann so ohne Zusatzbauelemente an den entsprechenden Ports betrieben werden.

Jeder Port ist mit einem seriellen Widerstand von 470 Ohm gegen Kurzschluss geschützt. Dieser Widerstand kann aber mit einem Jumper (grüner Jumper) überbrückt werden. Man kann diesen Schutzwiderstand bei Bedarf auch als Vorwiderstand für eine LED o.ä. verwenden.

Für Anschluß von verbreiteten Modulen mit I2C-Bus ist auch ein Lötanschluß verfügbar. Der auf dem Board integrierte 3,3V-Spannungsregler ist auch für weitere externe 3,3V-Module verwendbar, wenn zur drahtlosen Kommunikation der ESP8266 nicht verwendet wird.

Die Wlan-Module haben beide einen Steckanschluss und müssen seitenrichtig einfach nur eingesteckt werden.

Der Rest wird mit der Homeduino-Software eingestellt und konfiguriert. Die aktuelle Version der Software ist hier: https://www.stall.biz/project/homeduino-3-0-das-ultimative-io-modul-fuer-die-hausautomation

 

Viel Spaß und Erflog mit dem Teilchen :))

Folie8

 

 Wo bekommt man das IO-Shield-Plus?

Wer das IO-Shield-Plus nachbauen möchte, kann über meinen Webshop einen Bausatz mit allen Teilen außer dem Wifi-Modul beziehen.

https://www.stall.biz/produkt/io-shield-plus-neue-version

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.

 

 

Homeduino 3.0 … das ultimative IO-Modul für die Hausautomation

Homeduino 3.0 … das ultimative IO-Modul für die Hausautomation

Wichtiger Hinweis: Es gibt mittlerweile eine neue Softwareversion:   Homduino 4.0

Für die Ungeduldigen ist hier die erste vorläufige Version der Homeduino 3.0 Software veröffentlicht. An der Software wird noch gearbeitet und einige Funktionalitäten für  Infrarot- und 433Mhz-Module fehlen noch. Darüberhinaus ist auch noch eine LCD-Anzeige geplant.

Unterstützt werden das IO-Shield20 und das IO-Shield-Plus

Hier die Installationshinweise:

1. Installation der Arduino 1.6.3 IDE

2. Kopieren der zusätzlichen Libraries in das Library-Verzeichnis:
https://www.stall.biz/wp/wp-content/uploads/2015/04/homeduino_libraries30.zip

3. Ausführen der aktuellen Version : (mit W5100-Ethernet-Shield oder CC3000 Shield )

Anmerkung 07.05.2015:  Die aktuelle Version homeduino30_03 ist noch nicht komplett getestet !!

Rückmeldungen erwünscht .

Beide folgenden Versionen (W5100 mit LAN und CC3000 mit WLAN) könnte man in einem Sketch mit sog. „conditional compilation“ zusammenfassen, aber leider gibt es damit noch Fehlermeldungen, die aktuell (noch) nicht beseitigt werden konnten. Deshalb hier aktuell noch zwei Versionen:

 

 Hier die LAN-Version:

/*Ver.: "homeduino30_03_LAN.ino / Stand: 2015.05.11 / Verfasser: Eugen Stall
 
LAN-Version mit W5100 Shield
 
hier ist immer die aktuelle Version:
Home
das folgende homeduino-programm sendet messdaten zur ccu (homeduino als webclient) ...
und empfängt ausgabedaten für die homeduino-outputs (homeduino als webserver)
____________________ ___________________
 | | 
 server port 8181 |<------------<| client 
 | | 
 CCU | | Homeduino 
 | | 
 client |>------------>| server port 80
____________________| |___________________
 
erprobt fuer Arduino Mega 2560 mit Arduino 1.6.3
diese Software steuert referenziert die signale an den Arduino-pins mit entsprechenden systemvariablen in der Homematic ccu
mit dem Befehl: http://<ip der ccu>:8181/GET /xy.exe?antwort=dom.GetObject('<systemvariable>').State(" + value + ")"
/Quellen:Arduino website plus http://arduino.cc/en/Tutorial/WebClient und ...
 http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino und ...
*/
 
#include <SPI.h>
#include <Wire.h> 
#include <OneWire.h> //für Temperatursensoren DS18B20 http://www.hacktronics.com/code/OneWire.zip
#include <NewPing.h> //für Ultraschallsensoren SR04 https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip
#include "DHT.h" //für Temperatursensoren SHT22 https://github.com/adafruit/DHT-sensor-library/archive/master.zip
#include <AS_BH1750.h> //für I2C-Luxmeter https://github.com/hexenmeister/AS_BH1750/archive/master.zip
#include <SFE_BMP180.h>//für I2C-Barometer https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
#include <RCSwitch.h> // läuft noch nicht!
//#include <IRremote.h> // läuft noch nicht!
 
//Kommunikationsweg  festlegen
#define com_mode 0  //"0"  W5100, "1" CC300 Breakout                                     <<user-eingabe<< 
 
/*
//der folgende Bereich ist die Initialisierung des CC3000 Wifi auf dem IO-Shield-Plus 
#include <SFE_CC3000.h>// fuer cc3000 wifi http://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip
#include <SFE_CC3000_Client.h>
// Pins
#define CC3000_INT 18 // int-Pin mit Wifi Shield ist D3, mit breakout auf IO-Shield-Plus ist D18
#define CC3000_EN 46 // en-Pin mit Wifi Shield ist D5, mit breakout auf IO-Shield-Plus ist D46
#define CC3000_CS 53 // cs-Pin mit Wifi Shield ist D10, mit breakout auf IO-Shield-Plus ist D53
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
// Constants
char ap_ssid[] = "ssid"; // SSID Name des WLAN in Anführungszeichen                       <<user-eingabe<< 
char ap_password[] = "passwort"; // Passwort des WLAN in Anführungszeichen                <<user-eingabe<< 
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
unsigned int timeout = 30000; // Milliseconds
//char server[] = "192,168,178,50"; // Remote host site
*/
 
//der folgende Bereich ist die Initialisierung des LAN bei Verwendung des LAN-Shields
#include <Ethernet.h> 
EthernetClient client;
EthernetServer server(80);
 
 
byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU <<user-eingabe<< 
byte mac[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; //bei mehreren homeduinos ändern!!    <<user-eingabe<<
byte homeduino[] = { 192, 168, 178, 52 }; //das ist feste IP dieses Homeduino,             <<user-eingabe<< 
 //wenn DHCP versagt
String homeduino_nummer = "xyz"; //indiv. Bezeichnung dieses homeduino                     <<user-eingabe<< 
 //das ist bel. String ohne 
 //sonderzeichen und öäüß... 
String hm_systemvariable = "homeduino_" + homeduino_nummer +"_";
 
 
//Input-Kennung: hier wird die Funktion aller verwendbaren IO´s mit einer Kennziffer festgelegt 
//dabei haben alle IO´s die Standardfunktionen plus spez. Sonderfunktionen
byte iomodus_D[70] = 
{ 0, //D0 : '0' = andere Nutzg; 
 0, //D1 : '0' = andere Nutzg; 
 
//Standardfkt:'0' =andere Nutzg; '1' =dig_input; '2' =dig_output; '3' =1wire '4' =DHTxx; '5' =U_Schall 
 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield20 +++++++++++++++++ 
 2, //D2 : Standardfkt; '5' = IR_Rx?? '6' =ImpCount;                        <<user-eingabe für IO-Shield20<< 
 2, //D3 : Standardfkt; '7' = 433_Rx?? '6' =ImpCount;                       <<user-eingabe für IO-Shield20<< 
 0, //D4 : Standardfkt; '7' = 433_Tx?? '0' =W5100/SS-Pin                    <<user-eingabe für IO-Shield20<< 
 2, //D5 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D6 : Standardfkt; '9' = buzzer                                        <<user-eingabe für IO-Shield20<< 
 0, //D7 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D8 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 1, //D9 : Standardfkt; '5' = IR_Tx??                                       <<user-eingabe für IO-Shield20<< 
 0, //D10 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D11 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D12 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D13 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield_Plus ++++++++++++++ 
 3, //D14 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D15 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D16 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D17 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 0, //D18 : Standardfkt; '6' =ImpCount; '0' =CC3000                     <user-eingabe für IO-Shield-Plus20<< 
 3, //D19 : Standardfkt; '6' =ImpCount;                                 <user-eingabe für IO-Shield-Plus20<< 
 1, //D20 : Standardfkt; '6' =ImpCount; '8' =I2C;SDA                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D21 : Standardfkt; '6' =ImpCount; '8' =I2C;SCL                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D22 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D23 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D24 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D25 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D26 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D27 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D28 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D29 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
//hier wird die Funktion der Eingänge A0 bis A15 festgelegt
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield20 ++++++++++++++++++
 3, //D54 A0 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 2, //D55 A1 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D56 A2 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D57 A3 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D58 A4 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D59 A5 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D60 A6 : "0" =andere Nutzg; 
 0, //D61 A7 : "0" =andere Nutzg; 
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield_Plus +++++++++++++++
 1, //D62 A8 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D63 A9 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D64 A10 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D65 A11 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D66 A12 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D67 A13 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D68 A14 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1 //D69 A15 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
}; 
//hier werden Sensoren am I2C-Eingang aktiviert
byte iomodus_baro = 0; //'0' =nc; '1' =BMP180, dann auch oben I2C setzen <<user-eingabe für IO-Shield-Plus<<
byte iomodus_lux = 0; //'0' =nc; '1' =BH1750, dann auch oben I2C setzen  <<user-eingabe für IO-Shield-Plus<<
 
//hier werden die Kennwerte fuer die Impulszaehler festgelegt
unsigned zaehlwert;
unsigned last_zaehlwert[6] = {0,0,0,0,0,0};
volatile unsigned long pulsecounter[6] = 
{ 0, //Zaehlerstand fuer D2 -Impulseingang bei Reset                        <<user-eingabe für IO-Shield20<<
 0, //Zaehlerstand fuer D3 -Impulseingang bei Reset                         <<user-eingabe für IO-Shield20<<
 4711, //Zaehlerstand fuer D21-Impulseingang bei Reset                   <<user-eingabe für IO-Shield-Plus<< 
 3, //Zaehlerstand fuer D20-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 4, //Zaehlerstand fuer D19-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 5 //Zaehlerstand fuer D18-Impulseingang bei Reset                       <<user-eingabe für IO-Shield-Plus<< 
}; 
//hier wird der Teilerfaktor für die Impulszaehler festgelegt
int pulsedivider[6] = 
{ 1, //Teilerfaktor D2 :                                                    <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D3 :                                                     <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D21 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D20 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D19 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D18 :                                                 <<user-eingabe für IO-Shield-Plus<<
}; 
 
//hier werden die zuletzt gesendeten sytemvariablen gespeichert
boolean last_digital_value_D[70];
float last_value_D[70];
float last_IR_value;
float last_RF_value;
float last_lux_value;
double last_baro_value;
double last_baroT_value;
 
boolean complete_loop =1; // wenn 1, dann einmal komplett durchlaufen
 
String header = String(20);
String befehl;
String sub_command = String(20);
String parameter = String(20);
int param;
int port_pin;
boolean port_data;
 
boolean value;
String I;
int analogwert;
 
float tempNTC;
float B_wert = 3950; //aus dem Datenblatt des NTC //<<user-eingabe<<
float Tn = 298.15; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
float Rt ; 
float temp_tur;
float humidity;
 
float delta_onewire = 0.2; //Deltas für Sendeauslösung 
float delta_DHT = 0.2; //in °C 
float delta_us = 3.0; // in cm
float delta_analog = 2.0; // in inkrement
float delta_ntc = 0.5; //in °C
float delta_lux = 20; //in lux
float delta_counter = 5; //in counter inkrement
double delta_baro = 0.2; //in mB
double delta_baroT = 0.5; //in °C
 
long duration, cm; //variable für Ultraschallsensor
 
unsigned long next_full_loop = 0;
unsigned long delta_time = 3600000; // jede Stunde werden alle Inputs aktualisiert
unsigned long delta_tx = 500; //in ms, minimaler Abstand der Telegramme an die CCU
unsigned long next_tx = 0;
unsigned long time_DHT = 0; 
 
int rf_key;
String rfkey;
RCSwitch mySwitch = RCSwitch();
 
//************************************************************************************************** 
AS_BH1750 sensor; //Initialize BH1750 Luxmeter library
#define ALTITUDE 299.0 // eigene seehoehe in metern              <<user-eingabe für IO-Shield-Plus<<
SFE_BMP180 pressure;
char status;
double T,P,p0;
 
boolean reading = false;
String command = String(200);
 
//************************************************************************************************** 
//************************************************************************************************** 
void setup() 
{Serial.begin(115200); 
 
//einrichtung der interrupts fuer impulszahler D2,D3,D18,D19,D20,D21
if ((pulsedivider[0] > 0) && (iomodus_D[2] == 6)) {pinMode(2, INPUT_PULLUP); attachInterrupt(0, ISR_0, FALLING);}
if ((pulsedivider[1] > 0) && (iomodus_D[3] == 6)) {pinMode(3, INPUT_PULLUP); attachInterrupt(1, ISR_1, FALLING);} 
if ((pulsedivider[2] > 0) && (iomodus_D[21] == 6)) {pinMode(21, INPUT_PULLUP); attachInterrupt(2, ISR_2, FALLING);}
if ((pulsedivider[3] > 0) && (iomodus_D[20] == 6)) {pinMode(20, INPUT_PULLUP); attachInterrupt(3, ISR_3, FALLING);}
if ((pulsedivider[4] > 0) && (iomodus_D[19] == 6)) {pinMode(19, INPUT_PULLUP); attachInterrupt(4, ISR_4, FALLING);}
#if com_mode == 0 
if ((pulsedivider[5] > 0) && (iomodus_D[18] == 6)) {pinMode(18, INPUT_PULLUP); attachInterrupt(5, ISR_5, FALLING);}
#endif 
 
 
//+++++++ hier folgt die LAN Initialisierung
 if (Ethernet.begin(mac) == 0) // start the Ethernet connection:
 {Serial.println("Failed to configure Ethernet using DHCP"); Ethernet.begin(mac, homeduino);}
 delay(1000);// give the Ethernet shield a second to initialize:
 Serial.println("connecting..."); // if you get a connection, report back via serial:
 if (client.connect(ccu, 8181)) {}
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop(); 
 char myIpString[24]; //IP auslesen
 IPAddress myIp = Ethernet.localIP();
 sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]); 
 I = myIpString;
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "IP" + "').State('" + I + "')";
 set_sysvar(); 
 server.begin();
 
/*
//+++++++ hier folgt die CC3000 Initialisierung
 ConnectionInfo connection_info;
 int i;
 byte IP_ADDR_LEN =4;
 Serial.println("SparkFun CC3000 - WebClient");
 if ( wifi.init() ) {Serial.println("init complete");} 
 else {Serial.println("problem with init!");}
 // Connect using DHCP
 if(!wifi.connect(ap_ssid, ap_security, ap_password, timeout)) {Serial.println("no connection to AP");}
 // Gather connection details and print IP address
 if ( !wifi.getConnectionInfo(connection_info) ) {Serial.println("no connection details");} 
 else {for (i = 0; i < IP_ADDR_LEN; i++) 
 {Serial.print(connection_info.ip_address[i]);
 if ( i < IP_ADDR_LEN - 1 ) {Serial.print(".");}
 }
 Serial.println(" ist aktuelle IP-Adresse"); 
 }
 
 if (client.connect(ccu, 8181)) {} // Make a TCP connection to remote host
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop();
*/
 
}
//************************************************************************************************** 
//************************************************************************************************** 
void loop() 
{complete_loop = 0;
 if (millis() > next_full_loop) //mindestens jede Stunde eine komplette Aktualisierung
 {complete_loop = 1; next_full_loop = millis() + delta_time; 
 if (next_full_loop < millis()) {complete_loop = 0;} //wichtig wegen Zahlensprung von millis() alle 50 Tage
 } 
 for (int i = 2; i < 70; i++) //behandlung aller Ports D2 bis D69 
 {if (i== 30) {i = 54;} // unbenutzte pins überspringen
 
 //************************************************************************************************** 
 if (iomodus_D[i] == 1) //behandlung digitaleingänge 
 {pinMode(i, INPUT_PULLUP); 
 digitalWrite(i, HIGH);
 value =digitalRead(i);
 if ((!value == last_digital_value_D[i]) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + value + ")";
 set_sysvar();
 last_digital_value_D[i] = value;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 3) //behandlung onewire 
 {pinMode(i, INPUT_PULLUP);
 digitalWrite(i, HIGH);
 OneWire ds(i); 
 #define DS18S20_ID 0x10
 #define DS18B20_ID 0x28 
 
 byte present = 0;
 byte data[12];
 byte addr[8];
 temp_tur = 1000.0;
 if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
 if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
 if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
 if (temp_tur > -1000.0) 
 {ds.reset(); 
 ds.select(addr); 
 ds.write(0x44, 1); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5 // Calculate temperature value 18S20
 }
 if ((temp_tur > (last_value_D[i] + delta_onewire)) 
 || (temp_tur < (last_value_D[i] - delta_onewire)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 4) //behandlung DHT temperatur- und feuchtesensoren
 {DHT dht(i, DHT22); //je nach verwendetem sensor "DHT11" oder "DHT22" (AM2302) oder "DHT 21" (AM2301)
 dht.begin();
 //delay(2000); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
 time_DHT = millis() +2000;
 while (millis() < time_DHT) {datenempfang();} //wahrend der 2s wartezeit, daten empfangen
 humidity = dht.readHumidity(); // Read temperature as Celsius
 temp_tur = dht.readTemperature(); 
 if (isnan(humidity) || isnan(temp_tur) ) // Check if any reads failed and 
 { //Serial.println("Failed to read from DHT sensor!");
 temp_tur = -1000;
 }
 if ((temp_tur > (last_value_D[i] + delta_DHT)) || (temp_tur < (last_value_D[i] - delta_DHT)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "1').State(" + humidity + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 } 
 //************************************************************************************************** 
 if (iomodus_D[i] == 5) //behandlung ultraschallsensoren achtung: zu beachten 
 //bei verwendung der US-Sensoren beim IO-Shield-Plus sind die 150-Ohm-Schutzwiderstände 
 //zu überbrücken , entsprechend beim IO-Shield20 der digitale Jumper 4-5 zu setzen!! 
 {NewPing sonar(i, i, 200); // NewPing setup of pin and maximum distance.
 unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
 int cm = uS / US_ROUNDTRIP_CM;
 if ((cm > (last_value_D[i] + delta_us)) || (cm < (last_value_D[i] - delta_us)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + cm + ")";
 set_sysvar();
 last_value_D[i] = cm;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 10) //behandlung analogeingänge 
 {analogwert =analogRead(i); 
 if ((analogwert > (last_value_D[i] + delta_analog)) || (analogwert < (last_value_D[i] - delta_analog)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + analogwert + ")";
 set_sysvar();
 last_value_D[i] = analogwert;
 } 
 } 
//**************************************************************************************************
 if (iomodus_D[i] == 11) //behandlung NTC 
 {Rt = Rv/((1024.0/analogRead(i))- 1.0);
 tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn +25.0 ;
 if ((tempNTC > (last_value_D[70] + delta_ntc)) || (tempNTC < (last_value_D[70] - delta_ntc)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + tempNTC + ")";
 set_sysvar();
 last_value_D[i] = tempNTC;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 6) //behandlung impulszahler D2,D3,D21,D20,D19,D18 
 {byte offset =23;
 if (i ==2) {offset = 4;} if (i ==3) {offset = 6;}
 zaehlwert = pulsecounter[offset - i ] / pulsedivider[offset - i ];
 if ((pulsedivider[offset -i] > 0) && ((zaehlwert > (last_zaehlwert[offset - i]+ delta_counter) || complete_loop))) 
 {I = String(offset -i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "imp" + I + "').State(" + zaehlwert + ")";
 set_sysvar();
 last_zaehlwert[offset - i] = zaehlwert;
 } 
 } 
//**************************************************************************************************
//behandlung Luxmeter BH1750 an SCL pin21 und SDA pin 20
// for normal sensor resolution (1 lx resolution, 0-65535 lx, 120ms, no PowerDown) use: sensor.begin(RESOLUTION_NORMAL, false); 
 if ((iomodus_D[20] == 1) && (iomodus_D[21] == 1) && (iomodus_lux ==1))
 {if(!sensor.begin()) { Serial.println("Sensor not present"); }
 float lux = sensor.readLightLevel(); delay(1000);
 Serial.print("Helligkeit/lux: "); Serial.print(lux); Serial.println();
 if ((lux > (last_lux_value + delta_lux)) || (lux < (last_lux_value - delta_lux)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "lux" + "').State(" + lux + ")";
 set_sysvar();
 last_lux_value = lux;
 } 
 } 
//**************************************************************************************************
//behandlung barometer BMP180 an SCL pin21 und SDA pin 20
 if ((iomodus_D[20] == 8) && (iomodus_D[21] == 8)&& (iomodus_baro ==1))
 {if (pressure.begin()) {status = pressure.startTemperature();}
 if (status) {delay(status); status = pressure.getTemperature(T);} //messung T
 if (status) {status = pressure.startPressure(3);} // //messung P mit resolution 0 bis 3
 if (status) {delay(status); status = pressure.getPressure(P,T);}
 if (status) {p0 = pressure.sealevel(P,ALTITUDE);} // umrechnung auf N.N.
 Serial.print("Hoehe/m: "); Serial.print(ALTITUDE); Serial.print(" Temperatur/C: "); Serial.print(T); Serial.print(" Normaldruck /mb: "); Serial.println(p0); 
 if ((p0 > (last_baro_value + delta_baro)) || (p0 < (last_baro_value - delta_baro)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baro" + "').State(" + p0 + ")";
 set_sysvar();
 last_baro_value = p0;
 }
 if ((T > (last_baroT_value + delta_baroT)) || (p0 < (last_baroT_value - delta_baroT)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baroT" + "').State(" + T + ")";
 set_sysvar();
 last_baroT_value = T;
 }
 }
 }
//**************************************************************************************************
 if (iomodus_D[3] == 7) //behandlung 433Mhz-rx 
 {if (mySwitch.available()) 
 {int value = mySwitch.getReceivedValue();
 if (value == 0) {client.print("Unknown encoding");} 
 else {Serial.print("Pin D3 received : ");
 Serial.print (mySwitch.getReceivedValue() );
 Serial.print (" / ");
 Serial.print( mySwitch.getReceivedBitlength() );
 Serial.print("bit Protocol: ");
 Serial.println( mySwitch.getReceivedProtocol() + " \n\r" );
 }
 mySwitch.resetAvailable();
 }
 } 
//**************************************************************************************************
 
datenempfang(); 
} 
 
//##############################################################
//##############################################################
void datenempfang() //Unterprogramm datenempfang: daten von ccu an homeduino
{command = ""; 
 
 EthernetClient client = server.available();   //mit W5100
 //SFE_CC3000_Client client = SFE_CC3000_Client(wifi);   //mit CC3000
 
 if (client) 
 { // an http request ends with a blank line
 boolean currentLineIsBlank = true;
 while (client.connected())
 {if (client.available()) 
 {char c = client.read();
 if (reading && c == ' ') reading =false;
 if (c == '?') reading = true; // beginn der Befehlssequenz 
 if (reading) 
 {//read char by char HTTP request
 if (command.length() < 100) 
 { //store characters to string
 command = command + c;
 }
 } 
 if (c == '\n' && currentLineIsBlank) break;
 if (c == '\n') {currentLineIsBlank = true;} 
 else if (c != '\r') { currentLineIsBlank = false;}
 } 
 } 
 client.println(command);
 delay(1); 
 client.stop();
//**************************************************************************************************
 if (command.length() > 2) //behandlung Datenempfang: port auf 0 / 1 setzen 
 {Serial.println(command); //empfangenen befehl ausgeben
 client.print(command); 
 //befehl dekodieren 
 int colonPosition = command.indexOf(':');
 sub_command = command.substring(2,colonPosition); //portpin erkennen
 Serial.print("D" + sub_command + " :");
 port_pin = sub_command.toInt();
 command = command.substring((colonPosition+1)); //Rest-command bilden
 if ((iomodus_D[port_pin] == 2) && (command == "0")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, LOW); Serial.println(command);}
 if ((iomodus_D[port_pin] == 2) && (command == "1")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, HIGH); Serial.println(command);}
 if ((iomodus_D[port_pin] == 7) && (port_pin ==4)) 
 { rf_send(command); Serial.println(command);} 
 if ((iomodus_D[port_pin] == 5) && (port_pin ==9)) 
 { ir_send(command); Serial.println(command);} 
 
 }
 
 } 
} 
//##############################################################
void set_sysvar() // subroutine HTTP request absetzen:
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;
 if (client.connect(ccu, 8181)) 
 {Serial.println(befehl);
 client.println(befehl);
 client.println();
 client.stop();
 }
}
//##############################################################
void rf_send(String rf_command) // subroutine rf telegramm senden
{
 }
//##############################################################
void ir_send(String ir_command) // subroutine ir telegramm senden
{
 }
 
//##############################################################
//hier sind die interrupt-service-routinen fuer die impulszaehler
void ISR_0() //Interrupt an D2
{pulsecounter[0]++;}
 
void ISR_1() //Interrupt an D3
{pulsecounter[1]++;}
 
 
void ISR_2() //Interrupt an D21
{pulsecounter[2]++;}
 
void ISR_3() //Interrupt an D20
{pulsecounter[3]++;}
 
void ISR_4() //Interrupt an D19
{pulsecounter[4]++;}
 
void ISR_5() //Interrupt an D18 
{pulsecounter[5]++;}

 

 

Und hier die Wifi-Version :

/*Ver.: "homeduino30_03_wifi.ino / Stand: 2015.05.07 / Verfasser: Eugen Stall
 
Wifi-Version mit CC3000-Breakout
 
hier ist immer die aktuelle Version:
Home
das folgende homeduino-programm sendet messdaten zur ccu (homeduino als webclient) ...
und empfängt ausgabedaten für die homeduino-outputs (homeduino als webserver)
____________________ ___________________
 | | 
 server port 8181 |<------------<| client 
 | | 
 CCU | | Homeduino 
 | | 
 client |>------------>| server port 80
____________________| |___________________
 
erprobt fuer Arduino Mega 2560 mit Arduino 1.6.3
diese Software steuert referenziert die signale an den Arduino-pins mit entsprechenden systemvariablen in der Homematic ccu
mit dem Befehl: http://<ip der ccu>:8181/GET /xy.exe?antwort=dom.GetObject('<systemvariable>').State(" + value + ")"
/Quellen:Arduino website plus http://arduino.cc/en/Tutorial/WebClient und ...
 http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino und ...
*/
 
#include <SPI.h>
#include <Wire.h> 
#include <OneWire.h> //für Temperatursensoren DS18B20 http://www.hacktronics.com/code/OneWire.zip
#include <NewPing.h> //für Ultraschallsensoren SR04 https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip
#include "DHT.h" //für Temperatursensoren SHT22 https://github.com/adafruit/DHT-sensor-library/archive/master.zip
#include <AS_BH1750.h> //für I2C-Luxmeter https://github.com/hexenmeister/AS_BH1750/archive/master.zip
#include <SFE_BMP180.h>//für I2C-Barometer https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
#include <RCSwitch.h> // läuft noch nicht!
//#include <IRremote.h> // läuft noch nicht!
 
//Kommunikationsweg  festlegen
#define com_mode 1  //"0"  W5100, "1" CC300 Breakout                                     <<user-eingabe<< 
 
 
//der folgende Bereich ist die Initialisierung des CC3000 Wifi auf dem IO-Shield-Plus 
#include <SFE_CC3000.h>// fuer cc3000 wifi http://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip
#include <SFE_CC3000_Client.h>
// Pins
#define CC3000_INT 18 // int-Pin mit Wifi Shield ist D3, mit breakout auf IO-Shield-Plus ist D18
#define CC3000_EN 46 // en-Pin mit Wifi Shield ist D5, mit breakout auf IO-Shield-Plus ist D46
#define CC3000_CS 53 // cs-Pin mit Wifi Shield ist D10, mit breakout auf IO-Shield-Plus ist D53
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
// Constants
char ap_ssid[] = "ssid"; // SSID Name des WLAN in Anführungszeichen                       <<user-eingabe<< 
char ap_password[] = "passwort"; // Passwort des WLAN in Anführungszeichen                <<user-eingabe<< 
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
unsigned int timeout = 30000; // Milliseconds
//char server[] = "192,168,178,50"; // Remote host site
 
/*
//der folgende Bereich ist die Initialisierung des LAN bei Verwendung des LAN-Shields
#include <Ethernet.h> 
EthernetClient client;
EthernetServer server(80);
*/
 
byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU <<user-eingabe<< 
byte mac[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; //bei mehreren homeduinos ändern!!    <<user-eingabe<<
byte homeduino[] = { 192, 168, 178, 52 }; //das ist feste IP dieses Homeduino,             <<user-eingabe<< 
 //wenn DHCP versagt
String homeduino_nummer = "xyz"; //indiv. Bezeichnung dieses homeduino                     <<user-eingabe<< 
 //das ist bel. String ohne 
 //sonderzeichen und öäüß... 
String hm_systemvariable = "homeduino_" + homeduino_nummer +"_";
 
 
//Input-Kennung: hier wird die Funktion aller verwendbaren IO´s mit einer Kennziffer festgelegt 
//dabei haben alle IO´s die Standardfunktionen plus spez. Sonderfunktionen
byte iomodus_D[70] = 
{ 0, //D0 : '0' = andere Nutzg; 
 0, //D1 : '0' = andere Nutzg; 
 
//Standardfkt:'0' =andere Nutzg; '1' =dig_input; '2' =dig_output; '3' =1wire '4' =DHTxx; '5' =U_Schall 
 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield20 +++++++++++++++++ 
 2, //D2 : Standardfkt; '5' = IR_Rx?? '6' =ImpCount;                        <<user-eingabe für IO-Shield20<< 
 2, //D3 : Standardfkt; '7' = 433_Rx?? '6' =ImpCount;                       <<user-eingabe für IO-Shield20<< 
 0, //D4 : Standardfkt; '7' = 433_Tx?? '0' =W5100/SS-Pin                    <<user-eingabe für IO-Shield20<< 
 2, //D5 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D6 : Standardfkt; '9' = buzzer                                        <<user-eingabe für IO-Shield20<< 
 0, //D7 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D8 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 1, //D9 : Standardfkt; '5' = IR_Tx??                                       <<user-eingabe für IO-Shield20<< 
 0, //D10 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D11 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D12 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D13 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield_Plus ++++++++++++++ 
 3, //D14 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D15 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D16 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D17 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 0, //D18 : Standardfkt; '6' =ImpCount; '0' =CC3000                     <user-eingabe für IO-Shield-Plus20<< 
 3, //D19 : Standardfkt; '6' =ImpCount;                                 <user-eingabe für IO-Shield-Plus20<< 
 1, //D20 : Standardfkt; '6' =ImpCount; '8' =I2C;SDA                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D21 : Standardfkt; '6' =ImpCount; '8' =I2C;SCL                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D22 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D23 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D24 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D25 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D26 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D27 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D28 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D29 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
//hier wird die Funktion der Eingänge A0 bis A15 festgelegt
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield20 ++++++++++++++++++
 3, //D54 A0 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 2, //D55 A1 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D56 A2 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D57 A3 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D58 A4 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D59 A5 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D60 A6 : "0" =andere Nutzg; 
 0, //D61 A7 : "0" =andere Nutzg; 
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield_Plus +++++++++++++++
 1, //D62 A8 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D63 A9 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D64 A10 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D65 A11 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D66 A12 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D67 A13 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D68 A14 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1 //D69 A15 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
}; 
//hier werden Sensoren am I2C-Eingang aktiviert
byte iomodus_baro = 0; //'0' =nc; '1' =BMP180, dann auch oben I2C setzen <<user-eingabe für IO-Shield-Plus<<
byte iomodus_lux = 0; //'0' =nc; '1' =BH1750, dann auch oben I2C setzen  <<user-eingabe für IO-Shield-Plus<<
 
//hier werden die Kennwerte fuer die Impulszaehler festgelegt
unsigned zaehlwert;
unsigned last_zaehlwert[6] = {0,0,0,0,0,0};
volatile unsigned long pulsecounter[6] = 
{ 0, //Zaehlerstand fuer D2 -Impulseingang bei Reset                        <<user-eingabe für IO-Shield20<<
 0, //Zaehlerstand fuer D3 -Impulseingang bei Reset                         <<user-eingabe für IO-Shield20<<
 4711, //Zaehlerstand fuer D21-Impulseingang bei Reset                   <<user-eingabe für IO-Shield-Plus<< 
 3, //Zaehlerstand fuer D20-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 4, //Zaehlerstand fuer D19-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 5 //Zaehlerstand fuer D18-Impulseingang bei Reset                       <<user-eingabe für IO-Shield-Plus<< 
}; 
//hier wird der Teilerfaktor für die Impulszaehler festgelegt
int pulsedivider[6] = 
{ 1, //Teilerfaktor D2 :                                                    <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D3 :                                                     <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D21 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D20 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D19 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D18 :                                                 <<user-eingabe für IO-Shield-Plus<<
}; 
 
//hier werden die zuletzt gesendeten sytemvariablen gespeichert
boolean last_digital_value_D[70];
float last_value_D[70];
float last_IR_value;
float last_RF_value;
float last_lux_value;
double last_baro_value;
double last_baroT_value;
 
boolean complete_loop =1; // wenn 1, dann einmal komplett durchlaufen
 
String header = String(20);
String befehl;
String sub_command = String(20);
String parameter = String(20);
int param;
int port_pin;
boolean port_data;
 
boolean value;
String I;
int analogwert;
 
float tempNTC;
float B_wert = 3950; //aus dem Datenblatt des NTC //<<user-eingabe<<
float Tn = 298.15; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
float Rt ; 
float temp_tur;
float humidity;
 
float delta_onewire = 0.2; //Deltas für Sendeauslösung 
float delta_DHT = 0.2; //in °C 
float delta_us = 3.0; // in cm
float delta_analog = 2.0; // in inkrement
float delta_ntc = 0.5; //in °C
float delta_lux = 20; //in lux
float delta_counter = 5; //in counter inkrement
double delta_baro = 0.2; //in mB
double delta_baroT = 0.5; //in °C
 
long duration, cm; //variable für Ultraschallsensor
 
unsigned long next_full_loop = 0;
unsigned long delta_time = 3600000; // jede Stunde werden alle Inputs aktualisiert
unsigned long delta_tx = 500; //in ms, minimaler Abstand der Telegramme an die CCU
unsigned long next_tx = 0;
unsigned long time_DHT = 0; 
 
int rf_key;
String rfkey;
RCSwitch mySwitch = RCSwitch();
 
//************************************************************************************************** 
AS_BH1750 sensor; //Initialize BH1750 Luxmeter library
#define ALTITUDE 299.0 // eigene seehoehe in metern              <<user-eingabe für IO-Shield-Plus<<
SFE_BMP180 pressure;
char status;
double T,P,p0;
 
boolean reading = false;
String command = String(200);
 
//************************************************************************************************** 
//************************************************************************************************** 
void setup() 
{Serial.begin(115200); 
 
//einrichtung der interrupts fuer impulszahler D2,D3,D18,D19,D20,D21
if ((pulsedivider[0] > 0) && (iomodus_D[2] == 6)) {pinMode(2, INPUT_PULLUP); attachInterrupt(0, ISR_0, FALLING);}
if ((pulsedivider[1] > 0) && (iomodus_D[3] == 6)) {pinMode(3, INPUT_PULLUP); attachInterrupt(1, ISR_1, FALLING);} 
if ((pulsedivider[2] > 0) && (iomodus_D[21] == 6)) {pinMode(21, INPUT_PULLUP); attachInterrupt(2, ISR_2, FALLING);}
if ((pulsedivider[3] > 0) && (iomodus_D[20] == 6)) {pinMode(20, INPUT_PULLUP); attachInterrupt(3, ISR_3, FALLING);}
if ((pulsedivider[4] > 0) && (iomodus_D[19] == 6)) {pinMode(19, INPUT_PULLUP); attachInterrupt(4, ISR_4, FALLING);}
#if com_mode == 0 
if ((pulsedivider[5] > 0) && (iomodus_D[18] == 6)) {pinMode(18, INPUT_PULLUP); attachInterrupt(5, ISR_5, FALLING);}
#endif 
 
/*
//+++++++ hier folgt die LAN Initialisierung
 if (Ethernet.begin(mac) == 0) // start the Ethernet connection:
 {Serial.println("Failed to configure Ethernet using DHCP"); Ethernet.begin(mac, homeduino);}
 delay(1000);// give the Ethernet shield a second to initialize:
 Serial.println("connecting..."); // if you get a connection, report back via serial:
 if (client.connect(ccu, 8181)) {}
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop(); 
 char myIpString[24]; //IP auslesen
 IPAddress myIp = Ethernet.localIP();
 sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]); 
 I = myIpString;
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "IP" + "').State('" + I + "')";
 set_sysvar(); 
 server.begin();
*/ 
 
//+++++++ hier folgt die CC3000 Initialisierung
 ConnectionInfo connection_info;
 int i;
 byte IP_ADDR_LEN =4;
 Serial.println("SparkFun CC3000 - WebClient");
 if ( wifi.init() ) {Serial.println("init complete");} 
 else {Serial.println("problem with init!");}
 // Connect using DHCP
 if(!wifi.connect(ap_ssid, ap_security, ap_password, timeout)) {Serial.println("no connection to AP");}
 // Gather connection details and print IP address
 if ( !wifi.getConnectionInfo(connection_info) ) {Serial.println("no connection details");} 
 else {for (i = 0; i < IP_ADDR_LEN; i++) 
 {Serial.print(connection_info.ip_address[i]);
 if ( i < IP_ADDR_LEN - 1 ) {Serial.print(".");}
 }
 Serial.println(" ist aktuelle IP-Adresse"); 
 }
 
 if (client.connect(ccu, 8181)) {} // Make a TCP connection to remote host
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop();
 
 
}
//************************************************************************************************** 
//************************************************************************************************** 
void loop() 
{complete_loop = 0;
 if (millis() > next_full_loop) //mindestens jede Stunde eine komplette Aktualisierung
 {complete_loop = 1; next_full_loop = millis() + delta_time; 
 if (next_full_loop < millis()) {complete_loop = 0;} //wichtig wegen Zahlensprung von millis() alle 50 Tage
 } 
 for (int i = 2; i < 70; i++) //behandlung aller Ports D2 bis D69 
 {if (i== 30) {i = 54;} // unbenutzte pins überspringen
 
 //************************************************************************************************** 
 if (iomodus_D[i] == 1) //behandlung digitaleingänge 
 {pinMode(i, INPUT_PULLUP); 
 digitalWrite(i, HIGH);
 value =digitalRead(i);
 if ((!value == last_digital_value_D[i]) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + value + ")";
 set_sysvar();
 last_digital_value_D[i] = value;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 3) //behandlung onewire 
 {pinMode(i, INPUT_PULLUP);
 digitalWrite(i, HIGH);
 OneWire ds(i); 
 #define DS18S20_ID 0x10
 #define DS18B20_ID 0x28 
 
 byte present = 0;
 byte data[12];
 byte addr[8];
 temp_tur = 1000.0;
 if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
 if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
 if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
 if (temp_tur > -1000.0) 
 {ds.reset(); 
 ds.select(addr); 
 ds.write(0x44, 1); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5 // Calculate temperature value 18S20
 }
 if ((temp_tur > (last_value_D[i] + delta_onewire)) 
 || (temp_tur < (last_value_D[i] - delta_onewire)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 4) //behandlung DHT temperatur- und feuchtesensoren
 {DHT dht(i, DHT22); //je nach verwendetem sensor "DHT11" oder "DHT22" (AM2302) oder "DHT 21" (AM2301)
 dht.begin();
 //delay(2000); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
 time_DHT = millis() +2000;
 while (millis() < time_DHT) {datenempfang();} //wahrend der 2s wartezeit, daten empfangen
 humidity = dht.readHumidity(); // Read temperature as Celsius
 temp_tur = dht.readTemperature(); 
 if (isnan(humidity) || isnan(temp_tur) ) // Check if any reads failed and 
 { //Serial.println("Failed to read from DHT sensor!");
 temp_tur = -1000;
 }
 if ((temp_tur > (last_value_D[i] + delta_DHT)) || (temp_tur < (last_value_D[i] - delta_DHT)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "1').State(" + humidity + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 } 
 //************************************************************************************************** 
 if (iomodus_D[i] == 5) //behandlung ultraschallsensoren achtung: zu beachten 
 //bei verwendung der US-Sensoren beim IO-Shield-Plus sind die 150-Ohm-Schutzwiderstände 
 //zu überbrücken , entsprechend beim IO-Shield20 der digitale Jumper 4-5 zu setzen!! 
 {NewPing sonar(i, i, 200); // NewPing setup of pin and maximum distance.
 unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
 int cm = uS / US_ROUNDTRIP_CM;
 if ((cm > (last_value_D[i] + delta_us)) || (cm < (last_value_D[i] - delta_us)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + cm + ")";
 set_sysvar();
 last_value_D[i] = cm;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 10) //behandlung analogeingänge 
 {analogwert =analogRead(i); 
 if ((analogwert > (last_value_D[i] + delta_analog)) || (analogwert < (last_value_D[i] - delta_analog)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + analogwert + ")";
 set_sysvar();
 last_value_D[i] = analogwert;
 } 
 } 
//**************************************************************************************************
 if (iomodus_D[i] == 11) //behandlung NTC 
 {Rt = Rv/((1024.0/analogRead(i))- 1.0);
 tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn +25.0 ;
 if ((tempNTC > (last_value_D[70] + delta_ntc)) || (tempNTC < (last_value_D[70] - delta_ntc)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + tempNTC + ")";
 set_sysvar();
 last_value_D[i] = tempNTC;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 6) //behandlung impulszahler D2,D3,D21,D20,D19,D18 
 {byte offset =23;
 if (i ==2) {offset = 4;} if (i ==3) {offset = 6;}
 zaehlwert = pulsecounter[offset - i ] / pulsedivider[offset - i ];
 if ((pulsedivider[offset -i] > 0) && ((zaehlwert > (last_zaehlwert[offset - i]+ delta_counter) || complete_loop))) 
 {I = String(offset -i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "imp" + I + "').State(" + zaehlwert + ")";
 set_sysvar();
 last_zaehlwert[offset - i] = zaehlwert;
 } 
 } 
//**************************************************************************************************
//behandlung Luxmeter BH1750 an SCL pin21 und SDA pin 20
// for normal sensor resolution (1 lx resolution, 0-65535 lx, 120ms, no PowerDown) use: sensor.begin(RESOLUTION_NORMAL, false); 
 if ((iomodus_D[20] == 1) && (iomodus_D[21] == 1) && (iomodus_lux ==1))
 {if(!sensor.begin()) { Serial.println("Sensor not present"); }
 float lux = sensor.readLightLevel(); delay(1000);
 Serial.print("Helligkeit/lux: "); Serial.print(lux); Serial.println();
 if ((lux > (last_lux_value + delta_lux)) || (lux < (last_lux_value - delta_lux)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "lux" + "').State(" + lux + ")";
 set_sysvar();
 last_lux_value = lux;
 } 
 } 
//**************************************************************************************************
//behandlung barometer BMP180 an SCL pin21 und SDA pin 20
 if ((iomodus_D[20] == 8) && (iomodus_D[21] == 8)&& (iomodus_baro ==1))
 {if (pressure.begin()) {status = pressure.startTemperature();}
 if (status) {delay(status); status = pressure.getTemperature(T);} //messung T
 if (status) {status = pressure.startPressure(3);} // //messung P mit resolution 0 bis 3
 if (status) {delay(status); status = pressure.getPressure(P,T);}
 if (status) {p0 = pressure.sealevel(P,ALTITUDE);} // umrechnung auf N.N.
 Serial.print("Hoehe/m: "); Serial.print(ALTITUDE); Serial.print(" Temperatur/C: "); Serial.print(T); Serial.print(" Normaldruck /mb: "); Serial.println(p0); 
 if ((p0 > (last_baro_value + delta_baro)) || (p0 < (last_baro_value - delta_baro)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baro" + "').State(" + p0 + ")";
 set_sysvar();
 last_baro_value = p0;
 }
 if ((T > (last_baroT_value + delta_baroT)) || (p0 < (last_baroT_value - delta_baroT)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baroT" + "').State(" + T + ")";
 set_sysvar();
 last_baroT_value = T;
 }
 }
 }
//**************************************************************************************************
 if (iomodus_D[3] == 7) //behandlung 433Mhz-rx 
 {if (mySwitch.available()) 
 {int value = mySwitch.getReceivedValue();
 if (value == 0) {client.print("Unknown encoding");} 
 else {Serial.print("Pin D3 received : ");
 Serial.print (mySwitch.getReceivedValue() );
 Serial.print (" / ");
 Serial.print( mySwitch.getReceivedBitlength() );
 Serial.print("bit Protocol: ");
 Serial.println( mySwitch.getReceivedProtocol() + " \n\r" );
 }
 mySwitch.resetAvailable();
 }
 } 
//**************************************************************************************************
 
datenempfang(); 
} 
 
//##############################################################
//##############################################################
void datenempfang() //Unterprogramm datenempfang: daten von ccu an homeduino
{command = ""; 
 
 //EthernetClient client = server.available();   //mit W5100
 SFE_CC3000_Client client = SFE_CC3000_Client(wifi);   //mit CC3000
 
 if (client) 
 { // an http request ends with a blank line
 boolean currentLineIsBlank = true;
 while (client.connected())
 {if (client.available()) 
 {char c = client.read();
 if (reading && c == ' ') reading =false;
 if (c == '?') reading = true; // beginn der Befehlssequenz 
 if (reading) 
 {//read char by char HTTP request
 if (command.length() < 100) 
 { //store characters to string
 command = command + c;
 }
 } 
 if (c == '\n' && currentLineIsBlank) break;
 if (c == '\n') {currentLineIsBlank = true;} 
 else if (c != '\r') { currentLineIsBlank = false;}
 } 
 } 
 client.println(command);
 delay(1); 
 client.stop();
//**************************************************************************************************
 if (command.length() > 2) //behandlung Datenempfang: port auf 0 / 1 setzen 
 {Serial.println(command); //empfangenen befehl ausgeben
 client.print(command); 
 //befehl dekodieren 
 int colonPosition = command.indexOf(':');
 sub_command = command.substring(2,colonPosition); //portpin erkennen
 Serial.print("D" + sub_command + " :");
 port_pin = sub_command.toInt();
 command = command.substring((colonPosition+1)); //Rest-command bilden
 if ((iomodus_D[port_pin] == 2) && (command == "0")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, LOW); Serial.println(command);}
 if ((iomodus_D[port_pin] == 2) && (command == "1")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, HIGH); Serial.println(command);}
 if ((iomodus_D[port_pin] == 7) && (port_pin ==4)) 
 { rf_send(command); Serial.println(command);} 
 if ((iomodus_D[port_pin] == 5) && (port_pin ==9)) 
 { ir_send(command); Serial.println(command);} 
 
 }
 
 } 
} 
//##############################################################
void set_sysvar() // subroutine HTTP request absetzen:
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;
 if (client.connect(ccu, 8181)) 
 {Serial.println(befehl);
 client.println(befehl);
 client.println();
 client.stop();
 }
}
//##############################################################
void rf_send(String rf_command) // subroutine rf telegramm senden
{
 }
//##############################################################
void ir_send(String ir_command) // subroutine ir telegramm senden
{
 }
 
//##############################################################
//hier sind die interrupt-service-routinen fuer die impulszaehler
void ISR_0() //Interrupt an D2
{pulsecounter[0]++;}
 
void ISR_1() //Interrupt an D3
{pulsecounter[1]++;}
 
 
void ISR_2() //Interrupt an D21
{pulsecounter[2]++;}
 
void ISR_3() //Interrupt an D20
{pulsecounter[3]++;}
 
void ISR_4() //Interrupt an D19
{pulsecounter[4]++;}
 
void ISR_5() //Interrupt an D18 
{pulsecounter[5]++;}

 

 

Damit ist es jetzt möglich, auch Daten von der CCU  an den Homeduino zu senden, um beispielsweise einen beliebigen Port zu setzen. Der Weg zurück erfolgt automatisch, indem bei Veränderung der Sensorsignale die korrespondierenden Systemvariablen gesetzt werden.

Eine detaillierte Anleitung und Beschreibung erfolgt später. Wichtig: Gegenüber den bisherigen Versionen wurde aus verschiedenen Gründen die Portbezeichnung und die Port-Funktionskennung geändert. Mein aktueller Homeduino heißt homeduino_xyz. Wichtig bei der richtigen Benennung der verwendeten Systemvariablen !

 

Ein Beispiel für ein HM-Skript, mit dem man einen Ausgang auf dem Homeduino schalten kann ist hier:

 

var send_data = "homeduino_xyz/D9:0"; !##########################
!beim  "homeduino_xyz"  Pin D9 auf 0 / 1 setzen #####  Stand 12.04.2015  stall.biz  
integer word_position = send_data.Find("/");
var h_duino = send_data.Substr(0, word_position) + "_IP";
h_duino = dom.GetObject(h_duino).State();
send_data = "http://" + h_duino + "/?" + send_data.Substr(word_position+1, 30);
string stdout;
string stderr;
 
!verwendung system.Exec
!system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);
 
!verwendung CUxD
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#send_data#"'");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
stdout = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
 
!fehler behandlung fehlt noch
boolean fehler = 1;
if (stdout.Length() >0) {fehler =0;} 
dom.GetObject("CUxD.CUX2801001:1.SYSLOG").State("eine Statusmeldung");

 

Wichtig:
Die neue Homeduino 3.0 Software ist sowohl für das
>>> Basis-Shield  IO-Shield20 als auch für das …
>>> Ergänzungs-Shield IO-Shield-Plus geeignet!

Rückmeldungen und Erfahrungen sind willkommen.

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.

 

 

 

IO-Shield-Plus … mehr Inputs und integriertes WLAN

IO-Shield-Plus … mehr Inputs und integriertes WLAN

Vorgeschichte:

Auf dieser Webseite sind verschiedene Bauanleitungen mit Verwendung der äußerst vielseitigen und preiswerten Arduino-Module im Zusammenspiel mit der  Homematic vorgestellt. Zur einfachen Anwendung auch für den weniger versierten Elektroniker ist ein sehr praktisches Anschlußboard IO-Shield20  entstanden.  In Verbindung mit der kostenlosen Homeduino Software  lassen sich damit eine Vielzahl von Sensoren über einfache Schraubklemmen anschließen und die Sensorsignale über LAN oder WLAN an die Homematic übertragen. . Mehr dazu hier:

https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic

https://www.stall.biz/?project=vielseitiges-io-shield-board-2-0-fur-fast-alle-arduinos

Der Vorteil bei Verwendung des IO-Shield-Plus als Homeduino-Sensormodul ist, daß auf der Homematic keinerlei komplizierte Skripte o.ä. installiert werden müssen. Lediglich ist für jede Meßgröße eine entsprechende Systemvariable in der CCU festzulegen. Die Aktualisierung mit den Meßwerten aus dem Homeduino erfolgt automatisch, aber nur wenn  sich der Meßwert ändert. Damit entsteht ein sehr geringer Traffic im Netz, was insbesondere bei vielen Homeduinos von Vorteil ist.

Warum ein weiteres IO-Shield ?

Das hier vorgestellte  IO-Shield-Plus ist nicht ein Ersatz für das bisherige IO-Shield20, sondern eine wichtige Ergänzung. Dabei spielt eine wesentliche Rolle, daß für die Verwendung von weiteren Shields beispielsweise zur  LCD-Anzeige und zur Bereitstellung des WLAN oft recht viele Pins des Standard-Arduino-Pinouts für den Betrieb des Shields belegt werden. Für die eigentliche Automatisierungsaufgabe bleiben dann oft nur wenige Funktionspins übrig. Aber gerade beim MEGA2560 sind ja noch viele IO´s auf dem hinteren Teil der Platine verfügbar, die mit diesem Erweiterungsshield an Schraubklemmen verfügbar gemacht werden können. Vorne lassen sich  dann Shields beispielsweise für ein alphanumerisches Display oder ein Touch-Display aufstecken. Weiter unten sind Beispiele für typische Konfigurationen.

Eigenschaften des IO-Shield-Plus

Das IO-Shield-Plus wird mit Stiftleisen auf die hinteren Pins des MEGA2560 aufgesteckt. Mittels Schraubklemmen lassen sich verschiedene Sensoren anschließen. Für die  WLAN-Module sind Steckplätze vorhanden. Man kann dort das sehr leistungsfähige Wifi-Modul CC3000 von Texas Instruments und das besonders preisgünstige Modul ESP8266-01 einstecken. Das folgende Bild  zeigt das IO-Shield-Plus von der Bestückungsseite:

platine2

Alle Inputs sind mit 150Ohm-Widerständen gegen Kurzschluß geschützt. Für mögliche Störprobleme bei längeren Sensorleitungen lassen sich an den Inputs keramische Kondensatoren nachträglich einlöten. Ein 3,3V-Spannungsregler versorgt aktuell das Wifi-Modul, kann aber auch zur Versorgung von anderen 3.3V-Verbrauchern verwendet werden. Für den Anschluß der potentialfreien S0-Schnittstellen sind 4 Optokoppler ebenfalls auf der Platine.

Hier die Eigenschaften des IO-Shield-Plus im Detail:

  •   insgesamt 24  digital und analog nutzbare Funktionsports  werden insgesamt nach außen auf Schraubklemmen geführt  . Diese Inputs sind individuell aufgeteilt nutzbar als…
  •  24   digitale Inputs
  •     4   Impulseingänge direkt oder über Optokoppler (S0-Schnittstellen) ,
    (in Verbindung mit dem CC3000 sind nur 3 Impulseingänge verfügbar)
  •    8   analoge Inputs  mit Eingangsspannung alle von 0 bis 5V oder 0 bis 1V (wenn Uref umgeschaltet wird )
  •    8   NTC-Temperatursensoren 10kOhm  mit über Jumper zuschaltbarem 10kOhm-Widerstand
  •  24   1Wire-Temperatursensoren  DS18B20
  •  24   DHT-22 digitale Temperatursensoren
  •  24   Ultraschallsensoren

Da IO-Shield-Plus hat eine Größe von 100mm x 55mm und kann mit den Stiften auf der Unterseite direkt auf die entsprechenden Buchsenleisen des MEGA2560 aufgesteckt werden. Dabei läßt sich das Shield alleine betreiben aber auch in Kombination mit dem universellen IO-Shield20:

Folie7

 

Anwendungsmöglichkeiten

Natürlich läßt sich das Shield ganz normal in einem StandAlone-Arduino betreiben, um etwas zu steuern und zu regeln. Aber bei der Auslegung des IO–Shield-Plus wurde besonderer Wert auf eine einfache Anbindung über WLAN an die CCU der Homematic gelegt. Deswegen sind Stecksockel für geeignete Wifi-Module auf dem Board, so daß sehr einfach eine WLAN-Funktionalität erreicht werden kann. Damit bleibt der „normale“ Steckplatz für andere Shields frei und somit eröffnen sich flexible Kombinationsmöglichkeiten mit vielen Standard-Shields. Die folgenden Bilder sollen dazu einen Eindruck verschaffen:

Folie8

 

Folie5

 

Folie6

 

 

Installation des WLAN-Moduls CC3000

Als Wifi-Module können der CC3000 von Texas Instruments verwendet werden , aber auch der sehr preisgünstige Chip ESP8266-01 eines chinesischen Herstellers. Die Steuerung des CC3000 erfolgt über die sog. SPI-Schnittstelle, welche  auf dem MEGA2560 mit den Datenpins D50 bis D53 verfügbar ist. Zusätzlich werden noch die Pins D46 und D18 verwendet. Dabei ist zu beachten, daß der D18 im IO-Angebot des IO-Shields-Plus  nicht mehr für eine Zählerfunktion o.ä. verwendet werden kann.

Das CC3000-Modul ist als sog. Breakout in einschlägigen meist chinesischen Internet-Shops bereits für etwa 20€ verfügbar. Suchbegriff z.B. bei Aliexpress oder ebay „cc3000  breakout“.

Das Breakout-Modul ist nahezu fertig; es muß lediglich die mitgelieferte Stiftleiste eingelötet werden. Dabei hat man die Wahl, die Stiftleisten auf der  Rückseite oder der Bestückungsseite einzulöten. Dementsprechend zeigt das Modul später im eingesteckten Zustand auf dem Board nach hinten oder nach vorn. Ich habe die Stifte auf der Rückseite eingelötet:

cc3000_hand

Zusammenbau des IO-Shield-Plus

Das IO-Shield-Plus ist  in meinem Shop als Bausatz erhältlich. Wegen der Verwendung von relativ großen Standardteilen kann auch ein weniger versierter Elektronikbastler das Board einfach montieren und verlöten. Das folgende Bild zeigt die Stückliste und den Einbau der Einzelteile:

IO_plus_bestueck

 Anschlussschema

Der Anschluss der Sensoren und Module erfolgt im wesentlichen mit den vielen verfügbaren Schraubklemmen. Für die analogen Eingänge sind noch per Jumper zuschaltbare 10kOhm-Pullups vorhanden, was für die einfache Aplikation von 10kOhm-NTC-Thermosensoren hilfreich ist. Auch typische Sensoren mit Pullup-Bedarf wie der digitale Temperatursensor DS 18B20  kann ohne Zusatzbauelemente an den Pins A08 bis A15 betrieben werden.

Für Anschluß von verbreiteten Modulen mit I2C-Bus ist auch ein Lötanschluß verfügbar. Der auf dem Board integrierte 3,3V-Spannungsregler ist auch für Module verwendbar, wenn zur Kommunikation der ESP8266 nicht verwendet wird.

Die Wlan-Module haben beide einen Steckanschluss und müssen einfach nur seitenrichtig eingesteckt werden.

Der Rest wird mit der Homeduino-Software eingestellt und konfiguriert.

Zur Hilfestellung beim Zusammenbau gibt´s auch eine Bauanleitung : Bauanleitung_shield_plus

Viel Spaß und Erflog mit dem Teilchen :))

Folie2

 

 

 Wo bekommt man das IO-Shield-Plus?

Wer das IO-Shield-Plus nachbauen möchte, kann über meinen Webshop einen Bausatz mit allen Teilen außer dem Wifi-Modul beziehen. Der Zusammenbau ist einfach, da nur relativ große Standardteile verlötet werden müssen.

https://www.stall.biz/?post_type=product&p=1634

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.

 

 

 

 

Der Homeduino 2.0 mit CC3000-Wifi-Shield als Sensormodul für die Homematic

Der Homeduino 2.0 mit CC3000-Wifi-Shield als Sensormodul für die Homematic

Wichtiger Hinweis: Es gibt mittlerweile eine neue Softwareversion:   Homduino 4.0

 

In einem anderen Artikel auf dieser Website  wird beschrieben, wie man den Homeduino als universelles Sensormodul für die Homematic verwenden kann. Zur Kommmunikation wird dort entweder das Ethernet-LAN verwendet oder WLAN über einen separaten Repeater. https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic

Mittlerweile gibt es aber schon relativ preiswerte WLAN oder Wifi-Shields und sog. Breakout-Module auf Basis des Funkmoduls CC3000 von Texas Instruments. Dieses Modul hat den Vorteil, daß zur Kommunikation fast die gleichen Pins und ähnliche Libraries wie bei  dem verbreiteten Ethernet-Shield W5100 verwendet werden. Die Anpassung der Homeduino-Software ist deshalb sehr einfach.

Das Sensormodul  mit Wifi-Shield CC3000

Anbieter für entsprechende Module und Shields mit dem CC300 sind Adafruit https://learn.adafruit.com/search?q=cc3000 und Sparkfun https://www.sparkfun.com/products/12071 . Jeder bietet auch eine Library an, die aber nicht direkt austauschbar ist, weil die Pinbelegung  unterschiedlich ist.

Adafruit verwendet:   Pin D3,   Pin D5   und Pin D10, D11, D12, D13

Sparkfun verwendet:   Pin D2,   Pin D7 und Pin D10, D11, D12, D13

Dies muß man wissen, wenn CC3000-Shields oder Breakouts des einen oder anderen Herstellers eingesetzt werden. Die Libraries lassen sich von beiden genannten Herstellern verwenden, wenn man die Pinbelegung in den Beispielsketchen entsprechend korrigiert.

Ich selbst verwende das nachfolgend  verwendete Noname -Wifi-Shield, welches man in China schon für etwa 20€ kaufen kann.

wifi_shield1

 

Dieses Shield verwendet die Adafruit Pinbelegung  mit D3, D5 und D10 !

Darüberhinaus sind für den auf dem Shield integrierten SD-Kartenslot  noch weitere Pins belegt, die wir aber für das Homeduino Sensormodul nicht benötigen. Deshalb sollten auf der „digitalen“ Seite des Shield-Pinouts nur die notwendigen Adafruit-Pins eingesteckt und die anderen Pins nach außen gebogen werden. Siehe dazu das nachfolgende Bild:
wifi_shield_beinchen

Das Wifi-Shield wird nun anstelle des vorher verwendeten Ethernet W5100-Moduls ganz oben aufgesteckt, so wie es das nachfolgende Bild zeigt. Wegen der für das Wifi-Shield zusätzlich verwendeten  Steuerleitungen D2 und D7 können natürlich  diese Pins nicht mehr für Homeduino-Sensorsignale verwendet werden. In der zugehörigen Homeduino-Software sind diese Ports deshalb gesperrt.
wifi_in_hand

Die Homeduino-Software

Als erstes muß das Library-Verzeichnis der Arduino-Entwicklungsumgebung mit den entsprechenden CC3000 libraries ergänzt werden. Hier das Vorgehen:

– folgendes Datenpaket holen, entpacken und das Verzeichnis “SFE_CC3000_Library-master” umbenennen und als Unterverzeichnis “SFE_CC3000_Library” im Verzeichnis “libraries” wegspeichern:   http://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip

– folgendes Datenpaket holen, entpacken und das Verzeichnis “Adafruit_CC3000_Library-master” umbenennen und als Unterverzeichnis “Adafruit_CC3000_Library” im Verzeichnis “libraries” wegspeichern:   https://github.com/adafruit/Adafruit_CC3000_Library/archive/master.zip

Die Homeduino-Software mußte für das neue Wifi-Shield nur geringfügig angepasst werden. Da hier eine WPA-Verschlüsselung verwendet wir, ist die SSID des eigenen WLAN-Netzwerks in den Sketch einzutragen und auch das WLAN-Kennwort. Das ist schon alles!

 

//Ver.: "homeduino_small_cc3000_07.ino / Stand: 2015.04.06 / Verfasser: Eugen Stall
 
//hier ist immer die aktuelle Version:
//https://www.stall.biz/?project=der-homeduino-2-0-mit-cc3000-wifi-shield-als-sensormodul-fuer-die-homematic
//fuer Arduino Mega 2560, UNO, Duemilanove  mit Arduino 1.5.8
//diese Software steuert referenziert die signale an den Arduino-pins mit entsprechenden systemvariablen in der Homematic ccu
//mit dem Befehl:   http://<ip der ccu>:8181/GET /xy.exe?antwort=dom.GetObject('<systemvariable>').State(" + value + ")"
//Quellen:Arduino website plus http://arduino.cc/en/Tutorial/WebClient  und ...
// http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino und ...
 
#include <SPI.h>
#include <Wire.h>      // Comes with Arduino IDE
#include <OneWire.h>   //für Temperatursensoren DS18B20 http://www.hacktronics.com/code/OneWire.zip
#include <NewPing.h>   //für Ultraschallsensoren SR04 https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip
#include "DHT.h"       //für Temperatursensoren SHT22 https://github.com/adafruit/DHT-sensor-library/archive/master.zip
#include <AS_BH1750.h> //für I2C-Luxmeter https://github.com/hexenmeister/AS_BH1750/archive/master.zip
#include <SFE_BMP180.h>//für I2C-Barometer https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
#include <SFE_CC3000.h>// fuer cc3000 wifi http://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip
#include <SFE_CC3000_Client.h>
 
 
byte ccu[] = { 192, 168, 178, 50 };                   //das ist die IP der CCU                                    <<user-eingabe<< 
byte mac[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC };  //muss nur bei mehreren homeduinos geändert werden !        <<user-eingabe<<
byte homeduino[] = { 192, 168, 178, 52 };             //das ist die feste IP des Homeduino, wenn DHCP versagt     <<user-eingabe<< 
const byte board = 54;       //"14" = UNO/Duemilanove;  "54" = MEGA2560                                           <<user-eingabe<< 
String homeduino_nummer = "x";  // indiv. Bezeichnung für diese homeduino-box                                     <<user-eingabe<< 
String hm_systemvariable = "homeduino_" + homeduino_nummer +"_";
 
//Input-Kennung: hier wird die Funktion der Eingänge D0 bis D9 festgelegt 
byte iomodus_D[10] = {0, 0, 
                      1,   //D2  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall; "2" = Infrarot;  <<user-eingabe<< 
                      9,   //D3  :"9" = belegt wifi-shield; 
                      1,   //D4  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      9,   //D5  :"9" = belegt wifi-shield; 
                      1,   //D6  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      1,   //D7  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      1,   //D8  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      1    //D9  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                       };                                       
 
//hier wird die Funktion der Eingänge A0 bis A5 festgelegt
byte iomodus_A[6] = {1,   //A0  :"0" = digital_in; "10" = analogin; "11" = NTC; "1" = 1wire;                     <<user-eingabe<< 
                     1,   //A1  :"0" = digital_in; "10" = analogin; "11" = NTC; "1" = 1wire;                     <<user-eingabe<<  
                     1,   //A2  :"0" = digital_in; "10" = analogin; "11" = NTC; "1" = 1wire;                     <<user-eingabe<<   
                     1,   //A3  :"0" = digital_in; "10" = analogin; "11" = NTC; "1" = 1wire;                     <<user-eingabe<<   
                     1,   //A4  :"0" = digital_in; "10" = analogin; "11" = NTC; "1" = 1wire;                     <<user-eingabe<<   
                     1    //A5  :"0" = digital_in; "10" = analogin; "11" = NTC; "1" = 1wire;                     <<user-eingabe<<   
                      };                                              
//hier werden Sensoren am I2C-Eingang aktiviert
byte iomodus_baro  = 1;   //"0" = N.C.;  "1" = BMP180                     <<user-eingabe<< 
byte iomodus_lux  = 1;   //"0" = N.C.; "1" = BH1750;                      <<user-eingabe<< 
 
 
 
//hier werden die zuletzt gesendeten sytemvariablen gespeichert
boolean last_digitalin_value_D[10];
float last_digital_value_D[10];
boolean last_digitalin_value_A[6];
float last_analogin_value_A[6];
float last_IR_value;
float last_RF_value;
float last_lux_value;
double last_baro_value;
double last_baroT_value;
 
boolean complete_loop =1;  // wenn 1, dann einmal komplett durchlaufen
 
boolean value;
String befehl;
String I;
int analogwert;
 
float tempNTC;
float B_wert = 3950; //aus dem Datenblatt des NTC //<<user-eingabe<<
float Tn = 298.15; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
float Rt ; 
float temp_tur;
float humidity;
 
float delta_onewire = 0.2; //Deltas für Sendeauslösung 
float delta_sht = 0.2;     
float delta_us = 2;
float delta_analog = 2;
float delta_ntc = 0.2;
float delta_lux = 20;
double delta_baro = 0.2;
double delta_baroT = 0.5;
 
long duration, cm; //variable für Ultraschallsensor
 
unsigned long next_full_loop = 0;
unsigned long delta_time = 3600000; // jede Stunde werden alle Inputs aktualisiert
unsigned long delta_tx = 500;  //in ms, minimaler Abstand der Telegramme an die CCU
unsigned long next_tx = 0;
//**************************************************************************************************  
//EthernetClient client;  // Initialize the Ethernet client library
 
AS_BH1750 sensor;   //Initialize BH1750 Luxmeter library
 
#define ALTITUDE 299.0 // seehoehe in metern
SFE_BMP180 pressure;
char status;
double T,P,p0;
 
 
// Pins
#define CC3000_INT      3  // Needs to be an interrupt pin (D2/D3)
#define CC3000_EN       5   // Can be any digital pin
#define CC3000_CS       10  // Preferred is pin 10 on Uno
 
// Connection info data lengths
#define IP_ADDR_LEN     4   // Length of IP address in bytes
 
// Constants
char ap_ssid[] = "ssid";                  // SSID of network             <<user-eingabe<< 
char ap_password[] = "password";          // Password of network           <<user-eingabe<<     
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
unsigned int timeout = 30000;             // Milliseconds
//char server[] = "192,168,178,50";        // Remote host site
 
// Global Variables
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
//**************************************************************************************************  
void setup() 
{
  ConnectionInfo connection_info;
  int i;
 
  // Initialize Serial port
  Serial.begin(115200);  Serial.println("SparkFun CC3000 - WebClient");
  // Initialize CC3000 (configure SPI communications)
  if ( wifi.init() ) {Serial.println("init complete");} 
     else {Serial.println("problem with init!");}
 
  // Connect using DHCP
  if(!wifi.connect(ap_ssid, ap_security, ap_password, timeout)) {Serial.println("no connection to AP");}
 
  // Gather connection details and print IP address
  if ( !wifi.getConnectionInfo(connection_info) ) {Serial.println("no connection details");} 
    else {for (i = 0; i < IP_ADDR_LEN; i++) 
             {Serial.print(connection_info.ip_address[i]);
              if ( i < IP_ADDR_LEN - 1 ) {Serial.print(".");}
             }
         }
 
  // Make a TCP connection to remote host
 if (client.connect(ccu, 8181)) {}
   else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop(); 
 char myIpString[24];  //IP auslesen
 //IPAddress myIp = Ethernet.localIP();
 //sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]);   
 I = myIpString;
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "IP" + "').State('" + I + "')";
 set_sysvar();
}
 
//**************************************************************************************************  
void loop()
{if (millis() > next_full_loop)     //mindestens jede Stunde eine komplette Aktualisierung
   {complete_loop = 1; next_full_loop = millis() + delta_time; 
    if (next_full_loop < millis()) {complete_loop = 0;}  //wichtig wegen Zahlensprung von millis() alle 50 Tage
   } 
 //**************************************************************************************************   
 for (int i = 2; i < 10; i++)  //behandlung digitaleingänge D2 bis D9
   {if (iomodus_D[i] == 0)
     {pinMode(i, INPUT); 
      value =digitalRead(i);
      if ((!value == last_digitalin_value_D[i]) || complete_loop) 
        {I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + value + ")";
         set_sysvar();
         last_digitalin_value_D[i] = value;
        } 
     } 
  }
//**************************************************************************************************  
 for (int i = 2; i < 10; i++)  //behandlung onewire D2 bis D9
   {if (iomodus_D[i] == 1)
     {OneWire ds(i); 
      #define DS18S20_ID 0x10
      #define DS18B20_ID 0x28 
 
      byte present = 0;
      byte data[12];
      byte addr[8];
      temp_tur = 1000.0;
      if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
      if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
      if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
      if (temp_tur > -1000.0) 
        {ds.reset(); 
         ds.select(addr); 
         ds.write(0x44, 1); // Start conversion
         delay(850); // Wait some time...
         present = ds.reset(); 
         ds.select(addr);
         ds.write(0xBE); // Issue Read scratchpad command
         for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
         temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
         //temp_tur = ( (data[1] << 8) + data[0] )*0.5    // Calculate temperature value 18S20
        }
      if ((temp_tur > (last_digital_value_D[i] + delta_onewire)) || (temp_tur < (last_digital_value_D[i] - delta_onewire)) || complete_loop) 
        {
          I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
         set_sysvar();
         last_digital_value_D[i] = temp_tur;
        } 
     } 
  }  
//**************************************************************************************************  
 for (int i = 0; i < 6; i++)  //behandlung onewire A0 bis A5
   {if (iomodus_A[i] == 1)
     {OneWire ds(i+54); 
      #define DS18S20_ID 0x10
      #define DS18B20_ID 0x28 
 
      byte present = 0;
      byte data[12];
      byte addr[8];
      temp_tur = 1000.0;
      if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
      if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
      if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
      if (temp_tur > -1000.0) 
        {ds.reset(); 
         ds.select(addr); 
         ds.write(0x44, 1); // Start conversion
         delay(850); // Wait some time...
         present = ds.reset(); 
         ds.select(addr);
         ds.write(0xBE); // Issue Read scratchpad command
         for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
         temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
         //temp_tur = ( (data[1] << 8) + data[0] )*0.5    // Calculate temperature value 18S20
        }
      if ((temp_tur > (last_analogin_value_A[i] + delta_onewire)) || (temp_tur < (last_analogin_value_A[i] - delta_onewire)) || complete_loop) 
        {
          I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + temp_tur + ")";
         set_sysvar();
         last_analogin_value_A[i] = temp_tur;
        } 
     } 
  }   
 //**************************************************************************************************   for (int i = 2; i < 10; i++)  //behandlung onewire D2 bis D9
for (int i = 2; i < 10; i++)  //behandlung DHT22 D2 bis D9
  {if (iomodus_D[i] == 3)
     {DHT dht(i, DHT22);   //je nach verwendetem sensor "DHT11" oder "DHT22" (AM2302) oder "DHT 21" (AM2301)
      dht.begin();
      delay(2000); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
      humidity = dht.readHumidity();  // Read temperature as Celsius
      temp_tur = dht.readTemperature();  
      if (isnan(humidity) || isnan(temp_tur) )  // Check if any reads failed and 
        {Serial.println("Failed to read from DHT sensor!"); temp_tur = -1000;}
      if ((temp_tur > (last_digital_value_D[i] + delta_sht)) || (temp_tur < (last_digital_value_D[i] - delta_sht)) || complete_loop) 
        {
         I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
         set_sysvar();
          befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "1').State(" + humidity + ")";
         set_sysvar();
         last_digital_value_D[i] = temp_tur;
        } 
     } 
  }   
//**************************************************************************************************  
 for (int i = 2; i < 10; i++)  //behandlung Ultraschallsensor D2 bis D9
   {if (iomodus_D[i] == 4)
     { NewPing sonar(i, i, 200); // NewPing setup of pin and maximum distance.
       unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
       int cm = uS / US_ROUNDTRIP_CM;
       if ((cm > (last_digital_value_D[i] + delta_us)) || (cm < (last_digital_value_D[i] - delta_us)) || complete_loop) 
       { I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + cm + ")";
         set_sysvar();
         last_digital_value_D[i] = cm;
       } 
     } 
  }  
//**************************************************************************************************  
for (int i = 0; i < 6; i++)  //behandlung digitaleingänge A0 bis A5
  {if (iomodus_A[i] == 0)
     {pinMode(i +board, INPUT);
      value =digitalRead(i+board); //achtung beim uno sind 14 zu addieren, beim mega 54
      if ((!value == last_digitalin_value_A[i]) || complete_loop) 
        {I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + value + ")";
         set_sysvar();
         last_digitalin_value_A[i] = value;
        } 
     } 
  }
//**************************************************************************************************  
for (int i = 0; i < 6; i++)  //behandlung analogeingänge A0 bis A5
  {if (iomodus_A[i] == 10)
     {analogwert =analogRead(i); 
      if ((analogwert > (last_analogin_value_A[i] + delta_analog)) || (analogwert < (last_analogin_value_A[i] - delta_analog)) || complete_loop) 
        {I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + analogwert + ")";
         set_sysvar();
         last_analogin_value_A[i] = analogwert;
        } 
     } 
  }  
//**************************************************************************************************
for (int i = 0; i < 6; i++)   //behandlung NTC an A0 bis A5
  {if (iomodus_A[i] == 11)
     {Rt = Rv/((1024.0/analogRead(i))- 1.0);
      tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn +25.0 ;
       if ((tempNTC > (last_analogin_value_A[i] + delta_ntc)) || (tempNTC < (last_analogin_value_A[i] - delta_ntc)) || complete_loop) 
        {I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + tempNTC + ")";
         set_sysvar();
         last_analogin_value_A[i] = tempNTC;
        } 
     } 
  }  
 
//**************************************************************************************************
//behandlung Luxmeter BH1750 an SCL pin21 und SDA pin 20
// for normal sensor resolution (1 lx resolution, 0-65535 lx, 120ms, no PowerDown) use: sensor.begin(RESOLUTION_NORMAL, false);   
if (iomodus_lux == 1)
  {if(!sensor.begin()) { /*Serial.println("Sensor not present");*/}
   float lux = sensor.readLightLevel();   delay(1000);
   if ((lux > (last_lux_value + delta_lux)) || (lux < (last_lux_value - delta_lux)) || complete_loop) 
     {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "lux" + "').State(" + lux + ")";
      set_sysvar();
      last_lux_value = lux;
     } 
   } 
 
//**************************************************************************************************
//behandlung barometer BMP180 an SCL pin21 und SDA pin 20
if (iomodus_baro == 1)
  {if (pressure.begin()) {status = pressure.startTemperature();}
   if (status) {delay(status); status = pressure.getTemperature(T);} //messung T
   if (status) {status = pressure.startPressure(3);} // //messung P mit resolution 0 bis 3
   if (status) {delay(status); status = pressure.getPressure(P,T);}
   if (status) {p0 = pressure.sealevel(P,ALTITUDE);} // umrechnung auf N.N.
      //Serial.print("Hoehe/m:  "); Serial.print(ALTITUDE); Serial.print("  Temperatur/C: ");  Serial.print(T); Serial.print("  Normaldruck /mb: ");  Serial.println(p0); 
   if ((p0 > (last_baro_value + delta_baro)) || (p0 < (last_baro_value - delta_baro)) || complete_loop) 
     {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baro" + "').State(" + p0 + ")";
      set_sysvar();
      last_baro_value = p0;
     }
     if ((T > (last_baroT_value + delta_baroT)) || (p0 < (last_baroT_value - delta_baroT)) || complete_loop) 
     {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baroT" + "').State(" + T + ")";
      set_sysvar();
      last_baroT_value = T;
     }
  }
 
//**************************************************************************************************
 complete_loop = 0;
}
//##############################################################
// subroutine HTTP request absetzen:
void set_sysvar() 
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;
 if (client.connect(ccu, 8181)) 
   {Serial.println(befehl);
    client.println(befehl);
    client.println();
    client.stop();
   }
}

 

Die genaue Verwendung der Ports und der Anschluss der Sensoren wird im Referenzartikel detailliert beschrieben:

https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic

Das I/O-Shield als Bausatz können Sie in meinem Shop kaufen: https://www.stall.biz/?product=io-shield-2-0

Viel Spass beim Funken mit Wifi!

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.

 

 

Der Homeduino 2.0 als vielseitiges  LAN/WLAN-Sensormodul für die Homematic

Der Homeduino 2.0 als vielseitiges LAN/WLAN-Sensormodul für die Homematic

Wichtiger Hinweis: Es gibt mittlerweile eine neue Softwareversion:   Homduino 4.0

Update 19.03.2017: Software an die CCU2-Firmware 2.27.7 angepasst !

Eins vorweg:

Diese Lösung hier ist sehr einfach nachzubauen; man muß kein Arduino-Freak sein und auch keinerlei Kenntnisse mit der Homematic-Skriptsprache haben. Lediglich ein paar Komponenten kaufen und die hier verfügbare kostenlose Software auf seine persönlichen Belange anpassen, in den Arduino laden und fertig

Ergebnis ist ein universell konfigurierbares Sensormodul für die einfache (skriptfreie) Verwendung mit der Homematic, mit dem man (fast) alle Messaufgaben für die Hausautomation erledigen kann.

Grundidee: Ein frei konfigurierbares Modul für Alles!

Mit dem Homeduino-Projekt  https://www.stall.biz/?project=homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation wurde  schon eine sehr gute Möglichkeit geschaffen, einen vielseitigen I/O für nahezu beliebige Rechneransteuerungen zu ermöglichen. Allerdings sind zur Einbindung des Homduino  in die Homematic-Welt verschiedene HM-Skripte notwendig , die  mit dem unbeliebten (weil absturzgefährdenden) system.Exec-Befehl arbeiten.  Zwar wird mit CuxD das Absturzrisiko geringer, jedoch ist das  Ziel der hier vorgestellten Weiterentwicklung, auf HM-Skripte ganz zu verzichten.

Mit dieser Lösung wird jedem der beim Homeduino 2.0 vorhandenen 14 Eingangskanäle eine entsprechende Systemvariable auf der CCU zugeordnet. Die Aktualisierung der Systemvariablen mit dem entsprechenden Sensorwert erfolgt automatisch und zyklisch in relativ kurzen Abständen im Sekundenbereich. Damit erfolgt die Aktualisierung sehr schnell und dadurch eröffnen sich neue Steuerungs- und Regelungsmöglichkeiten, die insbesondere mit den Funkkomponenten wegen der gesetzlich beschränkten geringen Funkhäufigkeit gar nicht vorstellbar sind. Mehr zum Homeduino 2.0 hier:  https://www.stall.biz/?project=vielseitiges-io-shield-board-2-0-fur-fast-alle-arduinos

Im Homematic Baukasten fehlen heute noch eine Reihe von Sensoren,

die für die Hausautomation wichtig sind. Zu nennen sind beispielhaft…
– geeichte digitale Temperaturfühler sog. 1wire-Sensoren DS18B20
– NTC-Fühler (Thermistor),
– Helligkeitsssensoren
– Geräuschmelder
– dynamische Entfernungsmessung  z.B. zur Füllstandsmessung oder Erkennung von bewegten Objekten,
– Infrarotsensoren für die Erkennung von TV-Fernbedienungen
– 433Mhz-Empfänger für einfache Funksteuerungen (Baumarktsteckdosen)
– schnelle analoge Eingänge für Signale beliebiger analoger Sensoren
– …

Alle diese Anforderungen und noch einiges mehr werden mit dem neuen Homeduino gut erfüllt .

Hier die Technischen Daten:

– bis zu 14 Schalteingänge für potentialfreie Schalter oder Ausgänge von digitalen Geräten

– bis zu 6 analoge Eingänge  (10bit Auflösung) mit wählbaren Eingangsspannungsbereichen 0…+5V , 0… +10V, -5…+5V

– bis zu 6 Eingänge für analoge Temperatursensoren (Thermistoren oder sog. NTC-Messwiderstände)

– bis zu 14 Eingänge für digitale Temperatursensoren (sog. 1wire DS18B20) mit autom. Adresserkennung

– bis zu 8 Eingänge für digitale Temperatur- und Feuchtigkeitssensoren DHT22 /DHT11

– bis zu 8 Eingänge für Ultraschall-Entfernungssensoren

1 Eingang für I2C-Sensoren  wie Barometersensor BMP180  und Lichtintensitätssensor BH1750 …

1 Eingang als Infrarot-Gateway ( fehlt noch! )

1 Eingang als Funk-Gateway (433Mhz-Empfänger, fehlt noch!)

 

Diese Funktionalitäten sind natürlich nicht alle gleichzeitig vorhanden sondern teilen sich in beliebiger Mischung die verfügbaren 14 I/O´s des Homeduino.

Was sind die notwendigen Zutaten?

1x  Arduino MEGA 2560 r3 (bei ebay in China für unter 10€ zu bekommen)
es funktioniert in der Basis-Version auch mit einem UNO oder Duemilanove

1x  Ethernet Shield W5100 (bei ebay in China für unter 6€ zu bekommen)
nicht das Ethernet- Shield mit dem ENC28J60-Chip verwenden !!

1x  Homeduino-I/O-Shield  aus meinem Shop : https://www.stall.biz/?product=io-shield-2-0

und optional bei gewünschter drahtloser WLAN Anbindung:
1x  WLAN-Repeater/Bridge möglichst mit integriertem USB-Netzteil
(ich verwende den Phicomm M1 , bei Amazon für 12,50€)

homeduino_komponenten

So entsteht der Homeduino

Die drei verwendeten Boards steckt man einfach zusammen und erhält einen robusten Aufbau, den man in ein geeignetes Gehäuse einbauen kann. Versorgt wird das Gerät beispielsweise mit einem preisgünstigen 5V USB Netzteil über die USB-Buchse.  Man kann aber auch andere 5V-Netzteile verwenden, der gemessene Strombedarf ist deutlich weniger als  300 mA, d.h. mit einem 500mA-Netzteil ist man schon gut ausgerüstet . Die Sensorsignale werden dabei einfach an den auf dem Homeduino I/O-Shield verfügbaren Schraubklemmen angeschlossen. Die Funktion der einzelnen Eingänge wird einerseits mit den  Jumpern auf dem Homeduino I/O-Shield festgelegt und andererseits kann man in dem verwendeten  Homeduino-Sketch bestimmte Port-Eigenschaften programmieren, die individell jeder Anwender festlegen kann. Oder man nimmt einfach die im Sketch voreingestellten Eigenschaften und muß dann eigentlich gar nichts mehr anpassen!

Hier der zusammengesteckte Homeduino. Wichtig ist, daß das Ethernet-Board immer ganz oben eingesteckt ist und von diesem Board der Pin D4 nicht eingesteckt bzw. leicht nach außen gebogen ist!! … so wie in den nachfolgenden Bildern:

homeduino etagen1 homeduino_inhand

Die verschiedenen Sensoren werden an die Schraubklemmen des Homeduino I/O-Shields angeschlossen. Dabei sind die speziellen Eigenschaften der Sensoren zu beachten und entsprechende Jumper zu setzen. Dies wird später bei den verschiedenen Sensoren erklärt.

Wie erhält der Homeduino seine Software /Firmware

Hier die “Schritt für Schritt”-Installation:

1. Die verwendete  Arduino-Version „for non admin install“ herunterladen: http://arduino.cc/download_handler.php?f=/arduino-1.6.3-windows.zip  , entpacken in ein neues Verzeichnis „homeduino/arduino-1.6.3″  und die USB-Treiber im Unterverzeichnis „drivers“ durch Aufruf der entsprechenden exe-Files installieren.
Dann einen Folder für die eigenen Sketche einrichten z.B.  „homeduino/arduino-1.6.3/sketchbook“ und arduino.exe (die Arduino-IDE  = integrierte Entwicklungsumgebung) im Verzeichnis „homeduino/arduino_1.6.3″ aufrufen. Dort unter dem Reiter „Datei/Voreinstellungen“ den Speicherort für den soeben eingerichteten Ordner Sketchbook angeben.
Damit ist erst mal die Arduino IDE eingerichtet.

2. in den Unterordner “homeduino/arduino_1.6.3/libraries” folgende jetzt noch zusätzliche Libraries als weitere Unterverzeichnisse kopiert. Man kann es sich einfach machen und den Zip-File hier entpacken und alle Ordner zu den vorhandenen libraries kopieren
homeduino_20_libraries
…oder man folgt den folgenden Schritten, um auch die aktuellsten Libraries zu erhalten:

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

4. folgendes Datenpaket holen, entpacken und das Verzeichnis “DHT-sensor-library-master” umbenennen und als Unterverzeichnis “DHT” im Verzeichnis “libraries” wegspeichern:
https://github.com/adafruit/DHT-sensor-library/archive/master.zip

5. folgendes Datenpaket holen, entpacken und das Verzeichnis “NewPing” als Unterverzeichnis im Verzeichnis “libraries” wegspeichern:
https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip

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

7. 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

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

9. folgendes Datenpaket holen, entpacken und daraus das Unterverzeichnis”AS_BH1750-master″  im Verzeichnis “libraries” wegspeichern:
https://github.com/hexenmeister/AS_BH1750/archive/master.zip

10. folgendes Datenpaket holen, entpacken und daraus das Unterverzeichnis   „SFE_CC3000_Library-master” im Verzeichnis “libraries” wegspeichern:
https://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip

Damit ist die Entwicklungsumgebung (IDE) vorbereitet und kann mit arduino.exe gestartet werden.

–  Dann unter „Werkzeuge/Board“ das  verwendete Arduino-Board MEGA25650 markieren und noch unter „Datei/Werkzeuge“ den verwendeten seriellen Port des angeschlossenen Arduino auswählen. Dieser Port ist aber erst sichtbar, wenn der Arduino auch angeschlossen ist. Die Portnummer ist meist höher als com3. In diesem Fenster unten rechts die Baudrate auf 115600Bd einstellen.

–  Im geöffneten fast leeren Editor-Fenster ersetzt man die Einträge per  “Copy/Paste”  mit dem folgenden Homeduino-Sketch und sichert diese Datei mit „Datei/Speichern unter“homeduino_20_xy„in den vorher definierten Sketchbook-Ordner.

– Jetzt noch im Homeduino-Sketch in der Zeile  „byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU “   die Adresse der eigenen heimischen CCU eintragen. Die Adresse des Homeduino wird automatisch per DHCP vom Router vergeben. Wichtig: wenn mehrere Homduinos verwendet werden, dann muß auch die MAC-Adresse so verändert werden, daß sie nicht zweimal im Netzwerk vorkommt.
Allein mit dem Eintrag der zugehörigen CCU-IP ist das eigentliche Anlernen des Homeduinos an die jeweilige CCU schon erfolgt.

– Die Homeduino-Software wird nun mit dem Pfeil-Rechts-Button oben in der Menueleiste compiliert und in den angeschlossenen Homeduino geladen. … Fertig!!

Hier ist die  Homeduino-Software oder besser gesagt das Homeduino-Sketch:

 

 

//Ver.: "homeduino_20_11_1.ino / Stand: 2017.03.19 / Verfasser: Eugen Stall
 
//hier ist immer die aktuelle Version:
//https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic&preview=true&preview_id=1115&preview_nonce=9162dd6679
//fuer Arduino Mega 2560, UNO, Duemilanove mit Arduino 1.5.8
//diese Software steuert referenziert die signale an den Arduino-pins mit entsprechenden systemvariablen in der Homematic ccu
//mit dem Befehl: http://<ip der ccu>:8181/GET /xy.exe?antwort=dom.GetObject('<systemvariable>').State(" + value + ")"
//Quellen:Arduino website plus http://arduino.cc/en/Tutorial/WebClient und ...
// http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino und ...
 
#include <SPI.h>
#include <Wire.h> 
#include <OneWire.h> //für Temperatursensoren DS18B20 http://www.hacktronics.com/code/OneWire.zip
#include <NewPing.h> //für Ultraschallsensoren SR04 https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip
#include "DHT.h" //für Temperatursensoren SHT22 https://github.com/adafruit/DHT-sensor-library/archive/master.zip
#include <AS_BH1750.h> //für I2C-Luxmeter https://github.com/hexenmeister/AS_BH1750/archive/master.zip
#include <SFE_BMP180.h>//für I2C-Barometer https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
 
 
//+++++++ der folgende Bereich ist die Initialisierung des LAN bei Verwndung des LAN-Shields
#define com_mode 0
#include <Ethernet.h> 
EthernetClient client;
//+++++++
 
/*
//+++++++ der folgende Bereich ist die Initialisierung des CC3000 Wifi auf dem IO-Shield-Plus 
#define com_mode 1
#include <SFE_CC3000.h>// fuer cc3000 wifi http://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip
#include <SFE_CC3000_Client.h>
// Pins
#define CC3000_INT 18 // int -Pin mit Wifi Shield ist D3, mit breakout auf IO-Shield-Plus ist D18
#define CC3000_EN 46 // en -Pin mit Wifi Shield ist D5, mit breakout auf IO-Shield-Plus ist D46
#define CC3000_CS 53 // cs -Pin mit Wifi Shield ist D10, mit breakout auf IO-Shield-Plus ist D53
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
// Constants
char ap_ssid[] = "ssid"; // SSID Name des WLAN in Anführungszeichen <<user-eingabe<< 
char ap_password[] = "passwort"; // Passwort des WLAN in Anführungszeichen <<user-eingabe<< 
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
unsigned int timeout = 30000; // Milliseconds
//char server[] = "192,168,178,50"; // Remote host site
//+++++++
*/ 
 
char ccu_ip[31] = "192.168.178.41"; //myCCUIP"; //das ist die IP der CCU <<user-eingabe<< 
byte mac[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; //muss nur bei mehreren homeduinos individuell geändert werden ! <<user-eingabe<<
byte homeduino[] = { 192, 168, 178, 52 }; //das ist die feste IP dieses Homeduino, wenn DHCP versagt <<user-eingabe<< 
 
String homeduino_nummer = "x"; // indiv. Bezeichnung für diese homeduino-box <<user-eingabe<< 
String hm_systemvariable = "homeduino_" + homeduino_nummer +"_";
 
//Input-Kennung: hier wird die Funktion der Eingänge D2 bis D29 festgelegt 
byte iomodus_D[30] = 
{ 0, //D0 : '0' = andere Nutzung; 
 0, //D1 : '0' = andere Nutzung; 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield20 +++++++++++++++++++++++++++++++++ 
 2, //D2 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; '5' = Infrarot; 
 2, //D3 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; '7' = 433Mhz_Rx
 2, //D4 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; 
 2, //D5 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; 
 2, //D6 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; 
 2, //D7 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; 
 2, //D8 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; 
 2, //D9 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield20<< 
 //'4' = Ultraschall; 
 
 0, //D10 : '0' = andere Nutzung; '2' = digital in; 
 0, //D11 : '0' = andere Nutzung; '2' = digital in; 
 0, //D12 : '0' = andere Nutzung; '2' = digital in; 
 0, //D13 : '0' = andere Nutzung; '2' = digital in; 
 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield_Plus +++++++++++++++++++++++++++++++++ 
 0, //D14 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '7' = ESP8266; 
 0, //D15 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '7' = ESP8266; 
 0, //D16 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '7' = ESP8266; 
 0, //D17 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '7' = ESP8266; 
 0, //D18 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '6' = Impulszaehler; '0' = CC3000
 0, //D19 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '6' = Impulszaehler; 
 0, //D20 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '6' = Impulszaehler; '8' = I2C; 
 0, //D21 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; '6' = Impulszaehler; '8' = I2C; 
 0, //D22 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
 0, //D23 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
 0, //D24 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
 0, //D25 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
 0, //D26 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
 0, //D27 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
 0, //D28 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
 0, //D29 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '3' = DHTxx; <<user-eingabe für I/O-Shield-Plus<< 
 //'4' = Ultraschall; 
}; 
 
//hier wird die Funktion der Eingänge A0 bis A15 festgelegt
byte iomodus_A[16] = 
{ 
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield20 +++++++++++++++++++++++++++++++++ 
 2, //A0 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield20<< 
 //'10' = analog in; 
 2, //A1 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield20<< 
 //'10' = analog in; 
 2, //A2 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield20<< 
 //'10' = analog in; 
 2, //A3 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield20<< 
 //'10' = analog in; 
 2, //A4 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield20<< 
 //'10' = analog in; 
 2, //A5 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield20<< 
 //'10' = analog in; 
 
 0, //A6 : "0" = andere Nutzung; 
 0, //A7 : "0" = andere Nutzung; 
 
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield_Plus +++++++++++++++++++++++++++++++++ 
 0, //A8 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
 0, //A9 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
 0, //A10 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
 0, //A11 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
 0, //A12 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
 0, //A13 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
 0, //A14 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
 0, //A15 : '0' = andere Nutzung; '1' = 1wire; '2' = digital in; '11' = NTC; <<user-eingabe für I/O-Shield-Plus<< 
 //'10' = analog in; 
}; 
//hier werden Sensoren am I2C-Eingang aktiviert
byte iomodus_baro = 0; //"0" = N.C.; "1" = BMP180, wenn aktiviert, dann auch oben I2C aktivieren <<user-eingabe für I/O-Shield-Plus<<
byte iomodus_lux = 0; //"0" = N.C.; "1" = BH1750, wenn aktiviert, dann auch oben I2C aktivieren <<user-eingabe für I/O-Shield-Plus<<
 
//hier werden die Kennwerte fuer die Impulszaehler festgelegt
unsigned zaehlwert;
unsigned last_zaehlwert[6] = {0,0,0,0,0,0};
volatile unsigned long pulsecounter[6] = 
{ 4713, 
 0,
 4711, //Zaehlerstand fuer D21-Impulseingang bei Reset <<user-eingabe für I/O-Shield-Plus<< 
 0, //Zaehlerstand fuer D20-Impulseingang bei Reset <<user-eingabe für I/O-Shield-Plus<< 
 0, //Zaehlerstand fuer D19-Impulseingang bei Reset <<user-eingabe für I/O-Shield-Plus<< 
 0, //Zaehlerstand fuer D18-Impulseingang bei Reset <<user-eingabe für I/O-Shield-Plus<< 
}; 
//hier wird der Teilerfaktor für die Impulszaehler festgelegt
int pulsedivider[6] = 
{ 1,
 1,
 1, //Teilerfaktor fuer D21 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor <<user-eingabe für I/O-Shield-Plus<<
 1, //Teilerfaktor fuer D20 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor <<user-eingabe für I/O-Shield-Plus<<
 1, //Teilerfaktor fuer D19 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor <<user-eingabe für I/O-Shield-Plus<< 
 1, //Teilerfaktor fuer D18 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor <<user-eingabe für I/O-Shield-Plus<<
}; 
 
//hier werden die zuletzt gesendeten sytemvariablen gespeichert
boolean last_digitalin_value_D[30];
float last_digital_value_D[30];
boolean last_digitalin_value_A[16];
float last_analogin_value_A[16];
float last_IR_value;
float last_RF_value;
float last_lux_value;
double last_baro_value;
double last_baroT_value;
 
boolean complete_loop =1; // wenn 1, dann einmal komplett durchlaufen
 
boolean value;
String befehl;
String I;
int analogwert;
 
float tempNTC;
float B_wert = 3950; //aus dem Datenblatt des NTC //<<user-eingabe<<
float Tn = 298.15; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
float Rt ; 
float temp_tur;
float humidity;
 
float delta_onewire = 0.2; //Deltas für Sendeauslösung 
float delta_sht = 0.2; 
float delta_us = 2;
float delta_analog = 2;
float delta_ntc = 0.2;
float delta_lux = 20;
double delta_baro = 0.2;
double delta_baroT = 0.5;
 
long duration, cm; //variable für Ultraschallsensor
 
unsigned long next_full_loop = 0;
unsigned long delta_time = 3600000; // jede Stunde werden alle Inputs aktualisiert
unsigned long delta_tx = 500; //in ms, minimaler Abstand der Telegramme an die CCU
unsigned long next_tx = 0;
 
boolean ccu_presence;
 
//************************************************************************************************** 
AS_BH1750 sensor; //Initialize BH1750 Luxmeter library
 
#define ALTITUDE 299.0 // seehoehe in metern
SFE_BMP180 pressure;
char status;
double T,P,p0;
 
//************************************************************************************************** 
//************************************************************************************************** 
void setup() 
{Serial.begin(115200); 
 
 
//+++++++ hier folgt die LAN Initialisierung
if (Ethernet.begin(mac) == 0) // start the Ethernet connection:
 {Serial.println("Failed to configure Ethernet using DHCP"); Ethernet.begin(mac, homeduino);}
 delay(1000);// give the Ethernet shield a second to initialize:
 Serial.println("connecting..."); // if you get a connection, report back via serial:
 if (client.connect(ccu_ip, 8181)) {}
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop(); 
 char myIpString[24]; //IP auslesen
 IPAddress myIp = Ethernet.localIP();
 sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]); 
 I = myIpString;
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "IP" + "').State('" + I + "')";
 set_sysvar(); 
//+++++++
 
/*
//+++++++ hier folgt die CC3000 Initialisierung
 ConnectionInfo connection_info;
 int i;
 byte IP_ADDR_LEN =4;
 Serial.println("SparkFun CC3000 - WebClient");
 if ( wifi.init() ) {Serial.println("init complete");} 
 else {Serial.println("problem with init!");}
 // Connect using DHCP
 if(!wifi.connect(ap_ssid, ap_security, ap_password, timeout)) {Serial.println("no connection to AP");}
 // Gather connection details and print IP address
 if ( !wifi.getConnectionInfo(connection_info) ) {Serial.println("no connection details");} 
 else {for (i = 0; i < IP_ADDR_LEN; i++) 
 {Serial.print(connection_info.ip_address[i]);
 if ( i < IP_ADDR_LEN - 1 ) {Serial.print(".");}
 }
 Serial.println(" ist aktuelle IP-Adresse"); 
 }
 if (client.connect(ccu, 8181)) {} // Make a TCP connection to remote host
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop();
//+++++++ 
*/
//einrichtung der interrupts fuer impulszahler D18,D19,D20,D21 
if ((pulsedivider[2] > 0) && (iomodus_D[21] == 6)) {pinMode(21, INPUT_PULLUP); attachInterrupt(2, ISR_2, FALLING);}
if ((pulsedivider[3] > 0) && (iomodus_D[20] == 6)) {pinMode(20, INPUT_PULLUP); attachInterrupt(3, ISR_3, FALLING);}
if ((pulsedivider[4] > 0) && (iomodus_D[19] == 6)) {pinMode(19, INPUT_PULLUP); attachInterrupt(4, ISR_4, FALLING);}
if ((pulsedivider[5] > 0) && (iomodus_D[18] == 6) && (com_mode == 0)) {pinMode(18, INPUT_PULLUP); attachInterrupt(5, ISR_5, FALLING);}
 
}
//************************************************************************************************** 
//************************************************************************************************** 
void loop()
{if (millis() > next_full_loop) //mindestens jede Stunde eine komplette Aktualisierung
 {complete_loop = 1; next_full_loop = millis() + delta_time; 
 if (next_full_loop < millis()) {complete_loop = 0;} //wichtig wegen Zahlensprung von millis() alle 50 Tage
 } 
 //************************************************************************************************** 
 for (int i = 2; i < 30; i++) //behandlung digitaleingänge D2 bis D29
 {if (iomodus_D[i] == 2)
 {pinMode(i, INPUT_PULLUP); 
 digitalWrite(i, HIGH);
 value =digitalRead(i);
 if ((!value == last_digitalin_value_D[i]) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + value + ")";
 set_sysvar();
 last_digitalin_value_D[i] = value;
 } 
 } 
 }
//************************************************************************************************** 
for (int i = 0; i < 16; i++) //behandlung zur verwendung digitaleingänge an analogen Eingängen A0 bis A15
 {if (iomodus_A[i] == 2)
 {pinMode(i + 54, INPUT_PULLUP);
 digitalWrite(i + 54, HIGH);
 value =digitalRead(i+54); //achtung beim uno sind 14 zu addieren, beim mega 54
 if ((!value == last_digitalin_value_A[i]) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + value + ")";
 set_sysvar();
 last_digitalin_value_A[i] = value;
 } 
 } 
 } 
//************************************************************************************************** 
 for (int i = 2; i < 30; i++) //behandlung onewire an D2 bis D29
 {if (iomodus_D[i] == 1)
 {OneWire ds(i); 
 #define DS18S20_ID 0x10
 #define DS18B20_ID 0x28 
 
 byte present = 0;
 byte data[12];
 byte addr[8];
 temp_tur = 1000.0;
 if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
 if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
 if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
 if (temp_tur > -1000.0) 
 {ds.reset(); 
 ds.select(addr); 
 ds.write(0x44, 1); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5 // Calculate temperature value 18S20
 }
 if ((temp_tur > (last_digital_value_D[i] + delta_onewire)) || (temp_tur < (last_digital_value_D[i] - delta_onewire)) || complete_loop) 
 {
 I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 last_digital_value_D[i] = temp_tur;
 } 
 } 
 } 
//************************************************************************************************** 
 for (int i = 0; i < 16; i++) //behandlung onewire an A0 bis A15
 {if (iomodus_A[i] == 1)
 {pinMode(i + 54, INPUT_PULLUP);
 digitalWrite(i + 54, HIGH);
 
 OneWire ds(i+ 54); 
 #define DS18S20_ID 0x10
 #define DS18B20_ID 0x28 
 
 byte present = 0;
 byte data[12];
 byte addr[8];
 temp_tur = 1000.0;
 if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
 if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
 if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
 if (temp_tur > -1000.0) 
 {ds.reset(); 
 ds.select(addr); 
 ds.write(0x44, 1); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5 // Calculate temperature value 18S20
 }
 if ((temp_tur > (last_analogin_value_A[i] + delta_onewire)) || (temp_tur < (last_analogin_value_A[i] - delta_onewire)) || complete_loop) 
 {
 I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 last_analogin_value_A[i] = temp_tur;
 } 
 } 
 } 
 //************************************************************************************************** 
for (int i = 2; i < 30; i++) //behandlung DHT22 D2 bis D29
 {if (iomodus_D[i] == 3)
 {DHT dht(i, DHT22); //je nach verwendetem sensor "DHT11" oder "DHT22" (AM2302) oder "DHT 21" (AM2301)
 dht.begin();
 delay(2000); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
 humidity = dht.readHumidity(); // Read temperature as Celsius
 temp_tur = dht.readTemperature(); 
 if (isnan(humidity) || isnan(temp_tur) ) // Check if any reads failed and 
 {Serial.println("Failed to read from DHT sensor!"); temp_tur = -1000;}
 if ((temp_tur > (last_digital_value_D[i] + delta_sht)) || (temp_tur < (last_digital_value_D[i] - delta_sht)) || complete_loop) 
 {
 I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "1').State(" + humidity + ")";
 set_sysvar();
 last_digital_value_D[i] = temp_tur;
 } 
 } 
 } 
//************************************************************************************************** 
 for (int i = 2; i < 30; i++) //behandlung Ultraschallsensor D2 bis D29
 {if (iomodus_D[i] == 4)
 { NewPing sonar(i, i, 200); // NewPing setup of pin and maximum distance.
 unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
 int cm = uS / US_ROUNDTRIP_CM;
 if ((cm > (last_digital_value_D[i] + delta_us)) || (cm < (last_digital_value_D[i] - delta_us)) || complete_loop) 
 { I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + cm + ")";
 set_sysvar();
 last_digital_value_D[i] = cm;
 } 
 } 
 } 
//************************************************************************************************** 
for (int i = 0; i < 16; i++) //behandlung analogeingänge A0 bis A15
 {if (iomodus_A[i] == 10)
 {analogwert =analogRead(i); 
 if ((analogwert > (last_analogin_value_A[i] + delta_analog)) || (analogwert < (last_analogin_value_A[i] - delta_analog)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + analogwert + ")";
 set_sysvar();
 last_analogin_value_A[i] = analogwert;
 } 
 } 
 } 
//**************************************************************************************************
for (int i = 0; i < 16; i++) //behandlung NTC an A0 bis A15
 {if (iomodus_A[i] == 11)
 {Rt = Rv/((1024.0/analogRead(i))- 1.0);
 tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn +25.0 ;
 if ((tempNTC > (last_analogin_value_A[i] + delta_ntc)) || (tempNTC < (last_analogin_value_A[i] - delta_ntc)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "A" + I + "').State(" + tempNTC + ")";
 set_sysvar();
 last_analogin_value_A[i] = tempNTC;
 } 
 } 
 } 
//**************************************************************************************************
//behandlung Luxmeter BH1750 an SCL pin21 und SDA pin 20
// for normal sensor resolution (1 lx resolution, 0-65535 lx, 120ms, no PowerDown) use: sensor.begin(RESOLUTION_NORMAL, false); 
if ((iomodus_D[20] == 1) && (iomodus_D[21] == 1) && (iomodus_lux ==1))
 {if(!sensor.begin()) { /*Serial.println("Sensor not present");*/}
 float lux = sensor.readLightLevel(); delay(1000);
 if ((lux > (last_lux_value + delta_lux)) || (lux < (last_lux_value - delta_lux)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "lux" + "').State(" + lux + ")";
 set_sysvar();
 last_lux_value = lux;
 } 
 } 
//**************************************************************************************************
//behandlung barometer BMP180 an SCL pin21 und SDA pin 20
if ((iomodus_D[20] == 1) && (iomodus_D[21] == 1)&& (iomodus_baro ==1))
 {if (pressure.begin()) {status = pressure.startTemperature();}
 if (status) {delay(status); status = pressure.getTemperature(T);} //messung T
 if (status) {status = pressure.startPressure(3);} // //messung P mit resolution 0 bis 3
 if (status) {delay(status); status = pressure.getPressure(P,T);}
 if (status) {p0 = pressure.sealevel(P,ALTITUDE);} // umrechnung auf N.N.
 //Serial.print("Hoehe/m: "); Serial.print(ALTITUDE); Serial.print(" Temperatur/C: "); Serial.print(T); Serial.print(" Normaldruck /mb: "); Serial.println(p0); 
 if ((p0 > (last_baro_value + delta_baro)) || (p0 < (last_baro_value - delta_baro)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baro" + "').State(" + p0 + ")";
 set_sysvar();
 last_baro_value = p0;
 }
 if ((T > (last_baroT_value + delta_baroT)) || (p0 < (last_baroT_value - delta_baroT)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baroT" + "').State(" + T + ")";
 set_sysvar();
 last_baroT_value = T;
 }
 }
//************************************************************************************************** 
for (int i = 2; i < 5; i++) //behandlung impulszahler D21,D20,D19,D18 
 {zaehlwert = pulsecounter[i] / pulsedivider[i];
 if ( (pulsedivider[i] > 0) && ((zaehlwert > (last_zaehlwert[i]) || complete_loop))) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "imp" + I + "').State(" + zaehlwert + ")";
 set_sysvar();
 last_zaehlwert[i] = zaehlwert;
 } 
 } 
//**************************************************************************************************
 complete_loop = 0;
}
//##############################################################
// subroutine HTTP request absetzen:
void set_sysvar() 
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;
 befehl += " HTTP/1.1\r\nHost:"; //zusaetzlich wegen neuer CCU-firmware
 befehl += ccu_ip;
 befehl += "\r\nConnection: close\r\n\r\n";
 
 if (client.connect(ccu_ip, 8181))
 {Serial.print("sent to ccu : "); Serial.print(befehl); yield();
 client.print(befehl);
 delay(10); client.stop();
 ccu_presence = 1;
 } else {Serial.println("keine verbindung zur ccu"); ccu_presence = 0; return;}
}
//##############################################################
//hier sind die interrupt-service-routinen fuer die impulszaehler
void ISR_2() //Interrupt an D21
{pulsecounter[2]++;}
 
void ISR_3() //Interrupt an D20
{pulsecounter[3]++;}
 
void ISR_4() //Interrupt an D19
{pulsecounter[4]++;}
 
#if com_mode == 0
void ISR_5() //Interrupt an D18 
{pulsecounter[5]++;}
#endif

 

 

 

hier sind noch alte Versionen:

homeduino_small_07   Stand: 2015.01.06
homeduino_small_08   Stand: 2015.03.15
homeduino_small_09   Stand:2015.03.29

 

Individuelle Anpassung des Homeduino

Im Homeduino-Sketch wird mit einer Kennzahl festgelegt, welche Funktionalität jeder Input-Port hat. Für jeden analogen und digitalen Inputpin ist je nach Wunsch die Pin-Funktionalität mit den entsprechenden Variablendefinitioinen im Homeduino-Sketch festzulegen.  In jeder Zeile ist nur der erste Zahleneintrag relevant; hinter dem Doppelschrägstrich steht immer der Kommentar bzw. die Erklärung für den jeweiligen Zahlenwert. Hier ein Auszug aus dem Listing:

//Input-Kennung: hier wird die Funktion der Eingänge D2 bis D29 festgelegt 
byte iomodus_D[30] = 
{0, //D0 : '0' = andere Nutzung; 
 0, //D1 : '0' = andere Nutzung; 
//+++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield20 +++++++++++++++++++++++++ 
 2, //D2: '0' =andere Nutzg; '1' =1wire; '2' =digital in; '3' =DHTxx;     <<user-eingabe für I/O-Shield20<< 
    //    '4' =Ultraschall;    '5' =Infrarot; 
 2, //D3: '0' =andere Nutzg; '1' =1wire; '2' =digital in; '3' =DHTxx;     <<user-eingabe für I/O-Shield20<< 
    //    '4' = Ultraschall; '7' = 433Mhz_Rx
...
//+++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield_Plus +++++++++++++++++++++ 
 0, //D14: '0' =andere Nutzg;  '1' =1wire; '2' =digital in; '3' =DHTxx;<<user-eingabe für I/O-Shield-Plus<< 
    //     '4' =Ultraschall;   '7' = ESP8266; 
 0, //D15: '0' = andere Nutzg; '1' =1wire; '2' =digital in; '3' =DHTxx;<<user-eingabe für I/O-Shield-Plus<< 
    //     '4' =Ultraschall;   '7' = ESP8266; 
...
//hier wird die Funktion der Eingänge A0 bis A15 festgelegt
byte iomodus_A[16] = 
{ 
//++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield20 +++++++++++++++++++++++++ 
 2, //A0: '0' = andere Nutzg; '1' =1wire; '2' =digital in; '11' =NTC;     <<user-eingabe für I/O-Shield20<< 
    //'10' = analog in; 
 2, //A1: '0' = andere Nutzg; '1' =1wire; '2' =digital in; '11' =NTC;     <<user-eingabe für I/O-Shield20<< 
    //   '10' = analog in; 
... 
//++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield_Plus ++++++++++++++++++++++ 
 0, //A8: '0' = andere Nutzg; '1' =1wire; '2' =digital in; '11' =NTC;  <<user-eingabe für I/O-Shield-Plus<< 
    //   '10' = analog in; 
 0, //A9: '0' = andere Nutzg; '1' =1wire; '2' =digital in; '11' =NTC;  <<user-eingabe für I/O-Shield-Plus<< 
    //   '10' = analog in; 
...
//hier werden Sensoren am I2C-Eingang aktiviert
byte iomodus_baro = 0; //"0" =N.C.; "1" = BMP180;                      <<user-eingabe für I/O-Shield-Plus<<
byte iomodus_lux  = 0; //"0" =N.C.; "1" = BH1750;                      <<user-eingabe für I/O-Shield-Plus<<
 
//+++++ hier werden die Kennwerte fuer die Impulszaehler festgelegt  ++++++++++++++++++++++++++++++++++++++
volatile unsigned long pulsecounter[6] = 
{ 4713, 
     0,
  4711, //Zaehlerstand fuer D21-Impulseingang bei Reset                <<user-eingabe für I/O-Shield-Plus<< 
     0, //Zaehlerstand fuer D20-Impulseingang bei Reset                <<user-eingabe für I/O-Shield-Plus<< 
     0, //Zaehlerstand fuer D19-Impulseingang bei Reset                <<user-eingabe für I/O-Shield-Plus<< 
     0, //Zaehlerstand fuer D18-Impulseingang bei Reset                <<user-eingabe für I/O-Shield-Plus<< 
}; 
//hier wird der Teilerfaktor für die Impulszaehler festgelegt
int pulsedivider[6] = 
{  1,
   1,
   1, //Teilerfaktor fuer D21 : wenn 0, dann keine Zaehlfunktion       <<user-eingabe für I/O-Shield-Plus<<
   1, //Teilerfaktor fuer D20 : wenn 0, dann keine Zaehlfunktion       <<user-eingabe für I/O-Shield-Plus<<
   1, //Teilerfaktor fuer D19 : wenn 0, dann keine Zaehlfunktion       <<user-eingabe für I/O-Shield-Plus<< 
   1, //Teilerfaktor fuer D18 : wenn 0, dann keine Zaehlfunktion       <<user-eingabe für I/O-Shield-Plus<<
}; 

    

Entsprechend wird im Listing durch Kennzahlen festgelegt, ob ein Barometersensor oder ein Lichtsensor verwendet werden. Und auch die Impulszähler können  bezüglich  Startwert und Vorteilerfaktor konfiguriert werden. Das scheint vielleicht etwas kompliziert zu sein, es gibt aber dem Nutzer viele Möglichkeiten, seine Hausautomation auf die individuellen Bedürfnisse anzupassen. Und man muß es ja nur einmal bei der Installation machen; die Verwendung ist kinderleicht!

Will man andere Konfigurationen einstellen, dann sind einfach nur kanalweise die entsprechenden Parameter einzutragen. Das ist alles!

Anlernen an die Homematic-CCU

Das Anlernen an die CCU war eigentlich schon gemacht mit dem Eintrag der CCU-IP im Homeduino-Sketch.  Um die verschiedenen Sensordaten in die CCU zu bekommen sind keinerlei Abfragen oder Skripts notwendig. Für jeden Eingangskanal wird einfach eine entsprechende Systemvariable angelegt. Diese wird vom Homeduino selbsttätig entsprechend dem zugehörigen Eingangssignal aktualisiert. Damit aber nicht dauernd „Traffic“ entsteht, wird nur bei einer softwareseitig vorgegeben Veränderung des Eingangssignals die Systemvariable aktualisiert. Bei oftmals nur langsam veränderlichen Temperatursignalen reduziert sich dadurch das Datenaufkommen dramatisch. Trotzdem reagiert das System sofort, wenn Änderungen der Eingangssignale vorhanden sind! Damit werden auch schnellere Steuer und Regelvorgänge mit der Homematic ermöglicht, wie z.B. die temperaturabhängige Steuerung der Zirkulationspumpe, Erkennung von Lichtschranken und Bewegungsmeldern etc.

Für die maximale Homduino-Konfiguration werden nun entsprechend der individuellen Bedürfnisse mehr oder weniger  Systemvariablen in der CCU angelegt: (exakte Schreibweise beachten!)

homeduino_x_A0               als Zahl oder Logikwert    und nach Bedarf  Maßeinheit z.B. °C          für das IO-Shield20
bis
homeduino_x_A5

homeduino_x_A8               als Zahl oder Logikwert    und nach Bedarf  Maßeinheit z.B. °C       für das IO-Shield-Plus
bis
homeduino_x_A15            

homeduino_x_D2               als Zahl oder Logikwert    und nach Bedarf  Maßeinheit z.B. °C            für das IO-Shield20
bis
homeduino_x_D13

homeduino_x_14               als Zahl oder Logikwert    und nach Bedarf  Maßeinheit z.B. °C       für das IO-Shield-Plus
bis
homeduino_x_D29

homeduino_x_IP               als Zeichenkette zur Anzeige der Homeduino IP
homeduino_x_baro          als Zahl  mit Maßeinheit mb                                                                        … für das IO-Shield-Plus
homeduino_x_lux              als Zahl mit Maßeinheit lux                                                                         … für das IO-Shield-Plus

homeduino_x_imp0          als Zahl mit Maßeinheit des verwendeten Impulszählers an D2        … für das IO-Shield-Plus
bis
homeduino_x_imp6          als Zahl mit Maßeinheit des verwendeten Impulszählers an D18

Ggf. können mehr oder weniger Systemvariablen definiert werden, je nach Art und Anzahl der verwendeten Anschlüsse.

Die Systemvariablen lassen sich nun einfach in WebUI-Programmen nutzen. Werden mehrere Homeduinos verwendet , dann erhält jeder Homeduino eine andere Kennung: aus dem x in der Bezeichnung der Systemvariablen wird ein y und so weiter…

HowTo:  Sensoren am Homeduino I/O-Shield20

Das Homeduino I/O-Shield20 wurde entwickelt, um möglichst ohne Löten oder Steckbrett die üblichen Sensoren einfach mit Schraubklemmen anzuschließen und mittels Jumper die hardwareseitigen Voraussetzungen zu schaffen. Details zu dem I/O-Shield kann man hier lesen: https://www.stall.biz/?project=vielseitiges-io-shield-board-2-0-fur-fast-alle-arduinos

Das  Homeduino I/O-Shield20 kann man bei mir beziehen. Bitte mich einfach per email (Kontakt -Button)  ansprechen. Der Teil-Bausatz kostet 26€ plus 3,90€ Versand nach Deutschland.

Das nachfolgende Bild zeigt schematisch die Möglichkeiten des Shields. Mit  Jumpern läßt sich hardwaremässig jeder der 14 I/Os  auf die verschiedenen Funktionsanforderungen einstellen:
Folie3

Wem die Anzahl der verfügbaren Inputs nicht ausreicht oder wer Impulszähler mit Optokopplern (S0-Schnittstelle) benötigt , der kann ein Ergänzungsboard IO-Shield-Plus auf die hinteren Pins des MEGA2560 aufstecken. Damit wird nochmal eine erhebliche Funktionserweiterung erreicht; das aktuelle Sketch unterstützt bereits das Erweiterungsshield!

Mehr zu diesem IO-Shield-Plus hier:

So schließt man potentialfreie Schalter und Taster an:

Zum Anschluss von Tastern, Schaltern, Reedschaltern und anderen Sensoren mit nur zwei Zuständen sind keinerlei Zustzwiderstände etc. notwendig, weil die bereits auf dem Board sind und mit Jumpern zugeschaltet werden Deshalb sind in dieser Betriebsart die Jumper 2-3 und 5-6 gesteckt. Damit ist der 4,7KOhm-Pullup-Widerstand aktiviert.

Folie1

Je nach den verwendeten Inputpins sind zur Messung die entsprechenden Systemvariablen in der Homematic einzurichten. In dem Beispiel hier sind es für die  linken Sensoren   homeduino_x_D2 bis homeduino_x_D9  als Logikwert. Die an den analogen Eingang angeschlossenen Sensoren haben die entsprechenden Systemvariablen  homeduino_x_A0 bis homeduino_x_A4 ebenfalls als Logikwert.

Damit der Homeduino auch weiß, daß an dem Eingang D2 bis D9  und A0 bis A5 einSchaltsensor angeschlossen ist, muß im Homeduino-Sketch die Input Kennung der Eingänge D2 bis D9 und A0 bis A5  auf „1“ gestellt werden.

 

 Anschluss von Onewire-Temperatursensoren DS19B20:

Die sog. Onewire-Temperatursensoren DS18B20 oder DS18S20 eignen sich für die Temperaturmessung besonders gut, weil sie bereits geeicht sind und die Meßinformation bereits in digitaler Form zur Verfügung stellen. Allerdings ist die Applikation nicht ganz einfach, weil das Datenprotokoll komplex ist. Darüberhinaus hat jeder Sensor eine individuelle Adresse, die man ggf. erst auslesen muß, um den Sensor zu adressieren und auszulesen.  In der Arduino-Gemeinde hat man schnell die Vorteile dieser Sensoren erkannt und entsprechende Libraries entwickelt. Diese sind hier implementiert, so daß man sich über die Details keine Gedanken machen muß sondern einfach die Sensoren an die Eingänge des Homeduino anschließen kann.

Auf die spezielle Betriebsart mit dem parallelen Anschluss von mehreren Sensoren an einer Zweidrahtleitung wurde beim Homeduino bewußt verzichtet, weil dafür vorher die Adresse jedes einzelnen Sensors mühsam ausgelesen werden muß und diese Adresse dann in die Auswertesoftware eingetragen werden muß. Hier beim Homeduino wird einfach nur je Anschlußpin ein Sensor angeschlossen, dessen Adresse dann automatisch erkannt wird. Dies ist viel komfortabler und man hat keine Zuordnungsprobleme: Jeder Anschlusspin hat also immer nur einen Sensor!

Die störsichere Anschlussmethode für den DS18B20 ist der Dreidrahtanschluss, wobei der Sensor über eine dritte Leitung mit 5V versorgt wird. Hier im Bild der mögliche Anschluß sowohl an den Digitalpin D2 bis D9 als auch an den (digital verwendeten ) analogen Pins A0 bis A5. Entsprechend dem Bild sind die Jumper zu stecken.

Folie5

Die einfachste Methode ist der sog. Zweidraht-Anschluss wie im folgenden Bild gezeigt. Die Jumperbelegung ist identisch!

Folie6
Je nach den verwendeten Inputpins sind zur Messung die entsprechenden Systemvariablen in der Homematic einzurichten. In dem Beispiel hier sind es für den linken Sensor  homeduino_x_D6 als Zahl mit Dimension °C. Für den rechten Sensor ist die Systemvariable homeduino_x_A1 ebenfalls als Zahl ,it der Dimension °C.

Damit der Homeduino auch weiß, daß an dem Eingang D6 ein Onewire-Sensor angeschlossen ist, muß im Homeduino-Sketch die Input Kennung vom Eingang D6 auf „1“ gestellt werden. Für den rechten Sensor ist A1 auf  „1“ gestellt.

Übrigens man kann die Sensoren als Basisversion DS18B20 im Transistorgehäuse kaufen und als Sensor „verpacken“. Es gibt aber auch preisgünstige fertig konfektionierte Sensoren wie im nächsten Bild. Für 5 Sensoren habe ich in China gerade mal  7€ bezahlt 🙂
ds18b20

 

So schließt man NTC-Temperatursensoren an:

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; //aus dem Datenblatt des NTC

Folie3
Wenn es nicht schon bereits erfolgt ist, muß noch in der Homematic-CCU eine Systemvariable vom Typ Zahl mit der Dimension °C angelegt sein . In diesem Beispiel mit dem Input A5 und A0  heißen sie  homeduino_x_A5 und homeduino_x_A0.
Damit der Homeduino auch weiß, daß an den Eingängen A0 und A5  ein NTC-Sensor angeschlossen ist, muß im Homeduino-Sketch die Input Kennung der  Eingänge A0 und A5 auf „11“ gestellt werden.

 

Anschluss Feuchte-Temperatursensor  DHT22 /AM2302:

Die DHT-22 ist ein kostengünstiger Feuchte-und Temperatursensor mit nur einem  Draht als digitale Schnittstelle. Damit werden mit einem speziellen Protokoll die Daten für Luftfeuchte und Temperatur übertragen. Der Vorteil des Sensors ist der günstige Preis  (ca. 3€) , der Nachteil ist die lange Meßzeit von etwa 2s. Aber bei Temperaturmessungen spielt dies meist keine Rolle!

Nach Anschluss der Spannungsversorgung kann die Datenleitung an beliebige Pins D2 bis D9 geschaltet werden entsprechend sind die Jumper wie im Bild zu schalten, so daß die Datenleitung einen sog. Pullup-Widerstand von 4,7KOhm hat.

Folie9

Wenn es nicht schon bereits erfolgt ist, muß noch in der Homematic-CCU eine Systemvariable vom Typ Zahl mit der Dimension °C angelegt sein . In diesem Beispiel mit dem Input D3 heißt sie  homeduino_x_D3. Wenn man auch den Feuchtewert haben will, dann legt man einfach eine weitere Systemvariable homeduino_x_D31 vom Typ Zahl und mit der Dimension % an. Das ist alles 🙂

Damit der Homeduino auch weiß, daß an den Eingängen D3 ein DHT22-Sensor angeschlossen ist, muß im Homeduino-Sketch die Input-Kennung der  verwendeten Eingänge , hier D3,  auf  „3“ gestellt werden.

Übrigens, der noch preiswertere aber etwas ungenauere Sensor DHT11 funktioniert auch, wenn das im Skript geringfügig angepasst wird.

 

So schließt man  Ultraschall-Entfernungssensoren  an:

Die Ultraschallsensoren vom Typ SR04 gibt es im Internet als fertiges Modul bereits für 1€. Sie sind ideal, um Entfernungen von schallreflektiven  Gegenständen zwischen 0 und  450cm zu messen. Im Homeduino wurde die maximale Entfernung auf 200cm begrenzt, weil mit zunehmender Entfernung das Signal „sehr variabel“ wird, was wegen der Änderungen des Messignals dann auch zu einem (zu ) regen Telegrammverkehr mit der CCU führt. Man kann die Meßhäufigkeit reduzieren, indem man die Änderungsschwelle von standardmäßig 2cm vergrößert. Die entsprechende  Variable im Homeduino Sketch heißt float delta_us = 2 .

Man kann an den Homeduino bis zu 8 SR04-Sensoren direkt (ohne die 150Ohm Schutzwiderstände, Jumper 4-5) an die Pins D2 bis D9 anschliessen. Die Software ist so ausgelegt, daß neben der Spannungsversorgung nur eine Datenleitung zum Sensor notwendig ist. Dazu sind aber die zwei mittleren Anschlusspins zu verbinden. (siehe nächstes Bild)

 

Folie4

Wenn es nicht schon bereits erfolgt ist, muß noch in der Homematic-CCU eine Systemvariable vom Typ Zahl mit der Dimension cm angelegt sein . In diesem Beispiel mit dem Input D5 heißt sie  homeduino_x_D5. Damit der Homeduino auch weiß, daß an dem Eingängen D5 ein SR04-Modul angeschlossen ist, muß im Homeduino-Sketch die Input-Kennung des  verwendeten Eingangs , hier D5,  auf  „4“ gestellt werden.

 

So schließt man vernetzte Rauchmelder an

Rauchmelder kann man an den Homeduino anschließen, sofern der Rauchmelder vernetzbar ist. Dieser „Datenbus“ der Rauchmelder-Vernetzung ist nach meiner Kenntnis durchweg  als Zweidraht-Leitung aufgebaut: eine Masseleitung (im Bild blau) und eine Signalleitung  (braun). Im Alarmfall wird von einem Rauchmelder das Potential auf der Signalleitung hoch gesetzt (wegen der verwendeten Batterien meist 9V) . Damit werden dann die anderen vernetzten Rauchmelder gleichzeitig auch alarmiert und schlagen Alarm . Man kann also einfach durch Überwachung der Spannung auf der Signalleitung erkennen, ob ein oder mehrere Rauchmelder Alarm geben. Umgekehrt kann man durch Spannungseinspeisung auf die Signalleitung auch Alarm auslösen. Das kann für die Hausautomation interessant sein z.B. als wirksamer Alarmgeber bei Einbruchsalarm etc.

Die vernetzbaren Rauchmelder sind leider deutlich teurer als die normalen Baumarkt-Rauchmelder, obwohl in fast allen Rauchmeldern die gleichen ICs vom Typ MC145010 oder baugleich verbaut werden.  Das eröffnet die Möglichkeit, einen einfachen Rauchmelder zu einem vernetzbaren Rauchmelder umzubauen. Hier sind interessante Quellen zu diesem Thema:
http://ccblog.de/tag/cs2105go-m12/
http://www.wikidorf.de/reintechnisch/Inhalt/RauchmelderExperimente
http://www.instructables.com/id/Modify-a-6-EUR-smoke-detector-for-use-with-microco/all/?lang=de
Inwieweit mit dem Umbau rechtliche oder versicherungsrechtliche Probleme entstehen können muß jeder unbedingt selbst prüfen. Ich verweise hier u.a. auf die allgemeinen Hinweise auf meiner Startseite.

Ich selbst habe bereits einige Rauchmelder entsprechend dem nachfolgenden Bild modifiziert und einen zweiadrigen Anschluss für die Rauchmelder-Vernetzung eingebaut. Für einen „Erfahrenen“ ist die Modifikation das sicher kein Problem! Man muß nur das besagte IC und dort den Pin7 identifizieren und dann zwei dünne Drähte für die Masse- und Signalleitung anlöten. Das folgende Bild sagt mehr als viele Worte:

Folie12

Die Verschaltung der Rauchmelder erfolgt durch Paralleschaltung der jetzt an den Rauchmeldern angebrachten Vernetzung ( siehe nächstes Bild). Zum Anschluss an den Homeduino wird die Signalleitung auf einen freien analogen Eingang geführt. Jumper müssen in diesem Fall keine gesetzt werden, aber da die Signalspannung bis zu 9V betragen kann, ist zum Schutz des verwendeten Homeduino-Eingangs A0 eine Zenerdiode mit 3 bis 5V Spannung empfehlenswert.

Folie11

Die Abfrage der Signalleitung im WebUI der Homematic ist einfach, weil dafür nur der hier verwendete analoge Eingang , in diesem Fall A0, bzw. die zugehörige Systemvariable homeduino_x_A0  abgefragt werden muß.

Anmerkung: Man kann grundsätzlich auch die Rauchmelder zur wirksamen akustischen Alarmierung verwenden, wenn der analoge Eingang zur Aklarmierung als digitaler Ausgang geschaltet wird. Damit läßt sich ein Spannungssignal von ca 5V auf die Signalleitung der vernetzten Rauchmelder schalten und löst damit einen akustischen Alarm aus.

 

So schließt man einen Infrarotsensor an:

 Folie7

Beschreibung fehlt noch!

 

So schließt man einen 433Mhz-Empfänger an:

Folie6

… oder das Empfangsmodul gleich in die Platine einlöten:

Folie12

Beschreibung fehlt noch!

 So schließt man  I2C-Sensoren an:

Die serielle Kommunikation nach dem sog. I2C-Standard wird sehr gern zum universellen Anschluss von verschiedensten meist sehr intelligenten Sensoren verwendet. Benötigt werden dafür nur zwei Leitungen SDA und SCL, die beim MEGA 2650 leider nicht auf dem Homeduino I/O-Shield verfügbar sind, sondern nur an den hinteren Pfostenbuchsen des MEGA (siehe Bild). Normalerweise  wird der I2C-Bus mit 3,3V-Signalpegeln betrieben, aber der 5V- MEGA „versteht“ auch die kleineren Signalspannungen. Problematisch ist das aber für einige I2C-Sensoren, die dann die 5V-Signale vom Arduino nicht vertragen. Deshalb immer vorher vergewissern, ob die I2C-Sensoren mit nur 3,3 oder oder auch mit 5V betreibbar sind. Eventuell sind Pegelwandler notwendig, die man für wenig Geld kaufen kann. Die hier verwendeten I2C-Sensoren können ohne Zusatzelemente direkt an 5V betrieben werden. Notwendig sind dann noch für die Spannungsversorgung der I2C-Module die entsprechenden zusätzlichen zwei Leitungen.

Der I2C-Bus ist ein Datenbus für kurze möglichst kapazitätsarme Leitungen. Solange man bei den Leitungslängen unter 2m bleibt, dürfte das kein Problem sein. Längere Leitungen muß man einfach probieren oder den Takt runtersetzen. (Wie das geht , müßte man googeln)
Normalerweise benötigt der I2C-Bus auch sog. Pullup-Widerstände. Diese sind aber in den hier verwendeten Sensoren bereits eingebaut.

Anschluss Barometersensor BMP180:
Der verwendete Sensor BMP180 ist der Nachfolgesensor des BMP085. Der Sensor selbst hat normalerweise eine Versorgungsspannung von 3,3V . Aber auf dem hier verwendeten Modul ist ein Spannungsregler integriert, so dass ein Betrieb mit 5V möglich ist. Also unbedingt auf den folgenden Bildern den Modultyp vergleichen. Ansonsten kauft man die 3V-Version und beschädigt so das Modul sofort bei Inbetriebnahme! Mehr zu diesem tollen Sensor hier :  http://www.bosch-presse.de/presseforum/details.htm?txtID=5192
Den genauen Anschluss des Sensors zeigt das nachfolgende Bild:

Folie10

 

Anschluss Lichtsensor BH1750:
Die Messung der Helligkeit kann in einfacher Form mit einem  lichtabhängigen Widerstand (LDR), erfolgen. Diese Bauelemente sind in vielen Dämmerungsschaltern und Bewegungsmeldern verbaut und verrichten für „normale“ Verhältnisse ihre Funktion recht gut. Sie sind einfach anzuwenden und sehr preiswert.
Leider hat aber die Umgebungshelligkeit eine riesige Dynamik zwischen „rabenschwarzer“ Nacht und Helligkeit in der prallen Sonne!
Diese Webseite zeigt das recht anschaulich: http://s6z.de/cms/index.php/arduino/sensoren/15-umgebungslichtsensor-bh1750
Für höhere  Ansprüche an die Lichtintensitätsmessung ist deshalb die Verwendung des I2C-Sensors BH1750 anzuraten. Auch dieses Modul ist mit 5V betreibbar und kann genauso einfach wie der Barometersensor an den I2C-Bus angeschlossen werden. Dabei kann der Sensor BH1750  alleine oder zusammen mit  dem BMP180 am I2C-Bus betrieben werden. (wie im Bild oben gezeigt)

So schließt Impulsgeber und S0-Schnittstellen an:

Für die Hausautomation ist die Überwachung der Zählerstände vom Stromzähler, vom Gaszähler und vom Wasserzähler wichtig, weil nicht nur der Nutzer informiert werden kann sondern von den Veränderungen der Zählerstände auch für die Hausautomation entsprechende Steuer- und Regelmaßnahmen abgeleitet werden können. Darüberhinaus sind mittlerweile viele Solarkollektoren auf den Dächern, die mit ihrer Stromerzeugung zusätzliche wertvolle Informationen für die Steuerung der Automationskomponenten im Haus geben können; beispielsweise ob und wie stark die Sonne scheint.

Bei neueren Impulszählern sind bereits sog. S0-Schnittstellen vorhanden. Mehr dazu hier: http://de.wikipedia.org/wiki/S0-Schnittstelle
Daneben gibt es noch viele Zählersensoren mit sog. TTL-Ausgang oder auch  als sog. Open-Collector-Ausgang (O.C–Output). Alle Zähler geben entsprechend dem  Verbrauch der verschiedenen Medien eine definierte Zahl von Impulsen pro Minute oder Stunde oder Tag ab und sind somit ein Abbild des Verbrauches.

Am Homeduino können direkt am I/O-Shield maximal 2 Impulsgeber angeschlossen werden. Wer mehr benötigt, der kann 4 weitere Impulsgeber an die bisher ungenutzten hinteren Datenpins des MEGA 2560 anschließen. In nächster Zeit wird ein weiteres ergänzendes I/O-Shield verfügbar sein, daß auch die hinteren Pins des MEGA über Schraubklemmen einfach verfügbar macht. Die folgenden Bilder zeigen die Anschlußkonfiguration der verschiedenen Zählergeber an den Homeduino:
Folie26

 

Folie27

 

Folie28

 

Die Integration der zugehörigen Software in das Homeduino Sensormodul  war nicht ganz einfach, weil bei einem regelmäßigen Abfragen der verwendeten Impulseingänge u.U. Impulse verloren gehen können. Deshalb wurden zur Impulszählung nur die verfügbaren Dateneingänge mit direkter Interrupt-Möglichkeit verwendet. Damit wird das laufende Sketch bei jedem neuen Impuls unterbrochen und mit einer Interruptroutine der entsprechende Zähler inkrementiert. Mehr dazu oben im Listing des aktuellen Sketches.

Was muß man tun, um die Zählerfunktion zu implementieren?
Zuerst muß sicher gestellt sein, daß die für die Impulszählung verwendeten Systemvariablen  homeduino_x_imp xy  auch  in der CCU definiert sind. Danach ist das aktuelle Sketch noch mit den sog. user-eingaben auf die Bedürfnisse des Anwenders einzustellen.  Der für die Impulszählung relevante Definitionsteil ist im Sketch:

volatile unsigned long pulsecounter[6] = {0,  //Zaehlerstand fuer D2-Impulseingang bei Reset                                        <<user-eingabe<< 
                                          9630,  //Zaehlerstand fuer D3-Impulseingang bei Reset                                     <<user-eingabe<<  
                                          0,  //Zaehlerstand fuer D21-Impulseingang bei Reset                                       <<user-eingabe<<   
                                          0,  //Zaehlerstand fuer D20-Impulseingang bei Reset                                       <<user-eingabe<<  
                                          0,  //Zaehlerstand fuer D19-Impulseingang bei Reset                                       <<user-eingabe<< 
                                          0,  //Zaehlerstand fuer D18-Impulseingang bei Reset                                       <<user-eingabe<< 
                                         };        
//hier wird der Teilerfaktor für die Impulszaehler festgelegt
int pulsedivider[6] = {5,  //Teilerfaktor fuer D2 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor                              <<user-eingabe<< 
                       1,  //Teilerfaktor fuer D3 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor                              <<user-eingabe<<  
                       1,  //Teilerfaktor fuer D21 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor                             <<user-eingabe<<  
                       1,  //Teilerfaktor fuer D20 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor                             <<user-eingabe<<  
                       1,  //Teilerfaktor fuer D19 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor                             <<user-eingabe<<  
                       1,  //Teilerfaktor fuer D18 : wenn 0, dann keine Zaehlfunktion, sonst Teilfaktor                             <<user-eingabe<<  
                      };

Mit dem oberen Definitionsteil können die Zählerstände einen bestimmten Startwert bekommen. Im unteren Definitionsteil sind für jeden Zählkanal beliebige ganzzahlige Teilerfaktoren definierbar, um die Impulsfrequenzen mit  einem gewünschten Teilerfaktor zu reduzieren. Das ist ganz praktisch, um eine  Impulszählung des Strom- oder Gaszählers beispielsweise auf KWh  o.ä. zu normieren.

 

Weitere Sensoren werden folgen !

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.

 

 

 

Vielseitiges I/O-Shield-Board 2.0 für (fast) alle Arduinos

Vielseitiges I/O-Shield-Board 2.0 für (fast) alle Arduinos

Hier wurde bereits ein universelles I/O-Shield Board für den Arduino beschrieben und für Interessierte einige  Komplettbausätze mit SMDs zur Verfügung gestellt.
https://www.stall.biz/?project=praxistaugliches-universelles-io-shield-board-fur-arduino .
Allerdings ist das Löten von SMDs doch nicht jedermanns Sache, weshalb jetzt ein neues auch funktional weiter verbessertes I/O-Shield   bei mir erhältlich ist. Dieses Board ermöglicht mit Schraubklemmen  den Anschluß von vielen Sensoren und Aktoren, die insbesondere für den Arduino  sehr günstig zu erwerben sind.

Das I/O-Shield als Bausatz können Sie in meinem Shop kaufen: https://www.stall.biz/?product=io-shield-2-0
Die Baubeschreibung hier zeigt, wie einfach der Zusammenbaus ist:  https://www.stall.biz/wp/wp-content/uploads/2015/03/Bauanleitung_shield.pdf

Hier die Beschreibung der Eigenschaften :

1  Allgemeines

Der Arduino hat in  den meisten  verbreiteten Ausführungen Stiftleisten mit standardisiertem Pinout. Durch Zusammenstecken verschiedener Platinen sog.  Shields sind nahezu alle Funktionen darstellbar, die im Bereich der Automation und insbesondere der Hausautomation benötigt werden. Allerdings ist normalerweise die notwendige Anschlusstechnik zu den Sensoren und Aktoren nur sehr unbefriedigend über Steckbrettchen oder Prototypen-Shields möglich. Die heute am Markt erhältlichen fertigen Prototypen- oder  I/O-Shields führen meistens einfach nur die Signale der Arduino-Stiftleisten auf Schraubklemmen. Damit lassen sich aber oft nicht die Sensoren und Aktoren direkt anschließen und man benötigt weitere Bauelemente wie Treiber und Widerstände. Und schon ist wieder ein unzuzverlässiger „Drahtverhau“ entstanden 😉

Der hier gewählte Ansatz für ein I/O-Shield führt die Signale der Stiftleisten an Anschlußklemmen, allerdings sind auf dem Board für jeden Port zusätzliche Bauelemente integriert, die entsprechend dem individuellen Bedarf per Jumper „programmierbar“ sind. Damit kann die gewünschte Funktionalität jeder einzelnen Anschlussklemme bzw. jedes einzelnen Ports dem typischen Bedarf in der Hausautomation angepaßt werden.

2  Eigenschaften des I/O-Shield-Boards

Das I/O-Shield-Board hat Stiftleisten mit dem gleichen Pinout wie die meisten Arduinos. Damit kann es unproblematisch mit fast allen Arduinos zusammengesteckt werden. Oben auf der Platine sind Stiftbuchsen und unten Stiftstecker, so daß die Signale komplett einschließlich ISP-Anschluss durchgereicht werden. Damit kann das Shield bei mehreren zusammengesteckten Shields in jeder beliebigen „Etage“ betrieben werden. Das I/O-Shield-Board ist dabei nur eine Teilkomponente, die eigenständig nicht funktionsfähig ist, sondern erst mit weiteren Komponenten und dem Arduino-Board in die gewünschte Funktion gebracht werden kann.  Darüberhinaus ist das Ganze vom Anwender noch in ein Gehäuse einzubauen und mit der notwendigen Anschlusstechnik und einem Netzteil  zu versehen.

Hier die Eigenschaften des I/O-Shield-Boards im Detail:

  •   17  I/Os insgesamt werden nach außen auf Schraubklemmen geführt  (D2 … D13 und A0 … A5) und sind alle jeweils mit 150 Ohm Schutzwiderständen gegen Kurzschluss geschützt
  •   11  I/Os sind davon ausschliesslich  digitale I/O-Ports , davon sind …
  •   8  digitale I/Os  (D2 … D9) , welche alle  per Jumper programmierbare MOSFET-Treiber,  LED-Statusanzeigen und 4k7-Pullup-Widerstände besitzen
    (die  verwendeten  IRLML0030 – MOSFETs  können  Ströme >2A und Spannungen bis 24V schalten, Hochstrom-LEDs und Infrarot-LEDs sind damit ebenfalls direkt steuerbar, z.B. pulsweitenmoduliert)
  •   6  analoge I/Os (A0 … A5) können als anloge Eingänge und digitale Ausgänge verwendet werden. Dabei können die Eigenschaften als analoge Eingänge per Jumper programmiert werden:
    Programmierbare Eingangsspannungsbereiche:    0 bis +5V;    0 bis +10V;    -5V bis +5V;
    Darüberhinaus kann ein 10k Ohm Pullup-Widerstand z.B. für NTCs zugeschaltet werden.
  •   1  Trimmpotentiometer ist vorhanden, mit dem eine analoge Spannung (0 …+5V) z.B. zum Testen über Jumper und Taster auf die analogen Eingänge geschaltet werden kann
  •   1 Reset-Taster, mit dem ein Arduino-Reset ausgelöst werden kann. (Wichtig, weil man beim Etagenaufbau oft nicht an den Arduino Reset-Taster  dran kommt!)
  •   Lötpads zum Anschluss für die  verbreiteten 433Mhz-Sender (an Port D05)  und -Empfänger (an Port D03) u.a. für die Steuerung von Funkschaltsteckdosen
  •   Lötpads für  5V-Buzzer  (Port D07)

Das nächste Bild zeigt das fertige Board von der Bestückungsseite:

Bild_5

Mit dem nachfolgenden Schemabild erklärt sich für den Fachmann die Funktion der Jumper-Programmierung :

Folie3

Und hier sieht man, wo welche Jumper gesetzt werden müssen.

Folie5

Das I/O-Shield_Board im typischen Etagenverbund:

Biold_3

Auf dem Board können sehr einfach  die sehr  preiswerten kleinen 433Mhz-Sender und -Empfänger eingelötet werden. Damit lassen sich dann Funksteckdosen aus dem Baumarkt etc. steuern und auch deren ausgesendeter Code empfangen.
Bild_8

 

3  Anwendungsmöglichkeiten

Verwendbar ist das Shield für nahezu alle Arduinos mit dem standardmäßigen Pinout.
Das sind heute : UNO,  Duemilanove,  MEGA2650, YUN,  Due, Leonardo, und ,und, und.
Sicher wird das verwendete Pinout auch in zukünftigen Arduinos verbreitet sein, so daß das Shield immer wieder eingesetzt werden kann!
Die Anschlussmöglichkeiten von Sensoren und Aktoren sind natürlich sehr vielseitig und können hier nicht alle beschrieben werden.

Weiter hervorzuheben ist, daß mit dem I/O-Shield  sehr einfach auch stromhungrige Aktoren bis zu 24V geschaltet werden können. Aber es sind auch sehr verbreitete sog. 1-Wire-Temperatursensoren wie die DS18B20 Sensoren direkt anzuschalten. NTC-Temperatursensoren können sogar  direkt angeklemmt werden, weil der notwendige 10k-Pullup-Widerstand einfach per Jumper  zugeschaltet wird.

Und wer doch gerne die zuverlässigen Federklemmleisten von WAGO oder PHOENIX einsetzen möchte, der kann statt der  verwendeten Schraubklemmleisten die entsprechenden Federklemmleisten einlöten. Das Platinenlayout ist so gestaltet, daß Klemmleisten im 2,5mm und 5mm Rastermaß passen. Hier ein Beispiel eines  I/O-Shields mit jeweils einer typischen Federklemmleiste im 2,5mm Rastermaß und einer im 5mm-Rastermaß:

Bild_10

Ganz besonders ist das I/O-Shield-Board für den Homeduino geeignet. Dies ist ein Hard- und Software-Konzept auf Basis von verbreiteten Arduino-Komponenten, mit dem sich drahtgebunden über LAN oder drahtlos über WLAN recht einfach per Browserbefehlen die verschiedensten Sensoren und Aktoren in die heimische  Automatisierung einbinden lassen. Mehr dazu hier:
https://www.stall.biz/?project=homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation


4  Wo bekommt man  das I/O-Shield-Board ?

Das I/O-Shield_Board gibt es nur als Teil-Bausatz. Dabei sind die sehr schwierig zu handhabenden SMD-Teile bereits auf der Platine verlötet. Andere Bauteile wie die 433Mhz-Sender und -Empfänger und auch der Buzzer müssen selbst beschafft und nach Bauanleitung in die Platine eingelötet werden. Auch die Programmierung der Jumper ist beispielsweise nach den gewünschten Pinfunktionen vorzunehmen. Entsprechende Beispiele und Lösungsansätze findet man u.a. im Homeduino -Projekt auf dieser Website.

Das I/O-Shield als Bausatz können Sie in meinem Shop kaufen: https://www.stall.biz/?product=io-shield-2-0

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.

 

 

 

 

 

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

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

Wichtiger Hinweis: Es gibt mittlerweile eine neue Softwareversion:   Homduino 4.0

Hier werden die Anwendungsmöglichkeiten mit dem aktuellen Homeduino I/O-Shield 2.0 beschrieben. Dies ist ein Update des vorhergehenden Artikels zum Homeduino I/O-Shield 1.0   https://www.stall.biz/?project=homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation

Update 26.04.2015:  Installationsanleitung der Entwicklungsumgebung aktualisiert.

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.

1  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  aus meinem Shop: https://www.stall.biz/?product=io-shield-2-0

 uebersicht

2  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 sind direkt steuerbar. Der elektrische Anschluss erfolgt mittels Schraubklemmen, damit ein zuverlässiger Betrieb ohne die beim Arduino häufig anzutreffenden “fliegenden” Breadboard-Aufbauten möglich ist! Alternativ sind auch Federklemmleisten von WAGO oder Phoenix im 5mm-Raster verwendbar.

Folie3

 

Folie5_1
Mit dem verwendeten Homeduino I/O-Shield 2.0 stehen insgesamt 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 zu vielen Funktionen “überfrachtet” wird. Stattdessen sollten sehr umfangreiche Steuerungsaufgaben besser auf mehrere Homeduinos verteilt werden.
Natürlich  kann das IO-Shield auch für die “kleinen” Arduinos wie der UNO verwendet werden, allerdings sind dann die Programmkapazitäten doch deutlich kleiner und nicht alle hier dargestellten Funktionalitäten implementierbar .

Der Homeduino hat mit dem optionalen I/O-Shield 2.0  bis zu…

>> 6 analoge Eingänge:
– 0 bis +5V, 0 bis +10V oder -5 bis +5V per Jumper kanalweise umschaltbar
– Port auch verwendbar  als digitaler schneller Input 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 LED zur Anzeige des digitalen Zustandes
– 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:

Folie7
Jedem digitalen Eingang (D2 bis D9)  und jedem analogen Eingang (A0 bis A5) ist jeweils eine 6-polige Stiftleiste zugeordnet, mit der unter Verwendung von Jumpern sehr unterschiedliche Funktionalitäten des korrespondierenden Ports aktiviert werden können. Das folgende Bild zeigt die entsprechenden Positionen der Jumper und die zugehörigen Funktionen:
Folie4

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 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 einfach  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\”

Ergänzung 26.04.2015: Mittlerweile gibt es neuere Versionen der Arduino Entwicklungsumgebung. Leider führen diese mit den hier verwendeten Libraries manchmal zu Fehlermeldungen beim Compilieren. Deshalb hier meine komplette verwendete Entwicklungsumgebung mit Version 1.5.8 :
https://dl.dropboxusercontent.com/u/6223164/arduino1.5.8_homeduino.zip
Das weiter unten veröffentlichte Homeduino-Sketch befindet sich dabei schon im“sketchbook“. Bei Verwendung dieser Entwicklungsumgebung können die nächsten Schritte übersprungen werden. Weiter geht’s dann mit mit Schritt 11.

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.

11. 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"; 
// fuer Arduino Mega 2560 mit Arduino 1.5.6r2
//Verfasser: Eugen Stall
// diese Software erlaubt die Steuerung der Pinfunktionen mit einfachen Browserbefehlen
//verwendete Quellen fuer libraires und Programme siehe Beschreibung und Erläuterungen im Quelltext
//die aktuellste Version ist immer hier:
//https://www.stall.biz/?project=homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation
 
#include <Ethernet.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RCSwitch.h>
#include <IRremote.h>
#include <Time.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
#include <SFE_BMP180.h>
#include <EEPROM.h>
 
String ver = "homeduino_20.ino / Stand: 2014.09.13"; // Versionsbezeichner
 
////////////////////////////////////////////////////////////////////////
//Netzwerk-Konfiguration muss individuell hier eingegeben werden
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); //server port 80
 
byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU //<<user-eingabe<< 
EthernetClient client;
 
//Variablendefinitionen:
boolean reading = false;
boolean valid_command = false;
String command = String(200); // string for fetching data from address
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; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
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; // 1 wenn ein ir-receiver an pin D2 verwendet wird
boolean rf_enable = 1; // 1 wenn ein rf-receiver an pin D3 verwendet wird
int schaltschwelle_high[]= {1023,1023,1023,510,510,510}; //schaltschwelle der Analogeingänge , //<<user-eingabe<<
 //wenn analogwert grösser, dann high
int schaltschwelle_low[]= {0,0,0,100,100,100}; //schaltschwelle der Analogeingänge , //<<user-eingabe<<
 //wenn analogwert kleiner, dann low 
 
int RECV_PIN = 2; 
IRrecv irrecv(RECV_PIN); //2 ist der IR- Empfangspin D2
IRsend irsend; // sendepin ist beim MEGA2650  D9!
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;
// Storage for the recorded code
int codeType = -1; // The type of code
unsigned long codeValue; // The code value if not raw
unsigned int rawCodes[RAWBUF]; // The durations if raw
int codeLen; // The length of the code
int count;
int STATUS_PIN = 13;
int addr;
 
SFE_BMP180 pressure;
int altitude = 229.0; // hoehe des barometer-standortes
boolean lcd_text_anzeigen; 
 
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
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; // nächste regelabtastung der analogen digitaleingänge alle 600 sec 
 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); //lED leuchtet während der Abarbeitung der Befehle
 digitalWrite(9, HIGH);} // Start the ir-receiver auf pin D2
 if (rf_enable = true) {mySwitch.enableReceive(1);} //start rf receiver auf pin D3
 
 lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines and turn on backlight
 lcd.backlight();
 }
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void loop()
{ 
 command = ""; //String(100);
 EthernetClient client = server.available();
 if (client) 
 { // an http request ends with a blank line
 boolean currentLineIsBlank = true;
 while (client.connected())
 { if (client.available()) 
 { char c = client.read();
 if (reading && c == ' ') reading =false;
 if (c == '?') reading = true; // beginn der Befehlssequenz 
 if (reading) 
 { //read char by char HTTP request
 if (command.length() < 100) 
 { //store characters to string
 command = command + c;
 }
 } 
 if (c == '\n' && currentLineIsBlank) break;
 if (c == '\n') 
 { currentLineIsBlank = true;} else if (c != '\r') 
 { currentLineIsBlank = false;}
 }
 }
////////////////////////////////////////////////////////////////////////
pinMode(13, OUTPUT); //lED leuchtet während der Abarbeitung der Befehle
digitalWrite(13, HIGH);
 
//jetzt wird das command ausgeführt 
// befehl herausmaskieren
int colonPosition = command.indexOf(':');
befehl = command.substring(1,colonPosition);
command = command.substring((colonPosition+1)); //Rest-command bilden
 
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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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;}; //kanalnummern max 2 stellen erlaubt
 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");
 
}
 
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if ((befehl == "ir_receive")&& (ir_enable == true)) //
 {valid_command = true; 
 decode_results results;
 irrecv.enableIRIn(); // Start the receiver
 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(decod);
         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(); // weitermachen mit empfangen
        } 
 }
 client.print("end ir_receive :" + command + " \n\r"); 
 }
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if (befehl == "ir_send") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 code_type = 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(); 
 
 if (code_type == "nec") {for (int i = 0; i < 1; i++) {
 irsend.sendNEC(param1, param2); // NEC code
 delay(40);}}
 
 if (code_type == "sony") {for (int i = 0; i < 3; i++) {
 irsend.sendSony(param1, param2); // Sony code
 delay(40);}} 
 
 if (code_type == "rc5") {for (int i = 0; i < 3; i++) {
 irsend.sendRC5(param1, param2); // rc5 code
 delay(40);}} 
 
 if (code_type == "rc6") {for (int i = 0; i < 3; i++) {
 irsend.sendRC6(param1, param2); // rc6 code
 delay(40);}} 
 
 client.print("ir_send mit Sendecode :" + command + " \n\r"); 
} 
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if (befehl == "ir_rawstore")
 {valid_command = true; 
  colonPosition = command.indexOf(':');
  if (colonPosition > 2) {valid_command = false;}; //speicherplaetze max 2 stellen erlaubt
  parameter = command.substring(0,colonPosition);
  param = parameter.toInt(); 
 
  decode_results results;
  irrecv.enableIRIn(); // Start the receiver
  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);  
         //IR-Code im EEPROM speichern, Werte wieder zurueckholen und ausgeben
         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(); // resume receiver
     digitalWrite(STATUS_PIN, LOW);
    } 
 }
 client.print("end ir_rawstore auf Speicherplatz: " + parameter + " \n\r"); 
}
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if (befehl == "ir_rawsend") 
 { valid_command = true; 
   colonPosition = command.indexOf(':');
   if (colonPosition > 2) {valid_command = false;}; //speicherplaetze max 2 stellen erlaubt
   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);// Assume 38 KHz
   client.print("ir_rawsend von Speicherplatz :" + parameter + " \n\r"); 
 }
 
//###########################################################################
// Quellen: http://code.google.com/p/rc-switch/
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(); 
 
 //RCSwitch mySwitch = RCSwitch();
 mySwitch.enableTransmit(param);
 // Optional set pulse length.
 // mySwitch.setPulseLength(320);
 // Optional set protocol (default is 1, will work for most outlets)
 // mySwitch.setProtocol(2);
 // Optional set number of transmission repetitions.
 // mySwitch.setRepeatTransmit(15);
 
 mySwitch.send(param1, param2);
 client.print("rf_send mit Sendecode :" + command + " \n\r"); 
} 
//###########################################################################
//Quellen http://code.google.com/p/rc-switch/ 
if ((befehl == "rf_receive")&& (rf_enable == true)) 
 { valid_command = true; 
 //mySwitch.enableReceive(1); //receiver on interrupt 1 => that is pin D3
 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; }; //kanalnummern max 2 stellen erlaubt
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 onewire_pin = parameter.toInt();
//Setup onewire//////////////////////////////////////////////////////////////////////
//long intervall_onewire =10000; //onewire-Operation alle 10sec
//long lastTime_onewire =0;
float tempC[10]; // 10 Onewire-Sensoren werden maximal verwendet
 
OneWire oneWire(onewire_pin); 
DallasTemperature sensors(&oneWire);
DeviceAddress TempSensor[] = //Adress-Array definieren
{ 
 { 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<<
};
 // Start up the library
 sensors.begin();
 // aufloesung 10 bit
 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);
 
//Setup onewire//////////////////////////////////////////////////////////////////////
 while (command.length() > 1 ) 
 { colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; //kanalnummern max 2 stellen erlaubt
 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");
 } 
} 
//###########################################################################
//Quellen: http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino
if (befehl == "1wire") /// Unterprogramm fuer 1wire Abfrage von einzelnen Sensoren
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; //kanalnummern max 2 stellen erlaubt
 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; } //find a device
 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); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( i = 0; i < 9; i++) { data[i] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5    // Calculate temperature value 18S20
 }
 client.print("1wire T" + parameter + " = " + temp_tur + " Celsius / pin D" + param + " as input \n\r");
 }
}
//###########################################################################
//Quellen:http://fluuux.de/2012/09/arduino-adressen-aller-ds1820-ermitteln/
if (befehl == "1wire_address") /// Unterprogramm fuer Auslesen der Sensoradresse
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; //kanalnummern max 2 stellen erlaubt
 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;} //0x10 = DS18S20
 else { if (address[0] == 0x28) { client.print("Device is a DS18B20 : "); tmp = 1; } //0x28 = DS18B20
 }
 if (tmp == 1) //display the address, if tmp is ok 
 {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++) //all is ok, display it
 { 
 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;
 }
 }//end if tmp
 }//end while
 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; }; //kanalnummern max 2 stellen erlaubt
 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;}; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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");
} 
 
//###########################################################################
//Quellen: https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
//library: https://github.com/sparkfun/BMP180_Breakout/tree/master/software/Arduino/libraries/SFE_BMP180
if (befehl == "barometer") 
{ valid_command = true; 
  colonPosition = command.indexOf(':');
  if (colonPosition > 4) {valid_command = false;}; //maximal 4 stellen erlaubt
   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;
      // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.
 
  client.print("Meereshoehe NN : ");
  client.print(parameter);
  client.print(" m\n\r"); 
 
  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:
    delay(status);
 
    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Function returns 1 if successful, 0 if failure.
    status = pressure.getTemperature(T);
    if (status != 0)
    { // Print out the measurement:
      client.print("Temperatur     : ");
      client.print(T,1);
      client.print(" gradC \n\r");  
 
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.
      status = pressure.startPressure(3);
      if (status != 0)
      { // Wait for the measurement to complete:
        delay(status);
 
        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.
 
        status = pressure.getPressure(P,T);
        if (status != 0)
        { // Print out the measurement:
          client.print("Druck absolut  : ");
          client.print(P,2);
          client.print(" mb\n\r"); 
 
          // The pressure sensor returns abolute pressure, which varies with altitude.
          // To remove the effects of altitude, use the sealevel function and your current altitude.
          // This number is commonly used in weather reports.
          // Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.
          // Result: p0 = sea-level compensated pressure in mb
 
          p0 = pressure.sealevel(P,param); //Messung
 
          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");} 
} 
//###########################################################################
//Quelle source code:  http://arduino-info.wikispaces.com/LCD-Blue-I2C#v3
// library hier :https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/LiquidCrystal_V1.2.1.zip
if (befehl == "display") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; }; //spalten max 2 Stellen erlaubt
 if (command.length() < 2) {lcd.clear();} //display loeschen nur mit befehl /?display:
 parameter = command.substring(0,colonPosition);
 param2 = parameter.toInt(); //spalte ist param2
 command = command.substring((colonPosition+1));
 colonPosition = command.indexOf(':');
 if (colonPosition > 1) {valid_command = false; }; //zeilen max 2 Stellen erlaubt
 parameter = command.substring(0,colonPosition);
 param3 = parameter.toInt(); //zeile ist param3
 command = command.substring((colonPosition+1));
 command.replace("%20", " ");//hier http-leerzeichen ersetzen
 //langere strings werden in 20-zeichen-haeppchen zerlegt
 //weil display sonst zeile ueberspringt. fehler in library ??
 int m = 0; //laufvariable
 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(); 
 
//###########################################################################
 // delay(100); // give the web browser time to receive the data
 client.stop(); // close the connection:
 }
//###########################################################################
pinMode(13, OUTPUT); //lED leuchtet während der Abarbeitung der Befehle
digitalWrite(13, LOW);
//hierhin kommen eigenständige Steuerung-_Programme, die dauernd zyklisch durchlaufen werden, 
//wenn aktuell keine http-Anfrage abgearbeitet wird:
//////////////////////////////////////////////////////////////////////// 
// IR empfang 
if (ir_enable == true) 
 {if (irrecv.decode(&results)) // IR-Signal da?
 { dump(&results); 
 ir_decode(); //Dekodieren
 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();
 }
 } 
 }
 }
//###########################################################################
//////////////////////////////////////////////////////////////////////// 
// RF empfang 
if (rf_enable == true) 
 { if (mySwitch.available()) // RF-Signal da?
 { 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(); //Dekodieren
 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();
 }
 }
 }
 }
 } 
//###########################################################################
// hier werden alternativ die analogeingänge als digitaleingänge verwendet, 
// und bei änderung die entsprechenden gespiegelten HM-Systemvariablen "homeduino_ax" 
// in der ccu entweder bei änderung der eingangssignale oder 
// aber immer alle 10min aktualisiert. 
// umschaltung zwischen analog- und digital-modusmit der variablen variablen ana_as_digital 
int i = 0;
int messwert;
String kanal;
String logikpegel;
String befehl;
akt_zeit = now();
 
if (akt_zeit > next_update)
 { next_update = next_update +600; // nächste zwangsaktualisierung in 10min
 while (i < 6) {Ax_alt[i] = !Ax_alt[i]; i=i+1; } // der altzustand wird komplementiert
 i = 0;
 }
 
if (akt_zeit > (last_get+5)) //sicherstellen, dass nicht häufiger als alle 5sec aktualisiert wird
{
 if (client.connect(ccu, 8181)) 
 { while (i < 6) 
 { messwert = analogRead(i); 
 if ((messwert < schaltschwelle_low[i]) && (Ax_alt[i] == 1 )) //bei aenderung des logikpegels, dann aenderungsmitteilung senden 
 { 
 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(); 
 }
}
//###########################################################################
}
//##################### ende Hauptprogramm #############################
 
 
 
 
//#################### Unterprogramme nachfolgend ######################################
 
//########################################################################################
//Unterprogramm zur Befehlserkennung der IR-Signale 
//
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;
 
// bis 254 Codes möglich
 
 default: rf_key = 255;
 }
 rfkey = String(rf_key);
 
} 
 
//########################################################################################
//Unterprogramm zur Befehlserkennung der IR-Signale 
//
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;
 
// bis 254 Codes möglich
 
 default: ir_key = 255;
 }
 irkey = String(ir_key);
 
}
//########################################################################################
//Quelle: Beispielprogramm aus der IRremote library
// Dumps out the decode_results structure. 
// Call this after IRrecv::decode()
// void * to work around compiler issue
void dump(void *v) {
decode_results *results = (decode_results *)v;
//void dump(decode_results *results) {
 
//werte als public variable speichern
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;
 }
 }
 
//##############################################################
// Stores the code for later playback Most of this code is just logging
void storeCode(decode_results *results)
{count = results->rawlen;
 codeLen = results->rawlen - 1;
 if (codeLen > 98) {codeLen =99;} //nur codelaengen bis 98 zulaessig
 // To store raw codes: Drop first value (gap) Convert from ticks to microseconds
 // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
 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");}// Mark
     else {rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS; Serial.print(" s");}// Space
   Serial.print(rawCodes[i - 1], DEC);
 
   //in EEPROM speichern 200bytes je IR-Code_Speicherplatz
   addr = 200*param + 2*(i-1);
   val = rawCodes[i - 1]/256;
   EEPROM.write(addr, val);  //schreibe High-Byte
   EEPROM.write(addr+1, rawCodes[i - 1] - val);  //schreibe Low-Byte
   k= k+1;
   if (k>10) {k=1; Serial.print("\n\r");}
 }
  //jetzt noch codeLen im EEPROM ablegen
   addr = 200*param + 2*99;
   val = codeLen/256;
   EEPROM.write(addr, val);  //schreibe High-Byte
   EEPROM.write(addr+1, codeLen - val);  //schreibe Low-Byte
   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. Werden die Pins D2 bis D9 als Eingänge verwendet, um beispielsweise Schaltersensoren abzufragen, dann sind ggf. mit den Jumpern  entsprechende Pullup-Widerstände (4k7) einzuschalten. Die Schaltungsbeispiele im nachfolgenden Bild zeigen typische digitale Ein- und Ausgänge.

Folie8

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)

Folie9

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};                      //Schaltschwelle High der Analogeingänge

int schaltschwelle_low[]= {200,0,0,0,0,100};                                                //Schaltschwelle  LOW der Analogeingänge

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!

Folie10

6.6 Temperaturmessung mit NTC

Eine Temperaturmessung mit einem Thermistor oder NTC-Widerstandssensor 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 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; //aus dem Datenblatt des NTC

Folie21

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.

Folie16

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 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;

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);
 }

Folie17
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 parallelgeschaltet  an einem der Ports D2 bis D9 angeschlossen sind. Das folgende Beispiel zeigt ausschnittartig die Adressen meiner verwendeten 1Wire-Sensoren im Homeduino-Sketch:

OneWire oneWire(onewire_pin); 
DallasTemperature sensors(&oneWire);
DeviceAddress TempSensor[] = //Adress-Array definieren
{ 
 { 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 Sensor  anzulegen. Weiteres Vorgehen und HM-Skript dazu  ähnlich wie bei dem Einzelsensor.

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 !!

Folie20
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;   // 1 wenn ein ir-receiver an pin D2 verwendet wird

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:

//Unterprogramm zur Befehlserkennung der IR-Signale
//
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;

// bis 254 Codes möglich

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.

Folie18
Folie19

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, da sehr zeitaufwändig!

 

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;                 // 1 wenn ein rf-receiver an pin D3 verwendet wird

Folie11Folie12
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:

//Unterprogramm zur Befehlserkennung der IR-Signale
//
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;

// bis 254 Codes möglich

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

Mehr Info hierzu : https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic
Entsprechendes HM-Skript wie in den Beispielen vorher.

 

Folie15

6.13 LCD-Display mit I2C

Funktion schon integriert.  Befehle  dafür:  display
Mehr Info hierzu : https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic
Entsprechendes HM-Skript wie in den Beispielen vorher.

 

6.14  Barometer Sensor BMP 180

Funktion schon integriert. Beschreibung fehlt noch!  Befehle  dafür:  barometer
Mehr Info hierzu : https://www.stall.biz/?project=der-homeduino-2-0-als-vielseitiges-lanwlan-sensormodul-fur-die-homematic
Entsprechendes HM-Skript wie in den Beispielen vorher.

7  Bezugsquelle für das Homeduino I/O-Shield 2.0

Das I/O-Shield als Bausatz können Sie in meinem Shop kaufen: https://www.stall.biz/?product=io-shield-2-0

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.

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

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

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"; 
// fuer Arduino Mega 2560 mit Arduino 1.5.6r2
//Verfasser: Eugen Stall
// diese Software erlaubt die Steuerung der Pinfunktionen mit einfachen Browserbefehlen
//verwendete Quellen fuer libraires und Programme siehe Beschreibung und Erläuterungen im Quelltext
//die aktuellste Version ist immer hier:
//https://www.stall.biz/?project=homeduino-der-universelle-lanwlan-arduino-fur-die-hausautomation
 
#include <Ethernet.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RCSwitch.h>
#include <IRremote.h>
#include <Time.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
#include <SFE_BMP180.h>
#include <EEPROM.h>
 
String ver = "homeduino_20.ino / Stand: 2014.09.13"; // Versionsbezeichner
 
////////////////////////////////////////////////////////////////////////
//Netzwerk-Konfiguration muss individuell hier eingegeben werden
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); //server port 80
 
byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU //<<user-eingabe<< 
EthernetClient client;
 
//Variablendefinitionen:
boolean reading = false;
boolean valid_command = false;
String command = String(200); // string for fetching data from address
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; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
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; // 1 wenn ein ir-receiver an pin D2 verwendet wird
boolean rf_enable = 1; // 1 wenn ein rf-receiver an pin D3 verwendet wird
int schaltschwelle_high[]= {1023,1023,1023,510,510,510}; //schaltschwelle der Analogeingänge , //<<user-eingabe<<
 //wenn analogwert grösser, dann high
int schaltschwelle_low[]= {0,0,0,100,100,100}; //schaltschwelle der Analogeingänge , //<<user-eingabe<<
 //wenn analogwert kleiner, dann low 
 
int RECV_PIN = 2; 
IRrecv irrecv(RECV_PIN); //2 ist der IR- Empfangspin D2
IRsend irsend; // sendepin ist beim MEGA2650  D9!
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;
// Storage for the recorded code
int codeType = -1; // The type of code
unsigned long codeValue; // The code value if not raw
unsigned int rawCodes[RAWBUF]; // The durations if raw
int codeLen; // The length of the code
int count;
int STATUS_PIN = 13;
int addr;
 
SFE_BMP180 pressure;
int altitude = 229.0; // hoehe des barometer-standortes
boolean lcd_text_anzeigen; 
 
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
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; // nächste regelabtastung der analogen digitaleingänge alle 600 sec 
 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); //lED leuchtet während der Abarbeitung der Befehle
 digitalWrite(9, HIGH);} // Start the ir-receiver auf pin D2
 if (rf_enable = true) {mySwitch.enableReceive(1);} //start rf receiver auf pin D3
 
 lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines and turn on backlight
 lcd.backlight();
 }
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void loop()
{ 
 command = ""; //String(100);
 EthernetClient client = server.available();
 if (client) 
 { // an http request ends with a blank line
 boolean currentLineIsBlank = true;
 while (client.connected())
 { if (client.available()) 
 { char c = client.read();
 if (reading && c == ' ') reading =false;
 if (c == '?') reading = true; // beginn der Befehlssequenz 
 if (reading) 
 { //read char by char HTTP request
 if (command.length() < 100) 
 { //store characters to string
 command = command + c;
 }
 } 
 if (c == '\n' && currentLineIsBlank) break;
 if (c == '\n') 
 { currentLineIsBlank = true;} else if (c != '\r') 
 { currentLineIsBlank = false;}
 }
 }
////////////////////////////////////////////////////////////////////////
pinMode(13, OUTPUT); //lED leuchtet während der Abarbeitung der Befehle
digitalWrite(13, HIGH);
 
//jetzt wird das command ausgeführt 
// befehl herausmaskieren
int colonPosition = command.indexOf(':');
befehl = command.substring(1,colonPosition);
command = command.substring((colonPosition+1)); //Rest-command bilden
 
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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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;}; //kanalnummern max 2 stellen erlaubt
 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");
 
}
 
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if ((befehl == "ir_receive")&& (ir_enable == true)) //
 {valid_command = true; 
 decode_results results;
 irrecv.enableIRIn(); // Start the receiver
 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(decod);
         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(); // weitermachen mit empfangen
        } 
 }
 client.print("end ir_receive :" + command + " \n\r"); 
 }
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if (befehl == "ir_send") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 code_type = 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(); 
 
 if (code_type == "nec") {for (int i = 0; i < 1; i++) {
 irsend.sendNEC(param1, param2); // NEC code
 delay(40);}}
 
 if (code_type == "sony") {for (int i = 0; i < 3; i++) {
 irsend.sendSony(param1, param2); // Sony code
 delay(40);}} 
 
 if (code_type == "rc5") {for (int i = 0; i < 3; i++) {
 irsend.sendRC5(param1, param2); // rc5 code
 delay(40);}} 
 
 if (code_type == "rc6") {for (int i = 0; i < 3; i++) {
 irsend.sendRC6(param1, param2); // rc6 code
 delay(40);}} 
 
 client.print("ir_send mit Sendecode :" + command + " \n\r"); 
} 
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if (befehl == "ir_rawstore")
 {valid_command = true; 
  colonPosition = command.indexOf(':');
  if (colonPosition > 2) {valid_command = false;}; //speicherplaetze max 2 stellen erlaubt
  parameter = command.substring(0,colonPosition);
  param = parameter.toInt(); 
 
  decode_results results;
  irrecv.enableIRIn(); // Start the receiver
  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);  
         //IR-Code im EEPROM speichern, Werte wieder zurueckholen und ausgeben
         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(); // resume receiver
     digitalWrite(STATUS_PIN, LOW);
    } 
 }
 client.print("end ir_rawstore auf Speicherplatz: " + parameter + " \n\r"); 
}
//###########################################################################
//Quellen: https://github.com/shirriff/Arduino-IRremote
if (befehl == "ir_rawsend") 
 { valid_command = true; 
   colonPosition = command.indexOf(':');
   if (colonPosition > 2) {valid_command = false;}; //speicherplaetze max 2 stellen erlaubt
   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);// Assume 38 KHz
   client.print("ir_rawsend von Speicherplatz :" + parameter + " \n\r"); 
 }
 
//###########################################################################
// Quellen: http://code.google.com/p/rc-switch/
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(); 
 
 //RCSwitch mySwitch = RCSwitch();
 mySwitch.enableTransmit(param);
 // Optional set pulse length.
 // mySwitch.setPulseLength(320);
 // Optional set protocol (default is 1, will work for most outlets)
 // mySwitch.setProtocol(2);
 // Optional set number of transmission repetitions.
 // mySwitch.setRepeatTransmit(15);
 
 mySwitch.send(param1, param2);
 client.print("rf_send mit Sendecode :" + command + " \n\r"); 
} 
//###########################################################################
//Quellen http://code.google.com/p/rc-switch/ 
if ((befehl == "rf_receive")&& (rf_enable == true)) 
 { valid_command = true; 
 //mySwitch.enableReceive(1); //receiver on interrupt 1 => that is pin D3
 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; }; //kanalnummern max 2 stellen erlaubt
 parameter = command.substring(0,colonPosition);
 command = command.substring((colonPosition+1));
 onewire_pin = parameter.toInt();
//Setup onewire//////////////////////////////////////////////////////////////////////
//long intervall_onewire =10000; //onewire-Operation alle 10sec
//long lastTime_onewire =0;
float tempC[10]; // 10 Onewire-Sensoren werden maximal verwendet
 
OneWire oneWire(onewire_pin); 
DallasTemperature sensors(&oneWire);
DeviceAddress TempSensor[] = //Adress-Array definieren
{ 
 { 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<<
};
 // Start up the library
 sensors.begin();
 // aufloesung 10 bit
 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);
 
//Setup onewire//////////////////////////////////////////////////////////////////////
 while (command.length() > 1 ) 
 { colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; //kanalnummern max 2 stellen erlaubt
 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");
 } 
} 
//###########################################################################
//Quellen: http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino
if (befehl == "1wire") /// Unterprogramm fuer 1wire Abfrage von einzelnen Sensoren
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; //kanalnummern max 2 stellen erlaubt
 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; } //find a device
 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); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( i = 0; i < 9; i++) { data[i] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5    // Calculate temperature value 18S20
 }
 client.print("1wire T" + parameter + " = " + temp_tur + " Celsius / pin D" + param + " as input \n\r");
 }
}
//###########################################################################
//Quellen:http://fluuux.de/2012/09/arduino-adressen-aller-ds1820-ermitteln/
if (befehl == "1wire_address") /// Unterprogramm fuer Auslesen der Sensoradresse
{ while (command.length() > 1 ) 
 { valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; break; }; //kanalnummern max 2 stellen erlaubt
 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;} //0x10 = DS18S20
 else { if (address[0] == 0x28) { client.print("Device is a DS18B20 : "); tmp = 1; } //0x28 = DS18B20
 }
 if (tmp == 1) //display the address, if tmp is ok 
 {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++) //all is ok, display it
 { 
 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;
 }
 }//end if tmp
 }//end while
 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; }; //kanalnummern max 2 stellen erlaubt
 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;}; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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; }; //kanalnummern max 2 stellen erlaubt
 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");
} 
 
//###########################################################################
//Quellen: https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
//library: https://github.com/sparkfun/BMP180_Breakout/tree/master/software/Arduino/libraries/SFE_BMP180
if (befehl == "barometer") 
{ valid_command = true; 
  colonPosition = command.indexOf(':');
  if (colonPosition > 4) {valid_command = false;}; //maximal 4 stellen erlaubt
   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;
      // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.
 
  client.print("Meereshoehe NN : ");
  client.print(parameter);
  client.print(" m\n\r"); 
 
  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:
    delay(status);
 
    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Function returns 1 if successful, 0 if failure.
    status = pressure.getTemperature(T);
    if (status != 0)
    { // Print out the measurement:
      client.print("Temperatur     : ");
      client.print(T,1);
      client.print(" gradC \n\r");  
 
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.
      status = pressure.startPressure(3);
      if (status != 0)
      { // Wait for the measurement to complete:
        delay(status);
 
        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.
 
        status = pressure.getPressure(P,T);
        if (status != 0)
        { // Print out the measurement:
          client.print("Druck absolut  : ");
          client.print(P,2);
          client.print(" mb\n\r"); 
 
          // The pressure sensor returns abolute pressure, which varies with altitude.
          // To remove the effects of altitude, use the sealevel function and your current altitude.
          // This number is commonly used in weather reports.
          // Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.
          // Result: p0 = sea-level compensated pressure in mb
 
          p0 = pressure.sealevel(P,param); //Messung
 
          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");} 
} 
//###########################################################################
//Quelle source code:  http://arduino-info.wikispaces.com/LCD-Blue-I2C#v3
// library hier :https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/LiquidCrystal_V1.2.1.zip
if (befehl == "display") 
{ valid_command = true; 
 colonPosition = command.indexOf(':');
 if (colonPosition > 2) {valid_command = false; }; //spalten max 2 Stellen erlaubt
 if (command.length() < 2) {lcd.clear();} //display loeschen nur mit befehl /?display:
 parameter = command.substring(0,colonPosition);
 param2 = parameter.toInt(); //spalte ist param2
 command = command.substring((colonPosition+1));
 colonPosition = command.indexOf(':');
 if (colonPosition > 1) {valid_command = false; }; //zeilen max 2 Stellen erlaubt
 parameter = command.substring(0,colonPosition);
 param3 = parameter.toInt(); //zeile ist param3
 command = command.substring((colonPosition+1));
 command.replace("%20", " ");//hier http-leerzeichen ersetzen
 //langere strings werden in 20-zeichen-haeppchen zerlegt
 //weil display sonst zeile ueberspringt. fehler in library ??
 int m = 0; //laufvariable
 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(); 
 
//###########################################################################
 // delay(100); // give the web browser time to receive the data
 client.stop(); // close the connection:
 }
//###########################################################################
pinMode(13, OUTPUT); //lED leuchtet während der Abarbeitung der Befehle
digitalWrite(13, LOW);
//hierhin kommen eigenständige Steuerung-_Programme, die dauernd zyklisch durchlaufen werden, 
//wenn aktuell keine http-Anfrage abgearbeitet wird:
//////////////////////////////////////////////////////////////////////// 
// IR empfang 
if (ir_enable == true) 
 {if (irrecv.decode(&results)) // IR-Signal da?
 { dump(&results); 
 ir_decode(); //Dekodieren
 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();
 }
 } 
 }
 }
//###########################################################################
//////////////////////////////////////////////////////////////////////// 
// RF empfang 
if (rf_enable == true) 
 { if (mySwitch.available()) // RF-Signal da?
 { 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(); //Dekodieren
 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();
 }
 }
 }
 }
 } 
//###########################################################################
// hier werden alternativ die analogeingänge als digitaleingänge verwendet, 
// und bei änderung die entsprechenden gespiegelten HM-Systemvariablen "homeduino_ax" 
// in der ccu entweder bei änderung der eingangssignale oder 
// aber immer alle 10min aktualisiert. 
// umschaltung zwischen analog- und digital-modusmit der variablen variablen ana_as_digital 
int i = 0;
int messwert;
String kanal;
String logikpegel;
String befehl;
akt_zeit = now();
 
if (akt_zeit > next_update)
 { next_update = next_update +600; // nächste zwangsaktualisierung in 10min
 while (i < 6) {Ax_alt[i] = !Ax_alt[i]; i=i+1; } // der altzustand wird komplementiert
 i = 0;
 }
 
if (akt_zeit > (last_get+5)) //sicherstellen, dass nicht häufiger als alle 5sec aktualisiert wird
{
 if (client.connect(ccu, 8181)) 
 { while (i < 6) 
 { messwert = analogRead(i); 
 if ((messwert < schaltschwelle_low[i]) && (Ax_alt[i] == 1 )) //bei aenderung des logikpegels, dann aenderungsmitteilung senden 
 { 
 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(); 
 }
}
//###########################################################################
}
//##################### ende Hauptprogramm #############################
 
 
 
 
//#################### Unterprogramme nachfolgend ######################################
 
//########################################################################################
//Unterprogramm zur Befehlserkennung der IR-Signale 
//
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;
 
// bis 254 Codes möglich
 
 default: rf_key = 255;
 }
 rfkey = String(rf_key);
 
} 
 
//########################################################################################
//Unterprogramm zur Befehlserkennung der IR-Signale 
//
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;
 
// bis 254 Codes möglich
 
 default: ir_key = 255;
 }
 irkey = String(ir_key);
 
}
//########################################################################################
//Quelle: Beispielprogramm aus der IRremote library
// Dumps out the decode_results structure. 
// Call this after IRrecv::decode()
// void * to work around compiler issue
void dump(void *v) {
decode_results *results = (decode_results *)v;
//void dump(decode_results *results) {
 
//werte als public variable speichern
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;
 }
 }
 
//##############################################################
// Stores the code for later playback Most of this code is just logging
void storeCode(decode_results *results)
{count = results->rawlen;
 codeLen = results->rawlen - 1;
 if (codeLen > 98) {codeLen =99;} //nur codelaengen bis 98 zulaessig
 // To store raw codes: Drop first value (gap) Convert from ticks to microseconds
 // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
 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");}// Mark
     else {rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS; Serial.print(" s");}// Space
   Serial.print(rawCodes[i - 1], DEC);
 
   //in EEPROM speichern 200bytes je IR-Code_Speicherplatz
   addr = 200*param + 2*(i-1);
   val = rawCodes[i - 1]/256;
   EEPROM.write(addr, val);  //schreibe High-Byte
   EEPROM.write(addr+1, rawCodes[i - 1] - val);  //schreibe Low-Byte
   k= k+1;
   if (k>10) {k=1; Serial.print("\n\r");}
 }
  //jetzt noch codeLen im EEPROM ablegen
   addr = 200*param + 2*99;
   val = codeLen/256;
   EEPROM.write(addr, val);  //schreibe High-Byte
   EEPROM.write(addr+1, codeLen - val);  //schreibe Low-Byte
   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};                      //Schaltschwelle High der Analogeingänge

int schaltschwelle_low[]= {200,0,0,0,0,100};                                                //Schaltschwelle  LOW der Analogeingänge

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; //aus dem Datenblatt des NTC

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[] = //Adress-Array definieren
{ 
 { 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;   // 1 wenn ein ir-receiver an pin D2 verwendet wird

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:

//Unterprogramm zur Befehlserkennung der IR-Signale
//
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;

// bis 254 Codes möglich

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;                 // 1 wenn ein rf-receiver an pin D3 verwendet wird

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:

//Unterprogramm zur Befehlserkennung der IR-Signale
//
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;

// bis 254 Codes möglich

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.

 

 

 

 

 

 

 

 

Homeduino mit I2C-Barometer-Sensor und LCD-Display für die Homematic

Homeduino mit I2C-Barometer-Sensor und LCD-Display für die Homematic

Update 14.11.2014: In der Beschreibung fehlte die Angabe der weiteren Systemvariablen homeduino_fehler  als Logikwert

Zur Einstimmung auf das Thema:

Die Welt des Arduinos bietet viele Möglichkeiten, mit preiswerten Sensoren und Modulen sehr hochwertige Steuer- und Messgeräte darzustellen. Ein besonders für die Hausautomation mit der Homematic geeigneter Ansatz ist der Homeduino. Details hierzu findet man hier:
Auf Basis eines Arduino MEGA mit einem Ethernet Shield W5100 ist ein sehr preisgünstiges Gerät darstellbar, das über Ethernet (Wired) oder auch drahtlos über WLAN direkt von der Homematic-CCU ansteuerbar ist. Die Gestaltung der Homeduino-Software ist so universell, daß eine Verwendung des Gerätes auch mit Raspberry und anderen Computern mittels einfacher Skripte leicht möglich ist!
So kann man I2C-Module mit der Homematic über den Homeduino steuern:
Hier wird beschrieben, wie man relativ einfach ein 4-zeiliges LCD-Display und einen Barometersensor über einen sog I2C-Bus ansteuert. Damit wird in diesem Beispiel ein hochwertiges elektronisches Barometer dargestellt.
Da Komponenten mit I2C-Bus sehr vielfältig im Markt verfügbar sind, eröffnet diese Vorgehensweise auch für ganz andere  Meßaufgaben einen interessanten Lösungsweg.
Was sind die „Zutaten“:
– ein Arduino-MEGA 2650 ( bei ebay in China schon für 12€ zu haben)
-ein Ethernet W5100-Shield ( ebenfalls preiswert für etwa 6€)
– ein Barometersensor BMP180_Modul ( <2€ )
– ein 4×20 LCD-Display mit I2C ( ca. 3,50€ „Serial Interface2004 20X4 Character LCD Modul“ )
– optional: ein IO-Shield (kann zukünftig von mir bezogen werden, bitte PN)
– die Homeduino-Software
Das Kochrezept:
1.)  Man steckt den MEGA und das Ethernet-Shield zusammen, spielt per USB die Homeduino 1.0 oder 2.0 -Software auf und schließt das Ganze am Router an oder stellt die Verbindung über WLAN her. Wie das im Einzelnen geht ist unter dem o.a. Link beschrieben.

2.)  Das Display und den Sensor schließt man über den I2C-Bus an und verbindet die verwendeten Module zusätzlich mit der 5V-Spannungsversorgung. Die folgenden Bilder zeigen die Verschaltung:

Folie14
Folie15
3.)  Systemvariablen in der Homematic anlegen:
barometer_druckNN als Zahl mit Dimension mb
barometer_temp als Zahl mit Dimension °C
barometer_tendenz als Werte: bleibend; fallend; steigend;
barometer_druckNN_alt als Zahl mit Dimension mb
homeduino_fehler als Logikwert

 

4.)  WebUI-Programm mit Skripten für die Datenabfrage und für die Darstellung auf dem Display erstellen. Abtastintervall bei mir : alle 30min
barometer10
Das erste HM-Skript fragt den Barometersensor ab. In diesem Skript ist in der url noch die Höhe des eigenen Standortes einzutragen, Bei mir sind das 229m.
HM-Skript   
var url = "192.168.178.58/?barometer:229:"; !Stand 23.08.14###
!Messung mit dem Barometersensor BMP180##############
!zuerst die Barometer-Abfrage mit system.Exec
string stdout;
string stderr;
system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
string arduino_xml = stdout;
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);
 
!Luftdruck in Systemvariable speichern
integer wort_position = arduino_xml.Find("bei NN");
string daten = arduino_xml.Substr(wort_position+10,8);
real druck = daten.ToFloat();
dom.GetObject("barometer_druckNN").State(druck);
 
!Temperatur in Systemvariable speichern
integer wort_position = arduino_xml.Find("tur     : ");
daten = arduino_xml.Substr(wort_position+9,5);
real temp = daten.ToFloat();
dom.GetObject("barometer_temp").State(temp);
 
!Tendenz berechnen und in Systemvariable speichern
real druck_alt = dom.GetObject("barometer_druckNN_alt").State();
dom.GetObject("barometer_druckNN_alt").State(druck); !umspeichern  neu >> alt
real druck_diff= druck - druck_alt;
integer tendenz = 0;
string ten_denz = "gleichbleibend";
if (druck_diff > 0.1) {tendenz =2 ;ten_denz = "steigend";}
if (druck_diff < -0.1) {tendenz =1 ;ten_denz ="fallend";}
dom.GetObject("barometer_tendenz").State(tendenz);

Das zweite HM-Skript stellt die Messwerte auf dem LCD-Display dar:

HM-Skript   
!LCD-Display , Stand 24.08.14   
var url = "192.168.178.58/?display:"; !##################################
real druck = dom.GetObject("barometer_druckNN").State();
string Druck =druck.ToString();
Druck = Druck.Substr(0,7); !zwei Nachkommastellen
 
real temp = dom.GetObject("barometer_temp").State();
string Temp =temp.ToString();
Temp = Temp.Substr(0,4); !nur eine Nachkommastelle
 
integer tendenz = dom.GetObject("barometer_tendenz").State();
string zeichen = "=";
if (tendenz == 1) {zeichen = "(";}
if (tendenz == 2) {zeichen = ")";}
 
integer druck_position = (druck - 981.0)/2.0;
if (druck_position < 0) {druck_position = 0; }
if (druck_position >19) {druck_position = 19;}
 
string zeile_1 = "Druck N.N. " + Druck +"mb    ";
zeile_1 = zeile_1.Substr(0,20); 
 
string zeile_2 = "____________________";
string zeile_20 = zeile_2.Substr(0,druck_position);
string zeile_21 = zeile_2.Substr(druck_position+1,19 - druck_position);
zeile_2 = zeile_20 + zeichen + zeile_21;
 
string gesamt =  url + "0:0:" + "Homeduino  Barometer" + zeile_1 + zeile_2;
string stdout; string stderr; system.Exec("wget -q -O - '"#gesamt#"'", &stdout, &stderr);
 
string zeile_3 = "Temperatur " + Temp +" grdC    ";
zeile_3 = zeile_3.Substr(0,20); 
string gesamt =  url + "0:3:" + zeile_3;
string stdout; string stderr; system.Exec("wget -q -O - '"#gesamt#"'", &stdout, &stderr);

Als Ergebnis hat man eine regelmässig aktualisierte Systemvariable bzw. den Messwert des Luftdruckes zurückgerechnet auf Normal-Null (N.N.), also Meereshöhe. Der Homeduino liefert zwar auch den absoluten Luftdruck, allerdings hat der nichts mit den Wetterdienst-Daten zu tun und wird deshalb hier nicht verwendet. In der dritten Zeile wird der Luftdruck quasi als Bargraph dargestellt . Je nach Tendenz des Luftdrucks wird ein „>“ oder „<“ oder „=“Zeichen in einer dem Luftdruckwert entsprechenden Zeilenposition angezeigt.

barometer9

 

Unabhängig von dieser Darstellung kann man auch mit einem Browser das Daten-Telegramm vom Homeduino ansehen:
barometer6
Anmerkungen zum Barometersensor BMP180: Der verwendete Sensor BMP180 ist der Nachfolgesensor des BMP085. Der Sensor selbst hat normalerweise eine Versorgungsspannung von 3,3V . Aber auf dem hier verwendeten Modul ist ein Spannungsregler integriert, so dass ein Betrieb mit 5V möglich ist. Also unbedingt auf den folgenden Bildern den Modultyp vergleichen. Ansonsten kauft man die 3V-Version und beschädigt so das Modul sofort bei Inbetriebnahme!
Mehr zu diesem tollen Sensor hier :  http://www.bosch-presse.de/presseforum/details.htm?txtID=5192

barometer1
Diese Bauanleitung wird noch erweitert zu einer kompletten Wetterstation. Bald mehr dazu!

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.

 

 

 

Praxistaugliches, universelles I/O-Shield-Board für Arduino

Praxistaugliches, universelles I/O-Shield-Board für Arduino

Ausgangssituation:

Die Verwendung von den verschiedenen Arduino -Typen auch im Bereich der Hausautomation ist deshalb so attraktiv, weil es preisgünstige Sensoren für die unterschiedlichsten Mess- und Steueraufgaben gibt. Dazu entwickelt eine riesige Gemeinde geeignete Software für fast alle Anwendungsfälle.
Im Hinblick auf den Einsatz im Bereich der Hausautomation gibt es aber einen entscheidenden Nachteil, nämlich dass vielfach die Anschlusstechnik mit hobbyartigen Breadboards etc. erfolgt. Diese sind zwar für die Funktionserprobung auf dem Labortisch ideal, sind aber für eine dauerhafte und zuverlässige Verbindungstechnik äußerst ungeeignet. Zwar gibt es sog. IO-Shields, diese sind aber einfach nur mit vielen Stiftleisten und Schraubklemmen gefüllte Boards, bei denen sich die Frage nach einer robusten und dauerhaft zuverlässigen Verbindungstechnik stellt. Auch sind Schraubklemmen-Boards nicht unbedingt „state of the art“ , weil bekanntermaßen Klemmleisten eine bessere dauerhafte Alternative sind!

Bild0.JPG

Anforderungsprofil:

Die Lösung war für mich deshalb die Eigenentwicklung eines I/O-Shields mit zusätzlichen Komponenten, die den Anschluss von Sensoren und Aktoren erlaubt, wie sie in der Heimautomation typisch sind. Dazu gehören einfache Anschlussmöglichkeiten ohne „fliegende“ externe Zusatzbauteile für 1Wire-Sensoren, NTC-Temperaturfühlern, Schaltern und Reedschaltern, Ultraschallsensoren, analogen Gebern, IR-Signalempfängern, usw. Darüber hinaus sollten natürlich auch alle Arten von Niedervoltrelais bis 24V ohne zusätzliche Treiber anschließbar und Niedervolt -Verbraucher bis etwa 2A direkt steuerbar sein.
Die technischen Daten sind im Einzelnen:
>> Geeignet für Arduino Boards mit Stiftbild wie UNO, MEGA, …

>> Anschluss mit professioneller 40-poliger WAGO-Klemmleiste

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

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

Der Schaltplan:

Das folgende Bild zeigt das relativ einfache Schaltschema für die einzelnen Eingänge und Ausgänge.

Folie2.JPG

Die analoge Eingangsspannung 0 bis +5V wird über einen 33k-Schutzwiderstand auf die analogen Eingänge A0 bis A5 des Arduino geführt. Ein 10nf-Kondensator verbessert die EMV-Eigenschaften und schützt den Eingang vor Schaltspitzen. Falls ein Eingangsspannungsbereich von 0 bis +10V benötigt wird, kann man durch Stecken der Jumper Jy den eingangsseitigen Spannungsteiler aktivieren. Dann hat man den gleichen Eingangswiderstand wie die Analogeingänge der Wired-Homematic-Module. Für die Verwendung von NTC-Thermofühlern kann man über Jumper Jx 10K-Pullup-Widerstände zuschalten. Und für die Verwendung der analogen Ports als digitale I/Os sind die entsprechenden analogen Pins auch noch auf die Klemmleiste geführt.
Die digitalen I/Os werden ebenfalls direkt auf die Klemmleiste geführt. Diese sind mit 4k7-Pullup-Widerstände direkt für den Anschluss von 1Wire-Sensoren geeignet. Der Status jedes digitalen I/Os wird mit LEDs angezeigt, so dass eine einfache optische Funktionskontrolle möglich ist. Für die Ansteuerung von Relais und Hochstromverbrauchern sind für alle 9 I/Os jeweils Hochstrom-Mosfets eingebaut, die auch stromhungrige NV-Relais oder ander NV-Verbraucher direkt steuern können.

Die Platine:

Die Platine ist eine durchkontaktierte doppelseitige Platine . Als MosFets lassen sich sowohl SMD-Typen SOT-23 als auch typische Transistorgehäuse TO-92 verlöten. Grundsätzlich sind auch NPN-Transistoren verwendbar. Für die Musterplatine wurden Mosfets vom Typ IRLML 0030 verwendet, die in China bereits für 6€/100Stück zu bekommen sind und sehr niedrige Einschaltwiderstände (Verluste) haben. Zusätzlich ist auf der Platine noch Platz für spezielle eigene Schaltungen. Dazu sind einige Lochrasterfächen vorgesehen.

Platine2.JPG

Anwendungsmöglichkeiten:

Verwenden kann man die Platine mit fast allen Arduinos, zumindest mit denen, die Stiftleisten wie der UNO oder der MEGA haben. Durch das Zusammenstecken entsteht ein stabiler Platinenverbund, der über die WAGO-Klemmleisten mit der Homematic-Außenwelt einfach verbunden werden kann. Das folgende Bild zeigt das I/O-Shield mit dem MEGA 2650 und dem Ethernet Board W5100

Bild33.JPG

Anmerkung:
Wenn sich genügend Interessenten bei mir melden, dann könnte man ggf. eine grössere Menge Platinen bestellen. Geschätzter Platinenpreis ca. 20€. Ob ggf. auch ein Teile-Bausatz zusammengestellt wird, hängt ebenfalls vom Interesse ab. Geschätzter Teilepreis 20€, da die WAGO-Klemmleisten recht teuer sind!

Ausblick:

Zur Zeit erprobe ich einen Arduino-MEGA mit LAN/WLAN Anbindung und natürlich mit der beschriebenen I/O-Platine. Für den Arduino habe ich ein simples eigenes „Betriebssystem“ entwickelt, das über LAN oder WLAN eine rudimentäre Steuerung mit jedem Browser möglich macht. Natürlich kann man dann auch über entsprechende Skripte von der Homematic oder vom Raspberry diese Steuerungs- und Messfunktionen aktivieren. Das funktioniert bisher schon sehr gut; natürlich nicht nur mit einfachen digitalen und analogen I/Os sondern auch mit komplexen Sensoren wie 1Wire-Temperaturfühlern , Ultraschall-Entfernungsmessern, IR-Sendern und Empfängern und sogar 435Mhz-Sender für die Ansteuerung von Baumarkt-Funksteckdosen funktionieren ganz ordentlich.
Demnächst mehr…

Hier die notwendigen Komponenten für diesen geplanten LAN/WLAN- Homeduino

Folie1.JPG

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.

Translate »