Seite auswählen
WEATHERMAN … die perfekte Wetterstation für die Hausautomation

WEATHERMAN … die perfekte Wetterstation für die Hausautomation

1 Warum eine besondere Wetterstation für die Hausautomation ?

Ursprünglich wollte ich ja gar keine Wetterstation selber bauen, sondern wollte die für die Homematic vorgesehene Wetterstation nehmen oder ggf. andere Wetterstationen anpassen. Aber nach dem Studium der technischen Daten kam doch etwas Enttäuschung auf: Einerseits war der Preis ganz schön hoch und andererseits fehlten den typischen Wetterstationen wesentliche Eigenschaften, die insbesondere für die Hausautomation wichtig sind.

Das geht schon beim Regenmesser los: Verwendet wird meist ein sog. Regenmengenmesser mit einem Trichter und einer Messwippe. Beim Durchlaufen von Wasser gibt diese Einrichtung Impulse ab, die dann ausgewertet werden. Bei Beginn eines Regenschauers kann das aber u.U. einige Minuten dauern, bis die Wippe schaltet. In dieser Zeit ist die Markise schon nass, bevor sie automatisch eingefahren werden kann. Auch ein zu lange geöffnetes Dachfenster kann zu unangenehmen Wasserschäden führen. Fazit: Für die Hausautomation braucht man einen sehr schnell reagierenden Regenmelder („one drop only“), der zur Zeit nur mit besonderen zusätzlichen externen Modulen (>>50€) darstellbar ist.

Gleiches „Elend“ bei der Erkennung, ob Sonne scheint oder nicht. Die meist verwendeten Helligkeitssensoren haben eine viel zu geringe Dynamik, um störsicher sowohl im dunklen Winter als auch im hellen Sommer eindeutig den Sonnenschein zu erkennen. Ein sog. Sonnensensor ist hier viel besser geeignet. Ich habe ihn schon seit Jahren mit großem Erfolg in Betrieb und möchte ihn nicht mehr missen. Deshalb gehört ein Sonnensensor unbedingt in eine Wetterstation für die Hausautomation integriert.

Und natürlich ist es für die Hausautomation wichtig, nicht nur zu wissen, ob die Sonne scheint oder nicht, sondern wo genau die Sonne am Himmel steht. Nur so kann man dann erkennen, ob beispielsweise Fenster besonnt sind, die dann ggf. automatisch abgeschattet werden können. Deshalb ist eine Berechnung der Sonnenposition unverzichtbar.

Wetterstationen, die nicht für die Homematic konzipiert sind, können prinzipiell natürlich auch verwendet werden, aber man hat das Problem, die Daten in die Homematic zu bekommen. Zudem sind üblicherweise kein schneller Regenmelder und auch kein Sonnensensor enthalten. Und für mich besonders störend ist die meistens verwendete  Batterie-Stromversorgung. Das ist schon deshalb negativ, weil man üblicherweise eine leistungshungrige Beheizung für den Regenmelder braucht.  All diese Argumente führten mich schließlich zum Selbstbau meiner eigenen Wetterstation WEATHERMAN.

2  Das kann der WEATHERMAN

Der WEATHERMAN ist die Fortsetzung einer Reihe von Sensor- und Aktor-Modulen ( die WIFFIs), die hauptsächlich zur  Erweiterung  und  Ergänzung der Hausautomation mit der Homematic konzipiert sind. Diese Module sind allesamt Funkmodule , die das in nahezu jedem Haushalt vorhandene gesicherte WLAN-Funknetz verwenden, um mit der Homematic-CCU zu kommunizieren.

Der WEATHERMAN hat eine Vielzahl von Sensoren, mit denen folgende Wettersignale messbar sind:

  • Windgeschwindigkeit mittel in m/s
  • Windgeschwindigkeit spitze in m/s
  • Windstärke in Bft
  • Windrichtung als Text und in Grad
  • Aussentemperatur in °C
  • Aussentemperatur gefühlt in °C
  • Taupunkt-Temperatur in °C
  • rel. Luftfeuchte in %
  • abs. Luftfeuchte in g/m3
  • Luftdruckmessung bez. auf N.N. in mb
  • Luftdruck-Trend zur Erkennung von Wetteränderungen 
  • Regenmelder  (one drop only!) mit einstellberer Empfindlichkeit
  • Regenmengenmesser  mit mm/h und mm/24h
  • Sonnensensor mit einstellbarer Schaltschwelle
  • Helligkeitssensor mit sehr weitem Dynamikbereich
  • Berechnung Sonnenstand Azimut
  • Berechnung Sonnenstand Elevation

Die Datenübertragung erfolgt mit dem hauseigenen WLAN. Die Datenübertragung zur Homematic arbeitet völlig automatisch im Hintergrund, indem die Daten auf entsprechende CCU-Systemvariable abgebildet werden. Für die Verwendung in Verbindung mit ioBbroker oder anderen Hausautomationssystemen kann der WEATHERMAN anstatt zur CCU auch JSON Daten an die entsprechende programmierbare Serveradresse versenden. Und natürlich kann man die Wetterstation auch ganz ohne Hausautomation verwenden: dafür hat der WEATHERMAN sogar seine eigene Webseite, womit die Wetterdaten im Heimnetz mit jedem üblichen Browser einfach dargestellt werden können. So  hat man die aktuellen Wetterdaten jederzeit auch auf dem Tablet oder Smartphone im Blick..

Das Erscheinungsbild könnte man zwar mit einer App graphisch aufpeppen, aber der Aufwand war mir einfach zu groß. Schließlich steht die Funktionalität an erster Stelle und die ist mit der aktuellen Webseite voll erfüllt. Aber vielleich findet sich in der Community ein „App-Experte“, der aus der eine alternative Darstellungsmöglichkeit für Smartphone oder Tablet schafft.

3  Nachbau leicht gemacht

Der erste Prototyp meiner Wetterstation war mechanisch und elektronisch komplett im Eigenbau hergestellt. Als Windmesser kam ein kardanisch aufgehängtes Pendel mit einer Kugel als Windfänger zur anwendung. Aus dem Ausschlag des Pendels konnte man Windstärke und Windrichtung gut berechnen. Allerdings war die Konfiguration einfach zu groß und erheblich zu kompliziert für den Nachbau von mechanisch weniger versierten Homematikern. Deshalb wurde diese Lösung nicht weiter verfolgt.

Eine sehr gute Lösung bot sich mit der preiswerten Verfügbarkeit eines Windmessers an, der als Ersatzteil für eine käufliche Wetterstation hier angeboten wird. Dieses Teil W132 hat einen relativ robusten Windmesser mit einer Windfahne für die Windrichtung. Ebenfalls eingebaut ist ein Temperatur- und Feuchtigkeitssensor mit einer eigenen Elektronik, welche  die Daten normalerweise mittels 433Mhz-Sender an die hier nicht verwendete Basisstation sendet. Im folgenden Bild ist das Modul rechts direkt am Mast befestigt.


Insgesamt besteht der WEATHERMAN aus den im Bild gezeigten Modulen, wobei der Regenmengenmesser und das W132 Ersatzteil fertig gekauft werden. Der WEATHERMAN-Controller kann als Bausatz in meinem Webshop gekauft werden. Die sog. Wetterkappe für den optionalen BME280-Sensor ist im 3D-Druck hergestellt und kann im Webshop bezogen werden. Wer einen 3D-Drucker hat, der kann sich mit diesem stl-File das Teil auch selbst ausdrucken.

In der ausführlichen 25-seitigen Bauanleitung wird genau beschrieben, wie die Wetterstation zusammen gebaut wird. Zum Überblick hier nur die wesentlichen Schritte:

Das W132-Modul wird mit einem Kabel modifiziert, so daß die Daten vom WEATHERMAN-Controller verarbeitet werden können. Normalerweise werden die W132-Messdaten intern an den 433Mhz-Sender geschickt und dort ausgesendet. Der WEATHERMAN hört diese Daten einfach ab und dekodiert diese. Die übliche Versorgung des W132 mittels Batterien entfällt, da  das Teil vom WEATHERMAN mit 3,3V versorgt wird. Die dafür notwendige Modifikation des W132 ist relativ einfach: nur drei(!) Leitungen sind für den Anschluss des W132 notwendig. In der Bauanleitung ist detailliert beschrieben, wie die Modifikation des W132 erfolgt. Das folgende Bild zeigt die geöffnete Box des W132 mit den drei verzinnten Leitungen, über die das Modul von aussen mit 3V-Spannung versorgt und das Datentelegramm „angezapft“ wird.

Der WEATHERMAN-Controller ist in einem robusten wassergeschützten Standard-ABS-Gehäuse untergebracht. Dieses Gehäuse nimmt auch den Regensensor, Sonnensensor, Helligkeitssensor und Barometersensor auf.  Hier ein Eindruck vom Innenleben des Hauptgehäuses mit der Ober- und Unterschale:


Den WEATHERMAN-Controller gibt´s nur als Bausatz. Der Nachbau ist auch für den weniger versierten Elektroniker möglich, denn mit dem angebotenen  Bausatz muß man eigentlich nur die mitgelieferte Platine bestücken und sauber verlöten. Der Mikrocontroller WeMos mini wird  bereits komplett programmiert geliefert, so daß man sich nicht mit der Arduino-Entwicklungsumgebung „auseinander setzen“ muß.  Aber man sollte schon etwas Erfahrung mit dem Zusammenbau und Inbetriebnahme von elektronischen Modulen haben! Mit der detaillierten  kann eigentlich  wenig „schief “ gehen, wenn man sorgfältig alle Schritte ausführt, über etwas Löterfahrung und ein Multimeter verfügt.
Der neu entwickelte Regensor ist ein besonderes „Schmankerl“! Dafür wurde eine von unten beheizte Platine mit vergoldeten (Korrosionsschutz!)  Leiterbahnen konzipiert. Ausgewertet wird sowohl die Widerstands- als auch Kapazitätsänderung, wenn ein Regentropfen auf das Messgitter tropft. Damit ist in gewissen Grenzen nicht nur  eine analoge Intensitätsmessung möglich sondern mit einer individuellen Schwellenvorgabe  auch die Schaltempfindlichkeit des Regenmelders einstellbar. Insgesamt ist die Reaktion des Regenmelders inkl. Übertragung zur CCU im Bereich von 1 bis 5sec !!. Mittig im Regensensor ist eine LED integriert, die das Einschalten des Regenmelders signalisiert. Das folgende Bild zeigt links die Sensorfläche und rechts die Unterseite mit den Kontaktstellen für die Heizwiderstände und die mittige  LED.

Zusätzlich ist noch ein typischer konventioneller Regenmengenmesser angebaut, dessen Zählimpulse vom WEATHERMAN ausgewertet werden. Dieses Gerät ist ein im Internet relativ preiswert verfügbares Modul. Kann man beispielsweise bei Aliexpress mit dem Suchwort „rain gauge“ finden.

Für den Nachbau habe ich hier die Einkaufsliste mit Bezugsquellen zusammengestellt. Die zugehörigen aktuellen Preise zeigen, daß der Selbstbau des WEATHERMAN sehr preiswert ist. Mal abgesehen davon, daß die Funktionalität insbesondere im Hinblick auf die Nutzung mit der Hausautomation überragend ist.

4 Programmierung und Einstellung

Der WEATHERMAN verwendet als Mikrocontroller mit WLAN den WeMos mini mit integrierter USB-Schnittstelle. Der WeMos ist vorprogrammiert, lediglich die für das WLAN notwendigen Zugangsdaten für den heimischen Router müssen eingegeben werden. Dies kann sehr komfortabel erfolgen, indem man den WEATHERMAN zur Einstellung als Hotspot arbeiten läßt.  Auf der eigenen Webseite des WEATHERMAN (IP: 192.168.4.1) kann man dann die notwendigen Daten und Einstellungen mit einem normalen Browser durchführen. Dafür sind keinerlei Programmierkenntnisse notwendig, also alles sehr einfach. Die folgenden Schritte zeigen kochrezeptartig das Vorgehen bei geöffnetem WEATHERMAN-Controller Gehäuse:

1.RESET-Taster seitlich am WeMos mini drücken. Einige Sekunden  warten bis die rote LED auf der Platine alle 1sec blinkt (dabei versucht der WEATHERMAN sich ins WLAN einzuloggen, was natürlich wegen des Fehlens der Zugangsdaten noch nicht geht!).

2. Dann den PROG-Taster (der Taster neben dem WeMos) etwa 2sec drücken bis die rote LED im 0,5sec-Takt blinkt. Jetzt ist der WEATHERMAN im Hotspot-Modus.

3. Mit dem Smartphone oder besser Laptop  nach einem Hotspot mit dem Namen „wiffi“ suchen und die Verbindung herstellen. Da es eine gesicherte Verbindung ist, muß beim ersten Zugang das Kennwort „wiffi1234“ eingegeben werden. Danach müßte, wenn alles richtig funktioniert, eine gesicherte Verbindung zum „wiffi“ vorhanden sein.

4. Auf dem so im WLAN eingeloggten Smartphone oder Tablet mit der Adresszeile des Browsers die Hotspot-Webseite des WEATHERMAN  aufrufen mit: 192.168.4.1/?
Die Antwort müßte so aussehen:

:

5. Jetzt die notwendigen Eingaben in der Adresszeile des Browsers machen. Das macht man mit folgenden Befehlen, die immer mit einem Doppelpunkt abgeschlossen werden:
192.168.4.1/?ssid:my_ssid:  dabei ist „my_ssid“ die SSID des eigenen Routers  (Achtung, die SSID darf keinen Doppelpunkt enthalten!)
192.168.4.1/?pwd:my_pwd:  dabei ist „my_pwd“ das Router-Passwort des eigenen Routers (Achtung, das PWD darf keinen Doppelpunkt enthalten!)
192.168.4.1/?ccu:my_ccu:  und „my_ccu“ ist die feste (!) IP der eigenen CCU1 oder CCU2 Wenn alle drei Daten richtig eingegeben sind und auf der Webseite auch richtig angezeigt werden , dann ist der WEATHERMAN startbereit und kann mit dem Befehl:
192.168.4.1/?reset: oder dem Druck auf den RESET-Taster (am WeMos)  neu gestartet werden. Nach einigen Sekunden blinkt die LED  solange im 2sec Takt bis der WEATHERMAN sich im heimischen WLAN eingeloggt hat. Danach sind nur sehr kurze LED-Lichtblitze vorhanden. Diese signalisieren eine erfolgreiche WLAN-Verbindung.

Jetzt kann die Webseite des WEATHERMAN im Heimnetz aufgerufen werden. Dazu schaut man im Router nach, welche IP der WEATHERMAN bekommen hat und ruft dann einfach diese IP auf, indem man diese IP in die Adresszeile des Browsers eingibt. Oder man schreibt einfach in die Adresszeile: weatherman.local.  Allerdings kann diese letzte Methode u.U. in einigen Heimnetzen nicht erfolgreich sein. Ich persönlich verwende immer die IP, dann hat man eine eindeutige Zuordnung. Deshalb stellt man dann auch sinnvollerweise den Router so ein, daß er dem WEATHERMAN immer diese gleiche IP zuteilt. Die Antwort auf den Browseraufruf ist im folgenden Bild dargestellt.


Das ist eigentlich schon alles. Für besondere individuelle Anforderungen gibt es noch mehr Befehle, die oben im Bild aufgelistet sind. Diese Befehle sind aber nur für besondere Anwendungen und werden weiter unten erklärt.

5. Anlernen an die CCU

Die automatische Verbindung zur CCU wird über Systemvariablen hergestellt, deren Namen von mir vorgegeben sind (in rot). Allerdings lassen sich mit dem name-Befehl beliebige andere Namen für die Systemvariablen  definieren. Im ersten Schritt sollte man diese Vorgabe erst mal behalten! Darunter werden auf der WEATHERMAN-Webseite die Sensorsignale der Wetterstation dargestellt.  Diese Werte werden alle 60sec in einem festen Zeitraster aktualisiert, um das Datenaufkommen für die Signalübertragung zu begrenzen. Erst durch Aktualisierung der Webseite oder Klick auf den Link Aktualisierung der Messwerte kann auch außerhalb des Zeitrasters die Anzeige jederzeit aktualisiert werden.

Das Anlernen des WEATHERMAN an die CCU ist sehr einfach, weil für jedes Sensorsignal nur eine korrespondierende Systemvariable angelegt wird. Entsprechend der Vorgabe (rote Namen) sind folgende Systemvariablen in der CCU anzulegen:

w_ip vom Typ „Zeichenkette“
w_temperature vom Typ „Zahl“ mit Maßeinheit „°C“
w_windchill vom Typ „Zahl“ mit Maßeinheit „°C“
w_taupunkt  vom Typ „Zahl“ mit Maßeinheit „°C“
w_humidity vom Typ „Zahl“ mit Maßeinheit „%“
w_hum_abs vom Typ „Zahl“ mit Maßeinheit „g/m3″
w_wind_avg vom Typ  Zahl mit Maßeinheit m/s
w_wind_peak vom Typ  Zahl mit Maßeinheit m/s
w_windstaerke vom Typ  Zahl mit Maßeinheit bft
w_wind_direction vom Typ „Zeichenkette“
w_wind_dir vom Typ  Zahl mit Maßeinheit °
w_rain_activity vom Typ „Zahl“
w_rain_status vom Typ „Logikwert“
w_rain_intensity vom Typ „Zahl“ mit Maßeinheit mm/h
w_rain_volume_1 vom Typ „Zahl“ mit Maßeinheit mm/1h
w_rain_volume_24 vom Typ „Zahl“ mit Maßeinheit mm/24h
w_barometer vom Typ „Zahl“ mit Maßeinheit mb
w_barotrend vom Typ „Zeichenkette“
w_sun_temp vom Typ „Zahl“ mit Maßeinheit „°C“
w_diff_temp vom Typ „Zahl“ mit Maßeinheit „°C“
w_sonne_scheint vom Typ „Logikwert“
w_lux vom Typ „Zahl“ mit Maßeinheit „lux“
w_elevation vom Typ  Zahl mit Maßeinheit °
w_azimut vom Typ  Zahl mit Maßeinheit °

Es müssen nur diejenigen Systemvariablen definiert werden, die man auch benutzen möchte!

Die Aktualisierung aller genannten  Systemvariablen erfolgt automatisch, aber nur wenn sich die Messwerte ändern. Dadurch wird vorteilhafterweise der Datenfluss stark reduziert.

Anmerkung:
Die oben genannten Systemvariablen sind „normale“ CCU-Systemvariablen, deren Zahl nicht wie bei den HM-Skriptvariablen auf  200 begrenzt ist !

14. Befehlsliste des WEATHERMAN

Auf der Help1-Seite sind Befehle dargestellt, mit denen bestimmte Eigenschaften des WEATHERMAN bei Bedarf geändert werden können. Normalerweise ist dies aber nicht notwendig. Nur bei speziellen Bedürfnissen wie Änderung der Namen für die CCU-Systemvariablen oder Löschung der Router Zugangsdaten etc. sollte man diese Befehle anwenden.

15. Einstellungen im Expertenmodus

Das Gleiche gilt für den sog. Expertenmodus. Normalerweise ist  keine Einstellung notwendig!!!!! Einstellungen sollten auch nur dann vorgenommen werden, wenn man wirklich weiß, was man verändert. Im ungünstigen Fall kann der WEATHERMAN irreparabel beschädigt werden. Hier ist diese Einstellungsseite:

16. Rückstellen in Werkszustand

Manchmal kann es notwendig sein, die im EEPROM abgelegten Daten zu löschen und den WEATHERMAN in den Auslieferungszustand zu versetzen. Hierfür wird durch 1sec-Drücken des PROG-Tasters zuerst der Hotspot-Modus eingestellt, was durch 1sec- Blinken der roten LED angezeigt wird. Danach hält man den PROG-Taster  solange gedrückt, bis die rote LED dauerhaft leuchtet. Jetzt werden die EEPROM-Daten gelöscht. Läßt man die PROG-Taste wieder los, dann startet WIFFI neu und geht automatisch in den Hotspot-Modus, um so wieder neu an den Router angelernt zu werden. Achtung: nie den PROG- und RESET-Taster gleichzeitig drücken, da das Modul dann in den Programmiermodus geht und u.U. die Firmware beschädigt wird.

17. Update des WEATHERMAN

Ein Update des WEATHERMAN kann ohne Demontage bzw. Geräteöffnung komplett über das WLAN erfolgen. Dabei ist der WEATHERMAN vorher im Heimnetz über WLAN eingeloggt und seine Webseite ist mit der vom Router vergebenen IP-Adresse aufrufbar.

Aktuelles Update Zip-Archiv von der Webseite stall.biz runterladen und den *.bin File entpacken und auf dem PC speichern. Achtung nicht das Zip-Archiv zum Update verwenden, das beschädigt u.U. den WEATHERMAN.

Die Update-Seite des WEATHERMAN aufrufen (siehe nächstes Bild). Dort werden zwei Alternativen eines Updates angeboten: das Komplett-Update nur wenn das beim Update-File ausdrücklich angemerkt ist und das normalerweise verwendete Teil-Update.

Das Teil-Update über den Link Teil-Update auslösen und mindestens 15sec warten und erst dann den Link Update-Explorer betätigen.

Nach kurzer Zeit öffnet sich der Browser mit der Möglichkeit per „Durchsuchen“ den neuen update *.bin File einzugeben und dann mit dem Update-Button den Vorgang zu starten:


Nach einigen Sekunden wird ein erfolgreiches Update bestätigt und der WEATHERMAN neu mit der upgedateten Firmware gestartet:

.

und hier sind die neuesten Updates zum runterladen:

Zum Update das ZIP-Archiv runterladen und entpacken. Zum Update nur die *.bin-Datei aus dem zip-Archiv verwenden.

Update 28.08.2017: weatherman_8   Kleine Fehler behoben, alternativ Wetterstation Froggit  WH5300 verwendbar, Betauungsschutz-Heizung  für den Regenmelder implementiert.

Update 01.09.2017: weatherman_9   Verschiedene Fehler behoben, Windchill-Berechnung korrigiert

Update 04.09.2017: weatherman_11  Temperatur- und Feuchte-Berechnung korrigiert, Barometerwert auch korrigierbar

Update 11.09.2017: weatherman_12  schnellere Datenaktualisierung des Regenmelders in der CCU

Update 15.09.2017: weatherman_14  Regenmelder mit zeitlicher Schalthysterese

Update 27.09.2017: weatherman_19  Tauvermeidung auf dem Regensensor durch verbesserte Heizstrategie, PWD- und SSID-Eingabe  ohne Abschluss-Doppelpunkt, zusätzliche I2C-Anschlussmöglichkeit für IR-Temperatursensor MLX90614

Update 03.10.2017: weatherman_24  variable Mittelwertbildung des Windrichtungssignals mit neuem param[17] möglich

… und wo kann man den Bausatz bekommen?

Für den Nachbauer  habe ich Bausätze zusammengestellt. Diese  können bei mir bezogen werden:  WEATHERMAN-Controller Bausatz Wer vorher einen Blick in die Bauanleitung werfen möchte, bitteschön: Bauanleitung

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.

Wiffi-wz mit Präsenzmelder für Deckenmontage

Wiffi-wz mit Präsenzmelder für Deckenmontage

Ausgangssituation

Mittlerweile nutzen viele Homematic-User den Wiffi-wz als ideale Möglichkeit, einen Wohnraum wie beispielsweise das Wohnzimmer mit verschiedenen Sensoren zu erfassen, so daß mit diesen Signalen verschiedene Automatisierungsaufgaben gelöst werden können. Ausführliche Informationen zum Wiffi-wz findet man hier: Der WIFFI-WZ 2.0 … der Wohnzimmersensor

Normalerweise ist der Wiffi-wz in einem kubusartigen Gehäuse eingebaut und kann an geeigneter Stelle im Raum positioniert werden. Dabei ist wichtig, daß insbesondere die beiden Bewegungsmelder „freie Sicht“ im Wohnraum haben, damit auch zuverlässig eine Personenpräsenz im Raum erkannt wird.

Mittlerweile kamen von Usern verschiedene konstruktive Vorschläge für zukünftige Erweiterungen oder Veränderungen, die zwar nicht alle aber doch teilweise integriert werden konnten. Eine besondere Herausforderung war der Wunsch nach einem kompakten Rundgehäuse, das ähnlich wie ein Rauchmelder oder Präsenzmelder an der Decke beispielsweise an die Brennstelle einer Deckenlampe angebracht werden kann.

Lösungsansatz

Wenn der Wiffi-wz an der Decke montiert wird, dann reicht ein Bewegungsmelder aus, um damit eine breite Anwesenheitserfassung im Raum zu machen. Den freien Eingang für den bisher verwendeten zweiten Bewegungsmelder kann man dann umfunktionieren beispielsweise als Relaisausgang zum automatisierten Schalten einer Lampe, die vielleicht vorher an der verwendeten Deckenbrennstelle montiert war.  Natürlich kann man damit auch andere Verbraucher direkt von der CCU oder über die Webseite des Wiffi-wz schalten.

Die 5V-Spannungsversorgung des Wiffi-wz erfolgt normalerweise mit einem Stecker-Netzteil. Das kann man auch bei der Deckenmontage so beibehalten, wenn man die 5V-Versorgungsleitungen auch an die deckenseitige Montagestelle des Wiffi verlegt. Alternativ kann man auch ein geeignetes Netzteil mit zusätzlichem Relais mit dem Wiffi-wz in ein entsprechend größeres Gehäuse einbauen. Dabei ist aber unbedingt sicher zu stellen, daß eine Überhitzung des Gehäuses und/oder  Netzteils ausgeschlossen ist. Dementsprechend muß ein kleines Schaltnetzteil mit sehr gutem Wirkungsgrad verwendet werden und mit einer geeigneten elektrischen Absicherung muß eine Brandgefahr ausgeschlossen werden. Gerade weil hier mit 230V Netzspannung gearbeitet wird, sind ausreichenden Fachkenntnisse bei der Realisierung unverzichtbar. Dieser Bauvorschlag erhebt keinen Anspruch auf Fehlerfreiheit oder Konformität mit geltenden technischen Regeln. Deshalb hier auch nochmal der wichtige Hinweis auf meine Sicherheitshinweise.

Das folgende Bild zeigt den Schaltplan der von mir verwendeten Konfiguration. Das 5V-Schaltnetzteil ist ein kleines Modul , welches über eine für das Netzteil geeignete Schmelzsicherung an das 230V-Netz angeschlossen wird. Bei mir ist die Schmelzsicherung mit 100mA träge ausgelegt, aber das muß man individuell auf das verwendete Netzteilmodul abstimmen. Die 5V-Ausgangsspannung wird an die entsprechende Stromversorgungsbuchse des Wiffi-wz angeschlossen.

Anstelle des rechten Bewegungsmelders wird ein Transistor als Open-Collector Treiber für ein Schaltrelais angeschlossen. Ich habe ein 5V-Schaltrelais verwendet und entsprechend dem Schaltbild verschaltet. Das sind schon alle elektrischen Änderungen!

Rundgehäuse als 3D-Ausdruck

Die Konzeption des Gehäuses für die Deckenmontage war nicht ganz einfach, weil einerseits das Gehäuse möglichst klein sein sollte und andererseits aber eine Reihe von funktionalen Anforderungen integriert werden mußten. Am wichtigsten ist die Kühlung bzw. die Gestaltung eines geeigneten Luftführung durch das Gehäuse, weil eine Erwärmung des Gehäuses durch den beheizten Luftgütesensor unvermeidbar ist. Gleichzeitig darf diese Erwärmung aber nicht zu einer Fehlmessung des integrierten Temperatursensors führen. Zusätzlich muß der integrierte Helligkeitssensor auch ein geeignetes „Fenster“ haben, damit er die Helligkeit im Raum detektieren kann.

Das Ergebnis  ist ein zweiteiliges Rundgehäuse, bei dem eine Fassung bzw. Rosette mit einer Zentralschraube an die Decke montiert wird. Das größere Hauptgehäuse wird einfach in der Art eines  Bajonettverschlusses aufgesteckt. Die folgenden Bilder erklären dazu mehr als viele Worte.

Im Bild links die Deckenrosette mit der Zentralschraube zur Deckenmontage. Zusätzlich sind Klemmstege zur Aufnahme und Befestigung des Netzteil-Moduls und des Schaltrelais vorhanden. Rechts ist das Hauptgehäuse mit den Lüftungsschlitzen und darunter der Bohrung für die Aufnahme des Bewegungs/Präsenzmelders. Neben den Lüftungsschlitzen ist ein Lagerbock zur Verschraubung des Helligkeitssensors und des Temperatursensors. Die größeren Bohrungen links und rechts dienen zur möglichen Durchführung eines Netzkabels, falls eine Hängelampe o.ä. angeschlossen wird. Die dreieckförmigen Auflager sind für die Befestigung der Hauptplatine.

In zusammengebautem Zustand kann das Hauptgehäuse in verschieden Höhen mit der Deckenrosette zusammen verschraubt sein.

Der Ausdruck der beiden Gehäuseteile erfolgt mit einem 3D-Drucker. Ich habe weißes PLA-Material verwendet, aber das kann man natürlich auf die persönlichen Wünsche abstimmen.

Für den Ausdruck des Gehäuses auf dem eigenen 3D-Drucker gibt’s hier die aktuellen stl-Files: wiffi_lamp.zip

Einbau des Wiffi-wz

Die Sensormodule BH1750 (Helligkeitssensor) und BME280 (Temperatur, Feuchte und Luftdruck) sind normalerweise in die entsprechenden Fassunge auf der Wiffi-wz Platine eingesteckt. Da aber u.a. wegen der Thermik im Gehäuse diese Sensoren möglichst nah an die Lüftungsschlitze montiert werden sollten, sind entsprechende Leitungsverlängerungen einzulöten. Das folgende Bild zeigt die Details:

Für den linken Bewegungsmelder ist die dreipolige Steckfassung jetzt auf der Unterseite der Platine angelötet, so daß der Bewegungsmelder nun von unten eingesteckt werden kann. Der OC-Transistor ist am Anschluss des zweiten (nicht verwendeten rechten) Bewegungsmelders angelötet. Die Rosette enthält das Netzteil, das Relais und die Schmelzsicherung im Schraubgehäuse. Die 4-polige Lüsterklemme sind die Anschlüsse für 230V und für die optionale geschaltete Lampe.

Im eingebauten Zusatnd sieht das Ganze so aus:

Der beheizte und dementsprechend warme Luftgütesensor MQ135 ist etwas nach innen zu drücken, damit er keinen Kontakt mit dem Gehäuse hat und so den Gehäuse-Kunststoff möglichst wenig erwämt.

Software-Anpassung

In der aktuellen Software ab Version wiffi_wz_71 sind die notwendigen Änderungen schon integriert. Um anstelle des rechten Bewegungsmelders einen digitalen Ausgang zur Ansteuerung des Transistors zu initialisieren ist lediglich im Expertenmodus der param[34] von 0 auf 1 zu setzen. Damit ergibt sich auf der Webseite des Wiffi-wz dann eine veränderte Messwertanzeige, in der nur ein Bewegungsmelder jetzt als Präsenzmelder vorhanden ist und zusätzlich noch ein Relaisausgang verfügbar ist. Das sieht dann so aus:

Das Schaltrelais kann man genauso wie den Beeper entweder auf der Webseite des Wiffi-wz auslösen oder aber direkt von der CCU aus mit einem entsprechenden HM-Skript. Die zugehörigen Browserbefehle sind: 192.168.178.35/?relais:on:   oder 192.168.178.35/?relais:off:

Von der CCU aus kann man das Relais mit einem kleinen HM-Skript mit Senden der o.a. Browserbefehle auch schalten.

HM-Skript   
!Schaltrelais einschalten(on) bzw. ausgeschalten(off)
string befehl = "/?relais:on:";  
!string befehl = "/?relais:off:";
string IP = dom.GetObject("wz_ip").Value();  !Holt IP_adresse des WIFFI_wz
var send_data = "http://" + IP  + befehl; !Befehl zusammensetzen
 
WriteLine(send_data);
string stdout; string stderr;           !und Befehl ausgeben
system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);

Natürlich kann man das Skript statt mit dem system.Exec Befehl auch mit analogen CuxD-Befehlen starten; das hat den Vorteil einer stabileren Arbeitsweise. Mehr dazu im Homematic-Forum.

Mit einem einfachen WebUI-Programm läßt sich mit diesem HM-skript  beispielsweise ein Bewegungsschalter realisieren, der bei Bewegung im Raum eine Lampe mit dem Relais einschaltet:

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.

DualBeam … die HM-Antenne für besonders schwierige Funkbedingungen

DualBeam … die HM-Antenne für besonders schwierige Funkbedingungen

Warum die Antenne so wichtig ist !

Man kann nicht oft genug wiederholen, daß bei Funksystemen die Antenne die wichtigste Komponente ist. Leider wird gerade diesem Teil von  Entwicklern manchmal wenig Beachtung geschenkt. Das führt dann zu suboptimalen Lösungen, die aber auch entsprechendes Verbesserungspotential haben. Die CCU1,die CCU2 und alle käuflichen HM-Komponenten haben eine eingebaute Antenne, die nur aus einem oft in das Gehäuse eingeklemmten Stückchen Lambda-Viertel-Draht besteht. Wenn man gute Funkbedingungen im Haus hat, dann reicht diese Lösung. Aber oft hat man eben nicht gute Funkbedingungen und die Betondecken zum Keller und zum Obergeschoss schirmen die Funkwellen gewaltig ab. Dann entstehen die vom Homematiker so geliebten „Fehlermeldungen“, welche oftmals ein unstabiles Verhalten der CCU zur Folge haben. Für eine zuverlässige Hausautomation ist eine störsichere Funkkommunikation deshalb unverzichtbar.

Zu diesem Thema habe ich bereits einige Artikel im Homematic-Forum und hier auf meiner Webseite veröffentlicht. Dabei wird gezeigt, daß mit einer externen Antenne die Stabilität des heimischen Funknetzes deutlich verbessert werden kann. Hier für den Interessierten noch weitere Informationen dazu:  

Externe Antenne für Raspberrymatic  und hier: Externe Stabantenne für CCU und andere HM-Komponenten  und hier Externe Flachantenne  und hier: Groundplane-Antenne für Homematic

Zum Thema Mehrfach-Antennen gibt’s hier noch Informationen: 2 Antennen gleichzeitig an der CCU

Mittlerweile sind viele meiner externen Antennen im Einsatz mit durchweg sehr positiver Rückmeldung im Hinblick auf weniger Fehlermeldungen. Dabei ist immer zu beachten, daß die normalerweise bei Antennen angegebenen sog. Antennengewinne für die Anwendung im Haus eine nur untergeordnete Bedeutung haben. Im Haus breiten sich die Funkwellen mehr oder weniger chaotisch aus, weil Wände, Möbel und Betondecken den „Konzertsaal“ für die Funkwellen unkalkulierbar bestimmen. Eines ist aber in jedem Fall wichtig, daß die Antenne möglichst flexibel räumlich platzierbar sein sollte, um den optimalen Sendeplatz üblicherweise nach dem try&error -Verfahren  zu ermitteln.

Warum eine zweite Antenne ?

Für die meisten Anwender reichen die in meinem Webshop verfügbaren Stab- und Flachantennen völlig aus, um die Hausautomation stabil zu bekommen. Aber unter sehr schwierigen Ausbreitungsbedingungen kann es immer noch Empfangsprobleme geben. Ursache sind meist dicke stahlbewehrte Betondecken, die eine Ausbreitung der Funkwellen über mehrere Stockwerke stark dämpfen. Repeater können zwar eine Lösung sein, jedoch verbrauchen sie dauernd Strom, kosten Geld und müssen entsprechend administriert werden. Eine zweite Antenne kann hier eine gute und einfache Lösung sein, weil man u.U. die beiden Antennen räumlich getrennt in zwei verschiedenen Stockwerken platzieren kann. Die zwischenliegende Betondecke ist dann nicht mehr das Problem.

Dazu müssen aber die zwei Antennen in geeigneter Weise an die CCU gekoppelt werden. Eine einfache Parallelschaltung funktioniert nicht, weil die Parallelschaltung von zwei 50 Ohm Antennen einen Wellenwiderstand von 25 Ohm ergibt und das würde an dem 50 Ohm Antennenausgang der CCU zu einer erheblichen Fehlanpassung und damit Leistungseinbuße führen. Der Lösungsansatz ist einfach und sehr kostengünstig. Mit einem Stück 75 Ohm-Sat-Kabel kann man leicht einen sog. Viertelwellen-Transformator aufbauen, der den Wellenwiderstand der parallel geschalteten zwei Antennen (25 Ohm) auf wieder 50 Ohm hochtransformiert. Das folgende Bild zeigt die Schaltung dazu:

Damit die zwei Sat-Kabel-Leitungsstücke für die praktische Realisierung nicht zu kurz sind, wurde statt 1/4 Lambda eine Länge von 3/4 Lambda gewählt. Damit ergibt sich als Länge ein Wert von 21,2cm, was für den Aufbau einfacher und praktikabel ist. Die beiden Antennen können nun an exponierter Stelle in jeder Hausetage positioniert werden, so daß auf diese Weise auch sehr schwierige Ausbreitungsbedingungen eigentlich kein Problem mehr sein dürften.

Messergebnisse

Natürlich entsteht  immer die Hauptfrage: Was bringt eigentlich die neue Antenne gegenüber der eingebauten Antenne bzw. den bisher hier gezeigten Antenn wie der Stabantenne und der Flachantenne? Allgemein kann man die Frage nur in einem idealen Versuchsumfeld (Freifeld) messen und beantworten. Aber „ideal“ nützt dem Einzelnen gar nichts , weil man die Frage  nur in bezug auf sein individuelles  HM-Umfeld  beantworten kann. Deshalb sollte man vor dem Umbau die Sende- Empfangs-Feldstärken der einzelnen HM-Module messen und dann nach dem Umbau die Messung zum Vergleich wiederholen. Als Meßwerkzeug kann man  dafür auf der CCU die Systemerweiterung „devconfig“ installieren. Damit kann man die Sende- und Empfangsfeldstärken der einzelnen Funkmodule abfragen. Mehr dazu im Homematic-Forum: Stichworte rssi und devconfig.http://homematic-forum.de/forum/viewtopic.php?f=31&t=26624&p=233643&hilit=rssi+devconfig#p233643

Wichtig ist bei der Messung mit „devconfig“ , daß man vorher die entsprechenden HM-Module betätigt oder abgefragt hat, damit die ermittelten  Werte auch  mit der neuen Antenne gemessen wurden. Und auch wichtig, daß möglichst der Mittelwert von mehreren HM-Modulen vorher und nachher verglichen wird. Einzelne Messungen bringen wenig, weil die Signale im Haus stark streuen.

Im Vergleich zur eingebauten Antenne (lambda/4 Draht ) ist mit der Stabantenne im Mittel über 3dB Gewinn erzielt worden. Die Flachantenne (nicht in diesem Vergleich ) ist etwa vergleichbar. Mit dem Dualbeam ist noch ein weiterer deutlicher Gewinn zu erzielen, aber dafür ist der Aufwand auch größer. Schließlich muß man selbst abschätzen, welche Antenne für den Eigenbedarf die richtige ist .

Nachbau der DualBeam-Antenne

Um den Nachbau einfach zu machen wurde im Webshop ein Bausatz mit einer ausführlichen Bauanleitung zusammengestellt. Damit sollte es auch dem weniger erfahrenen Löter möglich sein, dieses Antennensystem nachzubauen.

Dazu einige bildliche Impressionen: Hier ist der Bausatz. Optional können noch ein oder zwei 3m-Anschlusskabel für die räumlich getrennte Platzierung der Stabantennen bestellt werden.

Im mitgelieferten Kleinverteiler-Gehäuse haben für die Kabel des Powersplitters ausreichend Platz:

Am Gehause kann man entweder direkt zwei Stabantennen anschrauben oder wahlweise eine Stabantenne mit einem oder zwei optionalen 3m-Verbindungskabel räumlich getrennt platzieren

.

Haftungs- und Sicherheitshinweise

Nur HM-Module mit Spannungsversorgung aus Batterie oder galvanisch getrennten externen Netzteilen umrüsten. Keinesfalls HM-Module mit internem/integriertem Netzteil  oder 230V Netzspannung modifizieren, da über den  Antennenstecker gefährliche Berührungsspannungen entstehen können.

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.

Tipps für die Fehlersuche

Normalerweise ist der Anschluss der Antenne völlig problemlos und in wenigen Minuten erledigt. Wenn dennoch Probleme bleiben, dann können die nachfolgend aufgelisteten Lösungsvorschläge möglicherweise helfen:

  • Die Kabelpeitsche mit der SMA-Buchse muß an die entsprechenden Lötpunkte am Sendemodul angelötet werden. Beim Abisolieren kann durch zu heftiges Ziehen am Innenleiter der Innenstift der SMA-Buchse zurückgezogen werden. Deshalb beim Abisolieren den Innenleiter immer festhalten!
  • Nach dem Anlöten mit einem Ohmmeter prüfen, ob die Verbindung zwischen dem Innenstift der SMA-Buchse und dem Innenleiter-Lötpunkt am HM-Sendemodul vorhanden ist.
  • Mit dem Ohmmeter prüfen, ob der Aussenleiter (Abschirmung)  zwischen dem Gehäuse der SMA-Buchse und dem Abschirmungsanschluss am HM-Sendemodul auch  gute Verbindung hat
  • Mit dem Ohmmeter prüfen,  daß Innenleiter und Aussenleiter keinen Kurzschluss haben.
  • Bei Feldstärkemessungen mit devconfig ist zu berücksichtigen, daß die Zahlen negativ sind. Je kleiner die negativen Zahlen sind, umso besser! Weiterhin sind die angezeigten Werte vom letzten Datenverkehr und der kann u.U. sehr alt sein! Deshalb die für die Messung verwendeten Aktoren unbedingt manuell oder per Programm vor der Messung betätigen.
  • Feldstärkemessungen müssen mit mehreren Aktoren erfolgen und ein Mittelwert gebildet werden, weil die „chaotischen“ Wellenausbreitungen und Interferenzen im Haus an manchen Stellen zu Feldstärkeverberbesserungen aber auch zu Felstärkeminderungen führen können.
  • Der richtige Standort der Antenne ist von zentraler Bedeutung für gute Funkverbindungen im Haus. Leider kann kein Rezept dafür gegeben werden, weil im Haus eben durch Betondecken, Wände und aluminisierte Dampfsperren etc. eine völlig „chaotische“ Wellenausbreitung erfolgt. Antennen mit hoher Richtwirkung bzw. Gewinn sind deshalb im Haus völlig kontraproduktiv! Also Probieren und mit Verstand und Glück den richtigen Sendestandort finden.

Viel Erfolg beim Nachbau !

WIFFI-voice … Hausautomation mit Ansage

WIFFI-voice … Hausautomation mit Ansage

Firmware-Update 19.03.2017: Anpassung an neue CCU2-Firmware 

1  Wofür den WIFFI-voice ?

Die Reihe der verschiedenen WIFFIs wird mit dem WIFFI-voice folgerichtig ergänzt. Während der WIFFI-wz mit seiner Sensorik hauptsächlich für die Hauptwohnräume wie das Wohnzimmer gedacht ist, kann man den WIFFI-voice für nahezu alle anderen Räume verwenden. Dabei läßt sich der WIFFI-voice sehr gut in Verbindung mit der Homematic verwenden, aber da auch andere Datenformate wie JSON unterstützt werden, steht der Verwendung mit anderen Systemen der Hausautomation nichts entgegen. Ja sogar ganz ohne ein bestimmtes Hausautomationssystem läßt sich der WIFFI-voice verwenden, da er komplett über seine eigene Webseite fernbedienbar ist. So ist die Investition offen auch für zukünftige neue Systeme der Hausautomation.

2  Die technischen Daten

Bei der Konzeption des WIFFI-voice wurde besonderes Augenmerk darauf gelegt, daß die Kombination der Sensoren und Aktoren möglichst gut auf die Anforderungen für eine Raumüberwachung abgedeckt ist.  Dabei sollte alles in einem Gerät integriert sein, so daß „fliegende“ Gerätschaften möglichst vermieden werden. Auch ist die Verwendung kleiner Netzteile anstelle von Batterien ein wesentlicher Teil des Konzepts, weil ein regelmäßiger Batteriewechsel nicht nur nervig sondern auch teuer ist. Und schließlich wird als drahtlose Kommunikation das fast in jedem Haushalt verfügbare WLAN verwendet, welches auch nicht die 1%-Sendebegrenzung der 868Mhz-Geräte hat. Hier nun die technischen Daten:

  • einfache Einbindung ins  WLAN mit Hotspot-Funktion für Router-Dateneingabe
  • empfindlicher  Geräuschmelder mit Erkennung des Geräuschpegels sowohl als Mittelwert und Spitzenwert der letzten  3 Minuten
  • zwei Infrarot-Bewegungsmelder 90° versetzt, um einen Raum auf Bewegungen abzutasten
  • Temperaturmessung mit Temperatursensor mit DHT22 (im Lieferumfang enthalten) oder alternativ mit dem BME280 oder SHT21 ( nicht im Lieferumfang)
  • Messung der relativen Luftfeuchte mit DHT22 (im Lieferumfang enthalten) oder alternativ mit dem BME280 oder SHT21 ( nicht im Lieferumfang)
  • Berechnung der absoluten Luftfeuchtigkeit (g/m3) und der Taupunkt-Temperatur für Lüftungssteuerungen  und Schimmelwarnungen
  • zwei Eingabetaster für die Auslösung  von beliebigen Ereignissen bzw. Schalten von Aktoren über die  CCU
  • MP3-Sprachausgabe von selbst programmierbaren Ansagetexten und Geräuschsignalen von micro-SD-Karte (bis 32GB)
  • 3W-Stereo-Verstärker integriert
  • integrierter Mini-Lautsprecher
  • optionales formschönes Kubus-Gehäuse als  3D-Druck, passend für die einfache Montage von Platine und Lautsprecher
  • LED-Anzeigen für Bewegungs- und Geräuschmelder
  • Programmierung der Zugangsdaten für das häusliche WLAN einfach mit Smartphone oder Notebook
  • updatefähig über WLAN
  • alternativ zum DHT22  verwendbar: I2C-Schnittstelle für Anschluss spez. Sensoren
    wie SHT21(Temperatur & Feuchte),  BME280 (Luftdruck & Temperatur & Feuchte), BH1750 (Helligkeit)
  • optional verwendbar: USB-Schnittstelle des verwendeten WeMos mini für eigene Anpassungen mit der Arduino Entwicklungsumgebung

Die folgenden Bilder geben einen Eindruck vom „Innenleben“ des WIFFI-voice: voice_funktion Damit der WIFFI-wz auch im Zimmer eine gute Figur macht und an geeigneten Stellen optisch ansprechend platziert werden kann, wurde für optional Verwendung ein kubisches Gehäuse entwickelt. Dieses nimmt die Platine mit allen Sensoren auf und ist im 3D-Druckverfahren hergestellt. Es muß nicht nachbearbeitet werden, da bereits alle Bohrungen und Ausschnitte enthalten sind. voice_blume voice_hand Das verwendete Kunststoffmaterial ist PLA-Filament. Deshalb ist kein Betrieb im Aussenbereich mit direkter UV-Bestrahlung  möglich. Das Gehäuse ist formstabil bis ca. 60°C, was für den sinnvollen Betrieb des WIFFI-voice mit eingebautem Temperatursensor normalerweise ausreichend sein sollte. Die Oberfläche ist nicht völlig glatt sondern hat aufgrund des Herstellverfahrens eine schichtweise Struktur wie man in den beigefügten Bildern erkennen kann. Das Gehäuse hat auf der Unterseite eine gebogene eingeklipste Platte für den Mini-Lautsprecher. Seitlich sind noch ausreichende Schlitze, damit die Eigenerwärmung der Platine  mit den seitlichen  Lüftungsschlitzen abgeführt wird. Der Temperatursensor ist ganz unten montiert, damit Fehlmessungen durch thermische Effekte im Gehäuse möglichst gering sind. voice_speaker Wer Lust auf „Modding“ hat der das Gehäuse noch weiter „veredeln“ . Dazu sind die Gehäuseflächen möglichst glatt zu schleifen und ein sog. Dickschichtfüller aufzutragen (aus dem Autozubehörhandel). Dann kann man abschließend mit Acryllack die Deckschicht in der gewünschten Farbe aufbringen. Das Gehäuse ist als 3D-Ausdruck in meinem Webshop als Option für den WIFFI-voice verfügbar. Wer einen eigenen 3D-Drucker hat, der kann auch das Gehäuse selber ausdrucken. Hier die 3D-Datenfiles dazu:   WIFFI-voice Gehaeuse 3D-Files Übrigens… unter Windows 10 kann man sich das Gehäuse mit dem standardmäßig verfügbaren Programm  3D Builder ansehen und ggf. editieren bzw. anpassen.

3 Bauanleitung und Nachbau

Den WIFFI-voice gibt´s nur als Bausatz. Der Nachbau ist auch für den weniger versierten Elektroniker möglich, denn mit dem angebotenen  Komplettbausatz muß man eigentlich nur die mitgelieferte Platine bestücken und sauber verlöten. Der Mikrocontroller WeMos mini wird  bereits komplett programmiert geliefert, so daß man sich nicht mit der Arduino-Entwicklungsumgebung „auseinander setzen“ muß.  Wer das aber doch möchte, der kann das tun, denn der Source-Code ist hier veröffentlicht und mit der Arduino-IDE und der USB-Schnittstelle am WeMos lassen sich sogar  eigene Programme in den WIFFI-voice laden.   Aber man muß schon etwas Erfahrung mit dem Zusammenbau und Inbetriebnahme von elektronischen Modulen haben! Mit der detaillierten Bauanleitung kann eigentlich  wenig „schief “ gehen, wenn man sorgfältig alle Schritte ausführt, über etwas Löterfahrung und ein Multimeter verfügt.

4 Programmierung und Einstellung

Der WIFFI-voice verwendet als Mikrocontroller mit WLAN den WeMos mini mit integrierter USB-Schnittstelle. Der WeMos ist vorprogrammiert , lediglich die für das WLAN notwendigen Zugangsdaten für den heimischen Router müssen eingegeben werden. Dies kann sehr komfortabel erfolgen, indem man den WIFFI-voice als Hotspot arbeiten läßt.  Auf der eigenen Webseite des WIFFI-voice kann man dann die notwendigen Daten und Einstellungen mit einem normalen Browser durchführen. Dafür sind keinerlei Programmierkenntnisse notwendig, also alles sehr einfach und durch die Sprachausgabe des WIFFI-voice unterstützt :)) Die folgenden Schritte zeigen kochrezeptartig das Vorgehen: 1. Stromversorgung einstecken oder RESET-Taster am WeMos mini drücken. Etwa 20sec warten bis die rote LED  alle 2sec blinkt (dabei versucht der WIFFI sich ins WLAN einzuloggen, was natürlich wegen des Fehlens der Zugangsdaten noch nicht geht). Parallel informiert der WIFFI-voice den User über den Stand des  Einloggvorgangs mit entsprechenden Ansagen. 2. Dann den PROG-Taster (der Taster neben dem WeMos) etwa 2sec drücken bis die rote LED im 1sec-Takt blinkt.  Jetzt ist der WIFFI-voice im Hotspot-Modus. 3. Mit dem Smartphone oder besser Laptop  nach einem Hotspot mit dem Namen „wiffi“ suchen und die Verbindung herstellen. Da es eine gesicherte Verbindung ist, muß beim ersten Zugang das Kennwort „wiffi1234“ eingegeben werden. Danach müßte , wenn alles richtig funktioniert, eine gesicherte Verbindung zum „wiffi“ vorhanden sein. 4. Auf dem so im WLAN eingeloggten Smartphone oder Tablet in die Adresszeile des Browsers die Webseite des WIFFI-voice  aufrufen mit: 192.168.4.1/? Die Antwort sieht dann so aus: 5. Jetzt die notwendigen Eingaben in der Adresszeile des Browsers machen. Das macht man mit folgenden Befehlen, die immer mit einem Doppelpunkt abgeschlossen werden: – 192.168.4.1/?ssid:my_ssid:  dabei ist „my_ssid“ die SSID des eigenen Routers  (Achtung, die SSID darf keinen Doppelpunkt enthalten!) – 192.168.4.1/?pwd:my_pwd:  dabei ist „my_pwd“ das Router-Passwort des eigenen Routers (Achtung, das PWD darf keinen Doppelpunkt enthalten!) – 192.168.4.1/?ccu:my_ccu:  und „my_ccu“ ist die feste (!) IP der eigenen CCU1 oder CCU2 Wenn alle drei Daten richtig eingegeben sind und auf der Webseite auch richtig angezeigt werden , dann ist der WIFFI-voice startbereit und kann mit dem Befehl: – 192.168.4.1/?reset: oder dem Druck auf den RESET-Taster (am WeMos)  neu gestartet werden. Nach etwa 15 bis 30 sec blinkt die LED  solange im 2sec Takt bis der WIFFI sich im heimischen WLAN eingeloggt hat. Danach, im normalen Betrieb,  blinkt die rote LED immer dann, wenn der rechte Bewegungsmelder auslöst. Beim linken Bewegungsmelder schaltet analog die grüne LED. Jetzt kann die Webseite des WIFFI-voice im Heimnetz aufgerufen werden. Dazu schaut man im Router nach, welche IP der WIFFI bekommen hat und ruft dann einfach diese IP auf, indem man diese IP in die Adresszeile des Browsers eingibt. Oder man schreibt einfach in die Adresszeile: wiffi_voice.local.  Allerdings kann diese letzte Methode u.U. in einigen  Heimnetzen nicht erfolgreich sein. Ich persönlich verwende immer die IP, dann hat man eine eindeutige Zuordnung. Deshalb stellt man dann auch sinnvollerweise den Router so ein, daß er dem WIFFI-voice immer diese gleiche IP zuteilt. Die Antwort auf den Browseraufruf ist im folgenden Bild dargestellt. Das ist eigentlich schon alles.  Für besondere individuelle Anforderungen gibt es noch mehr Befehle, die oben im Bild aufgelistet sind. Diese Befehle sind aber nur für besondere Anwendungen und werden weiter unten erklärt. Die automatische Verbindung zur CCU wird über Systemvariablen hergestellt, deren Namen von mir vorgegeben sind (in rot). Allerdings lassen sich mit dem name-Befehl beliebige andere Namen für die Systemvariablen  definieren. Im ersten Schritt sollte man beim ersten WIFFI im Heimnetz diese Vorgabe erst mal behalten! Der WIFFI teilt über eine Systemvariable der CCU auch seine eigene Adresse mit. So ist der WIFFI ganz einfach auch über die CCU steuerbar. Darunter werden auf der WIFFI-Webseite die Sensorsignale des WIFFI-voice dargestellt.  Diese Werte werden nicht automatisch in einem festen Zeitraster aktualisiert, um das Datenaufkommen für die Signalübertragung zu begrenzen. Erst durch Aktualisierung der Webseite oder Klick auf den Link Aktualisierung der Messwerte wird die Anzeige auch aktualisiert. Vielleicht erklärt  sich ein User bereit, eine APP zur Abfrage des WIFFI-voice zu schreiben. Dann wird das Ganze noch „schöner“. Die Webseite des WIFFI-voice dient  hauptsächlich zum komfortablen Einstellen und Anschauen der Daten. Die Kommunikation mit der CCU läuft im Hintergrund völlig automatisch ab!

5 Anlernen an die CCU

Das Anlernen des WIFFI-voice an die CCU ist sehr einfach, weil für jedes Sensorsignal nur eine korrespondierende Systemvariable angelegt wird. Entsprechend der Vorgabe (rote Namen) sind folgende Systemvariablen in der CCU anzulegen: v_ip vom Typ „Zeichenkette“ v_noise_avg vom Typ „Zahl“ mit Maßeinheit „%“ v_noise_peak vom Typ „Zahl“ mit Maßeinheit „%“ v_Tast_links vom Typ „Logikwert“ v_Tast_rechts vom Typ „Logikwert“ v_motion_left vom Typ „Logikwert“ v_motion_right vom Typ „Logikwert“ v_temp vom Typ „Zahl“ mit Maßeinheit „°C“ v_hum vom Typ „Zahl“ mit Maßeinheit „%“ Die Aktualisierung aller genannten  Systemvariablen erfolgt automatisch, aber nur wenn sich die Messwerte ändern. Dadurch wird vorteilhafterweise der Datenfluss stark reduziert. Will man andere Namen für die Systemvariablen verwenden, kann man diese mit dem name-Befehl ändern (siehe weiter unten). Im ersten Schritt würde ich aber erst mal alles so  lassen, weil sonst nur unnötige Fehler entstehen. Spätestens aber mit dem zweiten WIFFI-voice im Heimnetz muß dies getan werden, um eine eindeutige Zuordnung zu behalten.

6 Anzeige der LEDs

Die blaue LED zeigt mit der Leuchtintensität die Stärke des Geräusches an.  Damit die LED nicht hektisch flackert, wenn dynamische Geräusche vorhanden sind, wird dieses Signal stark „geglättet“. Die rote LED zeigt verschiedene Betriebszustände und Meldungen an. Wenn der WIFFI-voice nach dem Reset versucht sich in das WLAN einzuloggen, dann leuchtet diese LED im 2sec Takt. Wenn das Einloggen erfolgreich war, dann zeigt alle 2sec  ein regelmäßiger „Herzschlag“  den ordnungsgemäßen Betrieb an:

> Ein ganz schwacher kaum sichtbarer einfacher Blitz signalisiert, daß weder WLAN- noch CCU-Verbindung da sind. > Ein etwas längerer einfacher Blitz signalisiert eine bestehende Verbindung mit dem WLAN > Ein Doppelblitz signalisiert die Verbindung mit WLAN und CCU

Aber dabei ist zu beachten, daß diese Blitzsignale von dem Status des rechten (aus Sicht des Versorgungssteckers)   Bewegungsmelders überschrieben wird, d.h. wenn dieser  Bewegungsmelder „anschlägt“, dann leuchtet die rote LED entsprechend dem Ausgangssignal des Bewegungsmelders. Die grüne LED zeigt nur den Status des linken (aus Sicht des Versorgungssteckers)  Bewegungsmelders an. Für die CCU werden die Signale der Bewegungsmelder standardmäßig auf 1min verlängert und bei jeder weiteren Bewegung nachgetriggert. Diese Zeit kann mit dem param(0) (Expertenmodus) beliebig eingestellt werden.

7 Verwendung des Geräuschsensors

Die Mikrofonsignale werden verstärkt und eine Art Effektivwert mit einem Operationsverstärker ermittelt. Entsprechend dem Schallpegel schwankt dieser Wert zwischen 0 und etwa 3V. Dieses Signal wird dem analogen Eingang des Mikrocontroller zugeführt und von diesem ausgewertet. Wenn man dieses u.U. stark schwankende Schallpegelsignal der CCU zuführen würde, dann entstünde sehr viel Datentraffic, den die CCU u.U. nicht verarbeiten kann. Deshalb sind aktuell zwei Algorithmen zur Vorbearbeitung des Schallsignals im WIFFI-voice integriert: Mit einer Mittelwertbildung über die letzten 60sec wird ein Geräuschwert abgeleitet und als Wert zwischen 0 und 100 auf die CCU-Systemvariable  v_noise_avg übertragen. Damit lassen sich dann Schaltvorgänge oder Aktivitäten auslösen , die beispielsweise die Anwesenheit von mehreren Menschen im Raum signalisieren. Beispielsweise kann eine Lüftung eingeschaltet werden oder ein eingeschaltetes Fernsehen signalisiert werden oder, oder… Mit einer Spitzenwertmessung wird der Spitzenwert des Geräuschpegels in den letzten 60sec erfasst und als Wert zwischen 0 und 100 zur  entsprechenden CCU-Systemvariablen  v_noise_peak übertragen. Dieser Wert ist dafür geeignet, besonders schnell auf Geräuschanstieg  im Raum zu reagieren. Auslösen kann man damit beispielsweise eine Treppenhausbeleuchtung oder einfach die Anwesenheit im Raum schnell signalisieren.

8 Ausgabe von MP3_ansagen

Eine besondere  Eigenschaft des WIFFI-voice ist die flexible Ausgabe von Sprach- oder  Tonsignalen. Nicht nur eigene Meldungen können mit dem integrierten Lautsprecher ausgegeben werden, sondern beim Start des WIFFI-voice oder beim Einloggen ins WLAN werden wichtige Statusansagen gemacht, die den Nutzer so über des Zustand des Gerätes akustisch informieren. Die entsprechenden Ton- und Sprach-„Schnipsel“ können  als mp3-Files auf einer Micro-SD-Karte gespeichert werden. Für das MP3-Modul ist eine mit FAT32 zu formatierte MicroSD  (bis zu 32GB)  mit den gewünschten Ansagefiles zu programmieren. Dazu sind  die Ansage- und Geräuschfiles  im MP3 Format herunter zu laden und damit die SD-Karte zu programmieren. Wichtig ist, daß die mp3-files nicht direkt im Root-Verzeichnis der Micro-SD sondern in einem Unterverzeichnis mit dem Namen mp3 gespeichert sind. Natürlich kann man eigene Ansagefiles hinzufügen, man sollte nur darauf achten, daß die jedem Filenamen vorangestellte Nummer von 0001 bis 0255 nur einmal vorkommt. Auch sind bereits einige Files für den WIFFI-voice reserviert, so daß man sinnvollerweise immer neue Files hinzufügt. Bei bis zu 255 möglichen Files reichen die Möglichkeiten hierfür sicher aus. Hier sind die MP3-Files zum Download Mit jedem üblichen Browser kann man nun die Tonausgabe eines beliebigen abgespeicherten MP3-Files auslösen. Dazu muß man aber die dem WIFFI-voice im Router vergebene IP-Adresse wissen. Bei mir hat der WIFFI-voice  eine feste IP-Adresse 192.168.178.87 im Router zugewiesen bekommen. Dementsprechend ist der „sound“-Ausgabe-Befehl in der Adresszeile des  Browsers: 192.168.178.87/?sound: 31:1:   „1“ ist die Nummer des MP3-Files und die vorangestellte „31“ ist die Lautstärke (zwischen 0 =  leise und 31 = laut) Zur Ausgabe von Listen oder zusammengesetzten Sätzen werden einfach bis zu 27 weitere Dateinummern angehängt. Beispiel: 192.168.178.87/?sound: 31:1:2:15:18:255: Mit einer so aufgebauten Kommandozeile läßt sich der WIFFI-voice auch von der CCU mit einem entsprechenden HM-Skript steuern. Da in der CCU automatisch die aktuelle IP des WIFFI-voice in der Systemvariablen wz_ip abgelegt ist, kann man auch bei dynamischer IP-Adressenvergabe die Tonausgabe von gespeicherten mp3-Files  mit folgendem  HM-Skriptes auslösen. Zum Beispiel so: sound_skript und das zugehörige HM-Skript ist:  

HM-Skript   
!hiermit wird beim WIFFI-voice der mp3-file 0101 mit Lautstaerke 31 ausgegeben 
string befehl = "/?sound:31:101:";   !hier erfolgt deine individuelle Anpassung 
string IP = dom.GetObject("v_ip").Value();  !in der CCU muss die systemvariable v_ip vorhanden sein
var send_data = "http://" + IP  + befehl; 
!WriteLine(send_data);
string stdout; string stderr;           
system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);
Natürlich kann man das Skript statt mit dem system.Exec Befehl auch mit analogen CuxD-Befehlen starten; das hat den Vorteil einer stabileren Arbeitsweise. Mehr dazu im Homematic-Forum.

9 Verwendung der Bewegungsmelder

Die IR-Bewegungsmelder werden in die dreipoligen Fassungen auf der Platine eingesteckt. Vorher sind beide Einstelltrimmer in der Aufsicht erst mal ganz nach links bis zum Anschlag zu drehen. Der Jumper kann wie im Bild gesteckt werden, dann löst er aus und schaltet erst mal ab, bevor er wieder neu triggerbar ist. In der anderen Jumperposition ist der Bewegungsmelder re-triggerbar, d.h. er bleibt kontinuierlich eingeschaltet, wenn Bewegung vorliegt. Ich bevorzuge diese Position!  Mehr dazu im Datenblatt SR501 Das Potentiometer für die Einschaltdauer (im Bild unten das rechte Poti) bleibt immer auf kürzeste Zeit eingestellt, da der WIFFI-voice die Zeit automatisch auf einen auf der Expertenseite  (param 0 ) einstellbaren Wert (standardmässig  60sec) verlängert. Mit dem  linken Poti kann durch Verdrehung nach rechts die Empfindlichkeit gesteigert werden. Die Empfindlichkeit sollte aber möglichst  weit nach links gedreht sein, weil eine zu hohe Empfindlichkeit, abhängig von Toleranzen des IR-Moduls und möglichen Störeinstrahlungen des  WLAN-Moduls, manchmal zu Fehlauslösungen führen kann. Insgesamt ist die optimale Einstellung der oft sehr unruhigen IR-Bewegungsmeldern immer eine sensible und zeitaufwendige Sache, weil nach jeder Veränderung der Potentiometer die Module einige Zeit brauchen, um sich zu „beruhigen“. Ich kenne leider keine IR-Bewegungsmelder, bei denen das nicht so ähnlich ist ! In der Bauanleitung ist beschrieben, wie man die Bewegungsmelder durch einen zusätzlichen Kondensator „beruhigen“ kann. Diese Lösung ist absolut empfehlenswert, da die Melder auch leicht durch elektromagnetische Einstrahlungen ungewollt auslösen.

10 Verwendung der Tasterschalter

Im WIFFI-voice sind zwei Taster-Eingänge integriert, die sich sehr flexibel einsetzen lassen. Die Drucktaster sind im optionalen Gehäuse an der Kubus-Oberseite einfach zu bedienen. Mit entsprechenden WebUI-Programmen auf der CCU lassen sich dann alle möglichen Schaltaufgaben auf Knopfdruck erledigen, beispielsweise Raumlicht an/aus oder Fernsehen an/aus oder, oder …

11 Messung Temperatur und Feuchte

Die Messung der Raumtemperatur und der Luftfeuchte erfolgt standardmässig mit einem DHT22-Sensormodul. Die Messwerte sind dann automatisch in der CCU verfügbar mit den entsprechenden Systemvariablen v_temp und v_hum. Steuern und regeln kann man damit beispielsweise die Heizung im Raum oder die Belüftung aktivieren.

12 Schaltuhr

Die integrierte Schaltuhr ist ein nettes „Gimmick“, um unabhängig von der CCU beliebige  akustische Meldungen über das MP3-Modul auszugeben. Dazu sind mit dem alarm-Befehl auf der Webseite der WIFFI-voice die „Weckzeiten“ mit der zugehörigen MP3-Tonausgabe zu programmieren. Mehr dazu auf der Help1-Webseite des WIFFI.

13 Experteneinstellungen und Informationen

Mit folgenden Befehlen kann der WIFFI-voice  auf seiner Einstell-Webseite mit der über den Browser eingestellt oder bedient werden. Die aktuell verfügbaren Befehle lassen sich auf der Help1-Seite abrufen:

Expertenmodus

Normalerweise ist im Expertenmodus keine Einstellung notwendig!!!!! Einstellungen sollten auch nur dann vorgenommen werden, wenn man wirklich weiß, was man verändert. Im ungünstigen Fall kann der WIFFI-voice beschädigt werden und muß ggf. neu programmiert werden.

14 Datenausgabe im JSON-Format

Ein optionaler Abruf der aktuellen Sensordaten des WIFFI-voice im JSON-Format ist mit dem json-Befehl einfach möglich. Entweder man gibt im Browser den Befehl ein oder man schickt von einem Homeserver den json-Befel an den WIFFI-voice. Die zurückgeschickte Antwort ist dann etwa so :

15 Update des WIFFI-voice

1. Voraussetzung:  Ein Update des WIFFI kann ohne Demontage bzw. Geräteöffnung komplett über das WLAN erfolgen. Dabei ist der WIFFI vorher im Heimnetz über WLAN eingeloggt und seine Webseite ist mit der vom Router vergebenen IP-Adresse aufrufbar. Diese individuelle IP-Adresse wird nachfolgend als bezeichnet. Man kann die Webseite des des Wiffi-voice alternativ auch mit wiffi_voice.local aufrufen. 2. Im Browser folgenden Befehl eingeben: (immer genauestens die Schreibweise beachten !!) /?update: es geht auch wiffi_voice.local/?update: Warten bis der Browser eine Fehlermeldung zeigt oder frühestens nach ca. 20 bis 30sec). 3.Erst jetzt im Browser den Update-Assistenten mit /update aufrufen. (Achtung die jetzt andere Schreibweise ohne Fragezeichen beachten !!!!) 4. Danach zeigt der Browser ein einfaches Bild mit zwei Buttons. update Mit „Durchsuchen“ den aktuellen Update-File (extension .bin) aus dem ZIP-Update-Archiv auswählen und danach mit Druck auf den Update-Button hochladen. (nicht den ZIP-File hochladen, sonst muß das Modul eingeschickt werden !) Nach einigen Sekunden kommt ein formloses „ok“, was ein erfolgreiches Update bestätigt. Danach sind alle Daten gelöscht ( auch die WLAN-Zugangsdaten!). Der WIFFI-voice  ist auf den upgedateten Auslieferungszustand zurück gesetzt und wird nun automatisch im Hotspot-Modus mit der festen IP 192.168.4.1 neu gestartet. Dabei blinkt die LED im Hotspot-Modus sehr schnell. ( 2Hz) 5. Mit einem Smartphone oder besser Windows-Laptop kann nun eine gesicherte WLAN-Verbindung mit diesem Hotspot hergestellt werden. Der Hotspot hat den Namen wiffi und das Zugangspasswort ist wiffi1234 Hinweis: – Bei Apple-Produkten kann es beim Einloggen wegen der strikten Sicherheitseinstellungen zu Problemen kommen. Möglichst Windows-Rechner verwenden! Manchmal kann es notwendig sein, alte WIFFI-Zugänge vorher zu löschen! 6. Wenn die Verbindung hergestellt ist, kann mit Browsereingabe der Hotspot-IP 192.168.4.1 die Webseite des WIFFI-voice aufgerufen werden. Auf dieser Webseite erfolgt dann wie bei der Erstinbetriebnahme die Eingabe der Router- und CCU-Zugangsdaten (WLAN- Netzwerkname, Netzwerkschlüssel/ Passwort, CCU IP-Adresse) mit den Befehlen … 192.168.4.1/?ssid:DeinNetzwerkname: 192.168.4.1/?pwd:DeinPasswort: 192.168.4.1/?ccu:DeineCCU_IP 7.Mit der Browsereingabe 192.168.4.1/?reset: startet abschließend der WIFFI neu. Nach etwa 20sec kann im Browser mit : /? oder wiffi_voice.local die Webseite des WIFFI im Heimnetz zur Eingabe weiterer Einstellungen wieder aufgerufen werden. Hinweis: Ab der Firmwareversion wiffi_voice_27  ist das Update deutlich einfacher über die eigene Update-Webseite des WIFFI durchzuführen !

… und hier sind die neuesten Updates zum runterladen:

Zum Update das ZIP-Archiv runterladen und entpacken. Zum Update nur die *.bin-Datei verwenden.

26.10.2016: wiffi_voice_12

01.12.2016: wiffi_voice_18  Update: mp3-Ausgabe von Listen oder zusammengesetzten Sätzen,

11.12.2016: wiffi_voice_24  Sonderzeichen in Router-Zugangsdaten erlaubt, SHT21  alternativ zum DHT22 verwendbar

09.01.2017: wiffi_voice_27  Taupunktberechnung und Absolutfeuchte hinzugefügt, DHT22 Abfrage verbessert

17.01.2017: wiffi_voice_30  Update über eigene Webseite, JSON-Telegramm überarbeitet

19.03.2017: wiffi_voice_36  Anpassung der 8181-Requests an CCU2-Firmware 2.27.7

28.03.2017: wiffi_voice_37  JSON Format angepasst

16 Update der Firmware über USB

Ein Update über USB ist etwas komplizierter als über WLAN. Aber wenn beispielsweise ein neues Ersatz-WeMos-Modul verwendet werden soll, dann ist  ein Update über USB die einzige Lösung. Hier die Anleitung dafür:

  1. Aktuelle Firmware runterladen, entpacken und bin-File wegspeichern
  2. Zuerst für den WeMos den notwendigen USB-Treiber installieren: windows 32&64bit
  3. USB-Kabelverbindung PC <>  WIFFI herstellen und im Gerätemanager unter Anschlüsse (COM & LPT) nachschauen, welcher COM-Port aktiv ist
  4. Xtcom Util runterladen, entpacken und starten
  5. Fenster Tools(T) / Config Device öffnen, die aktive COM-Nummer und die Baudrate 115200 eingeben und dann Open.
  6. Danach Connect  und dann am WIFFI den Prog-Taster gedrückt halten und währenddessen am WeMos kurz den Reset-Taster drücken. Wenn erfolgreich, dann kommt Meldung Connect with target OK
  7. Fenster API Test(A) /Flash Image Download öffnen und beim Image Path den Pfad des abgespeicherten bin-Files eingeben.
  8. Dann mit dem  Download Button den Download starten. Erfolgreicher Abschluss mit Operation Succeeded!
  9. Danach startet der WIFFI. Wenn LED  im sec-Takt blinkt, dann Prog-Taster solange drücken bis Dauerleuchten.
  10. Danach startet der WIFFI neu , warten bis die LED im 0,5sec-Takt blinkt, was den Hotspot-Modus signalisisiert
  11. Im Hotspot-Modus können jetzt auf IP 192.168.4.1 wie oben beschrieben die eigenen Zugangsdaten eingegeben werden.

… und wer unbedingt selbst die Software verändern oder anpassen möchte

Die Arduino Entwicklungsumgebung für den WeMos installieren. So geht’s: HowTo install Arduino IDE Hier sind die zusätzlichen voice-libraries:  diese libraries in den library Ordner laden Hier ist der Quellcode zur privaten Nutzung:  Quellcode wiffi_voice_38

… wo gibt´s den Bausatz ?

Einen kompletten Bausatz des WIFFI-voice  kann man in meinem Webshop erwerben:  Bausatz WIFFI-voice  und hier ist die  Bauanleitung  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.

WIFFI-pump-2… die intelligente Steuerung der Zirkulationspumpe mit Heizungsüberwachung

WIFFI-pump-2… die intelligente Steuerung der Zirkulationspumpe mit Heizungsüberwachung

Firmware-Update 08.09.2017:  JSON Telegramm korrigiert

Die Vorgeschichte

Ich verwende meine  intelligente Steuerung für die  Trinkwasser-Zirkulationspumpe schon seit Jahren. Dafür habe ich eine Lösung mit einem Mikrocontroller Attiny entwickelt , die sehr gut als preiswerte standalone-Lösung funktioniert. Mit einem zusätzlichen Aktor mit allerdings zusätzlichen Kosten ist die Steuerung auch in die Homematic-Hausautomation integrierbar. Diese Lösung wird als Bausatz in meinem Webshop angeboten, weil sie kostengünstig und einfach ist. Zirkulationspumpensteuerung Attiny

Das neue  WIFFI_pump-2  Konzept eröffnet aber viel mehr Möglichkeiten, die über die Funktionalität der „alten“ Zirkulationspumpen-Steuerung weit hinausgehen. Mit dem WIFFI-pump-2 wird wie bisher die intelligente Steuerung der WW-Zirkulationspumpe erreicht aber mit der jetzt verfügbaren WLAN-Anbindung ist ein Datenaustausch sowohl mit der Homematic als auch mit anderen Servern  einfach möglich. Darüberhinaus  lassen sich beim WIFFI-pump-2  zwei 1wire-Temperatursensoren anschließen , um beispielsweise  die Vor- und Rücklauftemperatur zu messen und an die Homematic zu übertragen. Zusätzlich ist sogar im Hutschienengehäuse ein lichtstarkes OLED-Minidisplay optional verfügbar. So kann man zusätzlich auch die Funktion der Heizung überwachen und mit diesen Informationen mit der Homematic  geeignete Aktionen auslösen. Der WIFFI-pump-2 löst das Vorläufermodell  WIFFI-pump ab.

Grundsätzliche Aspekte

Eine Warmwasser-Zirkulation ist ein in der Hausinstallation heute oft eingesetztes Komfortmerkmal, um an allen Zapfstellen im Haus nahezu sofort nach Aufdrehen des Wasserhahnes warmes Wasser verfügbar zu haben. Dazu verwendet man eine Ringleitung, in der eine kleine sog. Zirkulationspumpe  das warme Wasser dauernd oder nur zu bestimmmten Tagesabschnitten im Kreis pumpt. Im Hinblick auf Energieeinsparung kommt schnell der Gedanke auf, durch „intelligentere“ Steuerung das System zu verbessern.

Der erste Gedanke ist meist die Verringerung des Verbrauchs von elektrischer Leistung durch die Zirkulationspumpe. In einem typischen Einfamilienhaus hat die heute meist nur 5W. Das heißt im Dauerbetrieb verbraucht diese Pumpe übers Jahr ganze 44KWh, also mit 25ct/KWH macht das etwa 11€. Allerdings wird  meist eine Schaltuhr  verwendet, die vielleicht 12h schaltet und demnach die Verbrauchskosten auf 6€/Jahr halbiert. Für 6€/Jahr lohnt sich wohl keine  „intelligentere“ Steuerung als eine einfache Schaltuhr!

Also warum denn hier was machen??
Der Grund liegt darin, dass die eigentlichen Verluste nicht elektrisch sind, sondern die erheblichen Wärmverluste der Ringleitung. Dazu habe ich Messungen gemacht, die hier auf der Webseite nachgelesen werden können:

zirkulationspumpe-warmebedarfsgerecht-geschaltet

Das Ergebnis kann man mit wenigen Kennzahlen trendmässig beschreiben:

– Elektrische Verluste  der Zirkulationspumpe:  5W   >> Jahreskosten 11€
– Wärmeverluste  der Ringleitung ohne Schwerkraftzirkulation:  60W   >>  Jahreskosten 132€    (mit einem Absperrhahn im Rücklauf wurde die natürliche Zirkulation abgeschaltet )
– Wärmeverluste der Ringleitung mit Schwerkraftzirkulation: 128W   >>  Jahreskosten 282€ !!
– Wärmeverluste der Ringleitung mit 12h/Tag laufender Zirkulationspumpe : 562W   >>  Jahreskosten 616€ !!!

Ohne jetzt das nur als „Hausnummer“  zu wertende Ergebnis weiter im Einzelnen zu diskutieren, wird eines klar:

Eine intelligente Steuerung der Zirkulationspumpe ist nicht wegen der elektrischen Energieeinsparung sinnvoll, sondern hauptsächlich wegen der damit möglichen Reduzierung der Verlustwärme !!

Das intelligentes Steuerungskonzept

Optimal ist danach, daß die Zirkulationspumpe auch nur dann läuft, wenn auch irgendwo im Haus warmes Wasser möglichst ohne Wärmeverzug gezapft werden soll. Dazu gehört erst mal eine Strategie, um den Nutzerwunsch nach warmem Wasser zu erkennen. Denkbar wäre  ein Bewegungssensor im Badezimmer oder ein  Geräuschmelder in den „Wasserräumen“. Aber oftmals geht man in diese Räume, ohne den Warmwasserhahn zu betätigen . Also doch vielleicht einen Taster in Wasserhahnnähe installieren, den man anstößt, wenn warmes Wasser benötigt wird ? Das widerspricht aber einer „intelligenten“ automatischen Bedienung!
Also vielleicht einen Sensor installieren, der den Durchfluss mißt? Zu teuer und das erfordert   einen geeigneten Sensor und einen Eingriff in die Installation… Nein, lieber nicht!

Die Lösung ist einfach und auch nicht neu: Am Vorlauf-Ausgang des Warmwasserspeichers wird einfach mit einem Temperatursensor die Temperatur gemessen. Wenn dann warmes Wasser gezapft wird, dann erhöht sich schlagartig dort die Temperatur. Diese Temperaturerhöhung wertet man mit einer Elektronik entsprechend aus und schaltet umgehend die Zirkulationspumpe ein. Diese schiebt nun das warme Wasser schnellstens in die Ringleitung, so dass bereits nach relativ kurzer Zeit  das warme Wasser an der Zapfstelle ist.  Und spätestens jetzt wird klar, daß hierfür eine Pumpe mit möglichst hoher Leistung viel besser geeignet wäre, als die heute mit Schaltuhr eingesetzten Kleinleistungs-Typen.

Abgeschaltet wird die Pumpe entweder nach 3 bis 4 Minuten ( wenn die Ringleitung gut und komplett durchspült ist) oder wenn im Rücklauf am Warmwasserspeicher die Temperatur angestiegen ist. Dazu würde allerdings noch ein zweiter Temperatursensor benötigt.

Nach mehreren Versuchen mit und ohne zweiten Temperatursensor im Rücklauf wurde die einfache Lösung mit nur einem Temperatursensor im Vorlauf praktisch umgesetzt. Die Vorteile mit einem zweiten Sensor wären nur sehr gering!

Die erste Steuerung war analog mit wenigen Bauelementen umgesetzt (siehe Link oben) und hat ein Jahr problemlos gelaufen. Allerdings hatten einige Nachbauer mit Bauteiltoleranzen der analogen Steuerung zu kämpfen, so daß der Wunsch nach einer robusteren digitalen Lösung aufkam, die zudem optional in meine Homematic-Haussteuerung gut integriert werden kann. Damit meine ich, daß die Homematic sowohl die Zirkulationspumpe einschalten kann, als auch bei selbsttätiger Einschaltung die Homematic über den Schaltzustand rückinformiert wird. (bidirektionale Einbindung).

Vielleicht wird der eine oder andere Leser die Frage stellen, warum denn nicht gleich die Zirkulationspumpe mit der Homematic steuern?
Die Antwort ist einfach, weil die aktuell verfügbaren Homematic-Temperatursensoren mit Aktualisierungsintervallen von 3 und mehr Minuten  viel zu langsam sind!

Technische Daten

Mit Verwendung des WeMos D1 mini Controllermoduls mit dem  hochintegrierten Wifi-Chip ESP8266 eröffnen sich ganz neue Möglichkeiten für die kompakte Realisierung eines Steuerungsmoduls im praktischen Hutschienengehäuse. Dabei wird nicht nur die intelligente Steuerung der Zirkulationspumpe nach oben beschriebenen Steuerungsprinzip möglich sondern zusätzlich werden mit dem Modul auch zwei sog. 1wire-Temperatursensoren abgefragt, deren Meßsignal an die Homematic-CCU übertragen und auf einem optionalen OLED-Minidisplay angezeigt wird.

Hier die wesentlichen Eigenschaften des WIFFI-pump-2:

  • schnelle Temperaturmessung am Warmwasser (WW)-Ausgang mit NTC und …
  • Einschalten der Zirkulationspumpe in Abhängigkeit von der WW-Temperaturerhöhung
  • Einschalten mit integrierter Internet-Wochenzeitschaltuhr mit 10 Schaltzeiten
  • beliebiges Einschalten der Zirkulationspumpe auch von der Homematic-CCU direkt
  • zusätzliche Messung von zwei Heizungstemperaturen mit optionalen 1wire-Sensoren (z.B. Vorlauf- und Rücklauftemperatur )
  • optionales lichtstarkes OLED-Minidisplay zur Anzeige  der Temperaturen
  • kompaktes Hutschienengehäuse nur 2TE
  • einfache Einstellung auf eigenen Webseiten mit dem Browser
  • WLAN-Kommunikation mit dem heimischen Router
  • automatische Kommunikation mit  der Homematic-CCU  oder unabhängiger Standalone-Betrieb
  • Update über WLAN  (OTA) auch später im verbauten Zustand
  • JSON-Datentelegramm abrufbar für die Integration in andere Systeme der Hausautomation

Die elektronische Schaltung

Die gesamte Schaltung konnte auf einer so kleinen Platine realisiert werden, daß sie in ein 2TE Hutschienengehäuse paßt. Auf der einen Seite werden die 5V-Spannungsversorgung (externes 5V-Netzteil mit mindestens  0,5A)  an die Schraubklemmen geschaltet. Auf der anderen Netzspannungsseite ist der Einschaltkontakt für die Zirkulationspumpe verfügbar. Die Statusanzeige erfolgt mit einer LED, die im Betrieb durch ein Schraubklemmenloch erkennbar ist. Diese LED-Anzeige benötigt man nur zum Anlernen und oder zur Funktionskontrolle.

wiffi_pump2_13

Die gesamte Verschaltung des Moduls zeigt das folgende Bild. Der NTC-Temperaturfühler mißt die WW-Auslauftemperatur und schaltet bei schnellen Temperaturerhöhungen am WW-Auslauf das Relais zum Einschalten der Zirkulationspumpe. Danach bleibt die Zirkulationspumpe für etwa 4min eingeschaltet, damit das warme Wasser in der WW-Zirkulationsleitung verteilt wird. Die Einschaltzeit von 4min kann an die individuellen Bedürfnisse  im sog. Expertenmodus angepasst werden. Wie das geht, ist weiter unten beschrieben. Aber die gewählten 4min sind für typische Zirkulationsleitungen ein guter Wert. Darüberhinaus können wie im Bild dargestellt sog. 1wire Temperatursensoren angeschaltet werden, mit denen ohne Eichung eine recht genaue Temperaturmessung möglich ist. Ich verwende diese Sensoren für die Messung der Vorlauftemperatur im Kesselkreis und zur Messung der Vorlauftemperatur für die Fussbodenheizung (nach dem Mischer). Aber was man letztlich damit macht,  kann man flexibel nach eigenen Bedürfnissen anpassen.

Folie13

Wichtige Anmerkung zu den 1Wire-Temperatursensoren mit dem DS18B20:
Die Sensoren werden teilweise mit unterschiedlichen Farben der Anschlussdrähte geliefert. Ich kenne aktuell folgende Versionen:
– wie Bild oben :    SCHWARZ=gnd, BLAU=data, ROT=+3.3V
– oder alternativ :  GELB = gnd,  GRÜN = data, ROT = +3.3V
– oder alternativ:   SCHWARZ = gnd,   GELB = data,  ROT = +3.3V

Der Nachbau

Zum Nachbau des WIFFI-pump habe ich einen Bausatz zusammen gestellt, der auch weniger löterfahrenen Elektronikern den Nachbau möglich macht.  Beim WeMos  D1 mini Modul müssen nur die Buchsenleisten eingelötet werden. Die wenigen restlichen Bauteile lassen sich mit meiner Bauanleitung recht schnell zusammenbauen.

wiffi_pump2_8

Den Bausatz gibt es optional auch mit den zusätzlich verwendbaren  zwei  1wire-Temperatursenoren vom Typ DS18B20. Diese Sensoren sind schon fertig mit einem 1m Kabel konfektioniert, wobei der Sensor in einer Edelstahlhülse sitzt.

Darüberhinaus gibt es optional ein lichtstarkes OLED-Minidisplay, das auch nachträglich einfach hinzugefügt werden kann. Nur das Displaymodul aufstecken, die Software erkennt automatisch das Modul. Damit das auch alles sehr professionell aussieht gibt´s zum Display einen passenden Kunststoffrahmen und eine Blende im 3D-Druck für das Hutschienengehäuse dazu.

wiffi_pump2_1

Die Inbetriebnahme

Die Steuerung sollte in einem Installationsgehäuse an einem trockenen Platz in der Nähe der Heizung untergebracht sein. Leitungslängen für die Messsignale sollten möglichst nicht länger als 3m sein. Im Hinblick auf zuverlässige Funktion sind die Messleitungen aber so kurz wie möglich zu dimensionieren. Bei den Signaleitungen sollte man immer Netzleitungen und Signalleitungen getrennt verlegen. Dazu sind alle entsprechenden Sicherheitsregeln für den Umgang mit Netzspannungen unbedingt zu berücksichtigten.

Ohne entsprechende Fachkenntnisse muß die Installation unbedingt von Fachpersonal  durchgeführt werden. Siehe auch nochmal meine Warnhinweise hierzu: Warnhinweise

Anlernen und Einstellen des WIFFI-pump-2

Für die Einstellung des Moduls muß man nur zwei Taster  betätigen:

>> den Reset-Taster an der Seite des WeMos-Moduls

>>  den Prog-Taster auf der Platine

Achtung: nie den PROG-  und RESET-Taster gleichzeitig drücken, da das Modul dann in den Programmiermodus geht und u.U. die Firmware beschädigt wird.

Im Werkszustand weiß der WIFFI-pump-2 noch nicht die Zugangsdaten des heimischen WLAN. Deshalb muß man zuerst diese Zugangsdaten einprogrammieren. Dazu braucht man ein Smartphone oder besser ein Notbook mit WLAN. Und das geht so:

>> Reset-Taster kurz drücken.

>> Nach etwa 12 sec beginnt die LED im 1sec-Takt zu blinken. Damit wird signalisiert, daß ein WLAN-Hotspot gesucht wird. Da aber noch die Zugangsdaten fehlen, macht der WIFFI-pump-2 das einige Zeit so und geht dann nach längstens nach 60sec wegen Erfolglosigkeit in den Standalone-Modus (sehr kurze Blitze im 1sec-Takt).

>>Will man aber seinen WIFFI-pump-2 an den heimischen Router anlernen , dann sollte man während der 60sec-Suchphase den Prog-Taster etwa 2sec drücken. Die LED quittiert das mit einem gleichmäßigen Blinken mit etwa 2Hz. Jetzt ist der WIFFI-pump-2 dauerhaft im sog. Hotspot-Modus. Damit stellt er einen eigenen Hotspot mit dem Namen (ssid)  wiffi auf der festen IP 192.168.4.1 zur Verfügung. Mit einem Smartphone oder besser mit einem Notebook kann man im WLAN-Modus nun mit diesem Hotspot eine gesicherte Verbindung herstellen. Das Passwort (pwd) ist wiffi1234.

>> Danach mit dem Browser die Webseite zur Einstellung  des WIFFI-pump-2  aufrufen. Diese Webseite hat die feste IP 192.168.4.1  Achtung, diese IP-Adresse hat nichts mit der späteren IP-Adresse  des WIFFI-pump-2 im Heimnetz zu tun! Also man ruft im Browser einfach folgende Adresse auf   192.168.4.1/?  und erhält als Antwort die Hotspot-Webseite des WIFFI:

>> Mit wenigen verfügbaren Befehlen kann der WIFFI-pump-2  nun an den eigenen Router und die CCU angelernt werden: (… und nie den Doppelpunkt am Ende des Befehls  vergessen!)

  • 192.168.4.1/?ssid:meineSSID:    setzt die SSID des Routers, die SSID muß weniger als 25 Zeichen haben und keine Sonderzeichen enthalten
  • 192.168.4.1/?pwd:meinPasswort:   setzt den Router WLAN-Netzwerkschlüssel   ( WPA2) , Restriktionen wie bei SSID
  • 192.168.4.1/?ccu:192.168.178.41:   setzt die Homematic CCU-IP, dafür muß die CCU eine feste IP haben. Einstellen im Router !!

>> Damit ist schon der WIFFI-pump-2 für das Heimnetz eingestellt und kann mit dem Reset-Taster neu gestartet werden. Wenn die Router-Zugangsdaten richtig eingegeben worden sind, dann müßte nach etwa 12 sec der Wiffi-pump-2 beginnen, sich beim Router einzuloggen (LED blinkt jede Sekunde).  Meist dauert das einige Sekunden, bis das Einloggen erfolgreich ist und die LED dies signalisiert, indem sie jede Sekunde einen Doppelblitz sendet. Jetzt ist der WIFFI-pump-2 im Heimnetz mit einer eigenen IP und dem Namen  wiffi_pump.local  registriert. Welche IP das genau ist, das kann man im Router nachsehen.

>> An dem regelmässigen LED-Blitz kann man die Verbindungssituation erkennen:

  • sehr kurze und schwache regelmässige Blitze im 1sec-Takt: keine WLAN-Verbindung, stand-alone Betrieb!
  • helle regelmässige Blitze im 1sec-Takt: WLAN-Verbindung hergestellt. Aber keine CCU-Verbindung vorhanden!
  • helle regelmässige Doppelblitze  im 1sec-Takt: WLAN und CCU-Verbindung vorhanden!
  • helle regelmässige Blitze im 0,5sec-Takt: im Hotspot-Modus

Wichtig: Die Funktion der temperaturabhängigen Steuerung der Zirkulationpumpe funktioniert völlig unabhängig davon, ob WLAN-Verbindung da ist oder nicht! Ein Stand Alone Betrieb ist immer gewärleistet, auch wenn die CCU oder die WLAN-Verbindung ausfällt!

>> Jetzt läßt sich die Webseite des WIFFI-pump-2 mit jedem beliebigen Browser anzeigen. Man gibt in die Adresszeile einfach nur die IP oder den Namen ein:
http://<ip-wiffi>   oder einfach wiffi_pump.local. Das folgende Bild zeigt das Ergebnis.

Dabei ist zu beachten, daß die Messwerte nur beim Aktualisieren der Webseite oder Bedienen des Buttons „Aktualisierung Messwerte“ auch aktuell sind; eine permanente Aktualisierung der Anzeige erfolgt wegen Minimierung des Datenverkehrs nicht!

Einstellen der CCU

Damit  die Sensordaten und die Zustandsinformationen des Wiffi-pump-2 automatisch an korrespondierende Systemvariable in der Homematic-CCU geschickt werden, müssen einerseits in der CCU entsprechende Systemvariablen festgelegt werden und andererseits müssen die individuellen Namen dieser Systemvariablen auch  im Wiffi-pump-2 gespeichert werden. Das Anlernen des WIFFI-pump-2 an die CCU erfolgt also ganz einfach, indem man in der CCU die folgenden vier  Systemvariablen definiert:

>> wiffi_pump_ip  vom Typ Zeichenkette

>> wiffi_pump  vom Typ Logikwert , Werte EIN und AUS

>> wiffi_ww_temp  vom Typ Zahl, Maßeinheit °C    ( Anmerkung: ich verwende diesen Sensor zur Messung der Temperatur im WW-Speicher; kann natürlich individuell geändert werden! )

>> wiffi_vorlauftemp  vom Typ Zahl, Maßeinheit°C  ( Anmerkung: ich verwende diesen Sensor zur Messung derVorlauftemperatur der Heizung; kann natürlich individuell geändert werden! )

Eine funktionierende Kommunikation zwischen dem Wiffi-pump und der CCU erfordert absolut  gleiche Benamung der Systemvariablen in der CCU und im Wiffi-pump!

Wenn notwendig kann man mit dem name-Befehl  die HM-Systemvariablen auch mit eigenen Namen versehen . Standardmässig sind die oben im Bild gezeigten Systemvariablen benannt worden. Im ersten Schritt sollte man erst mal die von mir verwendeten Namen verwenden und kann dann die Erläuterung der nächsten 4 Befehle einfach überspringen !

  • 192.168.4.1/?name:o:meine_wiffi_ip:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariable, welche die IP-Adresse dese Wiffi-pump enthält.
  • 192.168.4.1/?name:1:zustand_Pumpe:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariable, welche den Schaltzustand der Zirkulationspumpe enthält.
  • 192.168.4.1/?name:2:meine_Temp_A:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariablen, welche die Temperatur des 1Wire-Sensors an D12 /A enthält.
  • 192.168.4.1/?name:3:meine_Temp_B:   setzt den individuellen Namenskürzel für die  entsprechenden HM-Systemvariablen, welche die Temperatur des 1Wire-Sensors an D13 /B enthält.

Und bei der Homematic immer beachten, daß für die Namen der Systemvariablen nie Sonderzeichen außer dem Tiefstrich verwendet werden. Das gibt nur Ärger !!

Die Befehle des WIFFI-pump-2

Im WIFFI-pump-2 sind eine Reihe von Befehlen integriert, mit denen der WIFFI nach den eigenen individuellene Bedürfnissen eingestellt werden kann (… aber nicht muß!). Dazu sind 3 Webseiten vorhanden, die durch Anklicken der blauen Schrift-Buttons aufgerufen werden. Die Seite Normalmodus  zeigt die Messwerte , alle relevanten Statusinformationen und die möglichen Browser-Befehle.  Mit Anklicken des EIN/AUS-Buttons kann man die Zirkulationspumpe manuell dauerhaft schalten und mit Aktualisierung der Messwerte werden die Messwerte erneut ermittelt.

Folgende Befehle können aktuell per Browsereingabe verwendet werden (Achtung nie den abschließenden Doppelpunkt vergessen !) .

Die Internet-Schaltuhr

Seht parktisch ist eine integrierte Schaltuhr mit 10 Schaltzeiten, die sich automatisch mit der aktuellen Internetzeit setzt. Die Schaltuhr kann hilfreich sein, wenn man beispielsweise in der Heizung feste Zeiten für die Desinfektion eingestellt hat. An diesen festen Zeiten kann man dann automatisch auch die Zirkulationspumpe einschalten. Zwar könnte man das auch über die Homematic machen, aber das Gerät soll auch ohne Homematic komfortabel funktionieren. Die Anwendungsmöglichkeiten einer integrierten Schaltuhr sind sicher vielfältig und müssen nicht näher erläutert werden.

Mit der Webseite „Schaltzeiten“ können insgesamt 10 Schaltsequenzen gesetzt werden. Das folgende Bild zeigt die Einstellseite:

Gesetzt werden die Schaltzeiten mit dem time-befehl in der Adresszeile des Browsers. Will man beispielsweise mit der Schaltzeit 1 die Zirkulationspumpe am Samstag (Wochentag 7) um 7h15 bis 8h15 einschalten, dann erfolgt dies mit dem Befehl in der Adresszeile des Browsers::

<ip-wiffi>/?time:1:7:0715:0815:

Weitere Erklärungen ergeben sich sicher aus dem obigen Bild der Webseite.

Der Experten-Modus

Als dritte Webseite ist der Expertenmodus vorhanden. Normalerweise sind hier keine Veränderungen durchzuführen. Und man sollte dies auch nur dann tun, wenn man weiß was man da einstellt. Ansonsten kann das Gerät u.U. danach nicht mehr funktionieren. Veränderungen von Kennwerten sind mit dem param-Befehl möglich. Wenn man beispielsweise die Laufzeit der Zirkulationspumpe von den eingestellten 240sec auf 300sec vornehmen will, dann macht man das mit dem Befehl:  <IP-wiffi>/?param:0:300:

Details zur Erläuterung der Experten-Parameter und die Liste möglicher Befehle sind im Informationsblatt der aktuellen Firmware im runterladbaren ZIP-Archiv (siehe weiter unten).

Update der Firmware über WLAN

Ein Update des WIFFI erfolgt ohne Demontage bzw. Geräteöffnung komplett über das WLAN. Dabei ist der WIFFI im Heimnetz über WLAN eingeloggt und seine Webseite ist mit der vom Router vergebenen IP-Adresse aufrufbar. Hier ist die genaue Beschreibung der Vorgehensweise als pdf-Dokument zum Runterladen :  wiffi_update_anleitung22

Hinweis: Ab der Firmwareversion wiffi_pump2_60a  ist das Update deutlich einfacher über die eigene Update-Webseite des WIFFI durchzuführen !

und hier ist die aktuelle Firmware zum Download:

diese Version wird verwendet mit und ohne 64×48- Display:

wiffi_pump_47 mit/ohne 64×48 Display
Ab 10/2016 wird als ein etwas breiteres OLED-Display mit 128×64 Pixel verwendet. Die dafür entsprechend geänderte Firmware ist:

wiffi_pump_53a mit/ohne 128×64 Display   >> besser einstellbarer Schaltalgorithmus (auch bei langsameren  Temperatursteigerungen) , Help-Funktion erweitert, PWD und SSID jetzt auch mit Sonderzeichen möglich

wiffi_pump_57a mit/ohne 128×64 Display  >> PWD und SSID mit Leerzeichen, verbesserte 1Wire-Temperaturmessung,Temperaturen mit Korrekturmöglichkeit, Update mit/ohne Erhalt der Zugangsdaten und Parameter, Parameter für Urlaubsabschaltung

wiffi_pump_60a mit/ohne 128×64 Display  >> vereinfachtes Update , zusätzliche Helpseite

wiffi_pump_61 mit/ohne 128×64 Display  >> verbessertes Verhalten bei WLAN-Störungen, Komplett-Update notwendig (siehe Update Menue)

wiffi_pump_66 mit/ohne 128×64 Display  >> Fix für neue CCU2-Firmware 2.27.7: 8181-Request angepasst, damit systemvariablen aktualisiert werden

wiffi_pump_69 mit/ohne 128×64 Display  >> JSON-Format angepasst, Bitte beachten: param[20] entsprechend der vorhandenen Hardwareversion setzen !

wiffi_pump_71 mit/ohne 128×64 Display  >> Die 1Wire-Eingänge können optional (param[21] einstellen!) auch als Tastereingänge verwendet werden. Taster über 330Ohm nach Ground! Die Taster schalten die Pumpe für die normale Pumpenzeit ein. Alternativ kann anstelle eines Tasters auch ein Bewegungsmelder etc. mit Open-Kollektor-Ausgang verwendet werden.

wiffi_pump_72 mit/ohne 128×64 Display  >> JSON-Telegramm korrigiert

Zum Updaten die heruntergeladenen Zip-Archive in ein temporäres Verzeichnis entpacken und zum Update nur die *.bin Datei verwenden, nicht den  Zip-File !!!

Update der Firmware über USB

Ein Update über USB ist etwas komplizierter als über WLAN.  Aber wenn beispielsweise ein neues WeMos-Modul verwendet werden soll, dann ist  ein Update über USB die einzige Lösung.

Hier die Anleitung dafür:

  1. Aktuelle Firmware runterladen, entpacken und bin-File wegspeichern
  2. Zuerst für den WeMos den notwendigen USB-Treiber installieren: windows 32&64bit
  3. USB-Kabelverbindung PC <>  WIFFI-pump herstellen und im Gerätemanager unter Anschlüsse (COM & LPT) nachschauen, welcher COM-Port aktiv ist
  4. Xtcom Util runterladen, entpacken und starten
  5. Fenster Tools(T) / Config Device öffnen, die aktive COM-Nummer und die Baudrate 115200 eingeben und dann Open.
  6. Danach Connect  und dann am WIFFI-pump den Prog-Taster gedrückt halten und währenddessen am WeMos kurz den Reset-Taster drücken. Wenn erfolgreich, dann kommt Meldung Connect with target OK
  7. Fenster API Test(A) /Flash Image Download öffnen und beim Image Path den Pfad des abgespeicherten bin-Files eingeben.
  8. Dann mit dem  Download Button den Download starten. Erfolgreicher Abschluss mit Operation Succeeded!
  9. Danach startet der WIFFI-pump. Wenn LED  im sec-Takt blinkt, dann Prog-Taster solange drücken bis Dauerleuchten.
  10. Danach startet der WIFFI-pump neu , warten bis die LED im 0,5sec-Takt blinkt, was den Hotspot-Modus signalisisiert
  11. Im Hotspot-Modus können jetzt auf IP 192.168.4.1 wie oben beschrieben die eigenen Zugangsdaten eingegeben werden.

Rückstellen in den Werkszustand

Manchmal kann es notwendig sein, die im EEPROM abgelegten Zugangsdaten für den heimischen WLAN-Router zu löschen und den WIFFI-pump in den Auslieferungszustand zu versetzen. Hierfür wird durch 2 sec-Drücken des PROG-Tasters zuerst in den  Hotspot-Modus geschaltet, was durch schnelles Blinken der roten LED angezeigt wird. Danach hält man den PROG-Taster für mehr als  10 sec gedrückt, was mit einer langsam blinkenden LED bestätigt wird, die dann in Dauerleuchten übergeht.  Jetzt sind alle Nutzerdaten gelöscht und mit Druck auf den RESET-Taster kann wieder neu gestartet werden.

Achtung: nie den PROG-  und RESET-Taster gleichzeitig drücken, da das Modul dann in den Programmiermodus geht und u.U. die Firmware beschädigt wird.

Alternativ kann man das auch mit dem oben beschrieben factory-Befehl durchführen.

Schalten der Zirkulationspumpe mit der Homematic

Eigentlich braucht man die Zirkulationspumpe nicht von der CCU schalten, da sie ja vom WIFFI-pump-2 automatisch in Abhängigkeit von der Temperaturerhöhung am WW-Auslauf eingeschaltet wird.  Aber aus verschiedenen Gründen ist es dennoch sinnvoll, die Zirkulationspumpe zu bestimmten Zeiten einzuschalten. Beispielsweise wenn die Heizung zur Legionellendesinfektion zu einem bestimmten Zeitpunkt die Temperatur im WW-Speicher hochfährt, dann macht ein gleichzeitiges Spülen der Ringleitung durchaus Sinn. Oder wenn man morgens immer zu einer bestimmten Zeit duscht, dann will man nicht warten, bis nach Aufdrehen des Wasserhahnes die Zirkulationspumpe das warme Wasser erst ranbringt. In all diesen Fällen ist ein vorausschauendes zeitgesteuertes Einschalten absolut sinnvoll.

Das Einschalten erfolgt mit einem einfachen HM-Skript, das zum gewünschten Zeitpunkt die Pumpe eine bestimmte Zeit einschaltet.

HM_wiffi_prog

und hier ist das HM-Skript dazu, das in meinem Beispiel alle 15min zwischen 7h00 und 8h00 aufgerufen wird.

!hiermit wird die z_pump  für 300 sec eingeschaltet 
string befehl = "/?trigger:300:";   
string IP = dom.GetObject("wiffi_pump_ip").Value();  !Holt IP_adresse des WIFFI_wz
var send_data = "http://" + IP  + befehl; !Befehl zusammensetzen
 
WriteLine(send_data);
string stdout; string stderr;           !und Befehl ausgeben
system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);

Man kann auch einfach mit einem Browser dies ausprobieren, indem man folgenden Befehl eingibt:

<ip-wiffi>/?trigger:300:       Danach schaltet die Zirkulationspumpe für 300sec ein.

Natürlich kann man solch einen String auch von anderen Rechnern wie Rasberry und Co. abschicken. Somit ist der WIFFI-pump sehr zukunftssicher. Vielleicht mache ich dazu mal eine einfache App . Anregungen dazu nehme ich gerne entgegen!

Die Montage des NTC-Temperatursensors

Der Temperatursensor muß am vorlaufseitigen Ausgangsrohr des Wasserspeichers so nah angebracht werden, daß bei Zapfen von warmem Wasser möglichst schnell eine Temperaturerhöhung gemessen wird. Andererseits darf der Sensor nicht zu nah am Wasserspeicher sein, weil sonst die wasserseitige Wärmeausstrahlung das Rohr immer erwärmt. Mein Erfahrungswert für die optimale Leitungsentfernung zwischen Sensor und Speicherausgang ist  etwa 40cm bis 60cm; das hängt vom Leitungsquerschnitt und den räumlichen Gegebenheiten ab. Muß man halt etwas probieren!
Test: Wenn die Zirkulationspumpe längere Zeit nicht gelaufen ist, dann sollte der geplante Anbringungsort für den Sensor höchstens handwarm sein!
Folie8

Besonders wichtig für eine gute Funktion ist natürlich eine gut entlüftete Ringleitung. Wenn hier sich Luftblasen angesammelt haben, dann ist eine effektive Pumpfunktion nicht möglich. Besonders die Schwerkraftbremse muß einwandfrei funktionieren, damit bei abgeschalteter Zirkulationspumpe auch wirklich kein Wasser zirkuliert. Prüfen kann man das folgendermaßen:
Zirkulationspumpe stromlos machen und mindestens 2 Stunden den Kreislauf abkühlen lassen. wenn  danach der Rücklauf  kalt ist und der Vorlauf nur auf dem ersten Meter handwarm, dann ist keine natürliche Zirkulation da und die Schwerkraftbremse ist in Funktion.

Danach wird die Zirkulationspumpe eingeschaltet und die Zeit gemessen, bis das warme Wasser am Rücklauf angekommen ist. Wenn nach 2 bis 5 Minuten das warme Wasser im Rücklauf angekommen ist, dann scheint der hydraulische Pumpenkreis wohl in Ordnung zu sein!

Hinweise bei Funktionsproblemen

Ein ganz einfacher Funktionstest ist nun möglich, indem man den noch nicht montierten kalten NTC-Temperatursensor zwischen den Fingern einige Sekunden anwärmt. Dann muß sofort das Relais einschalten und nach etwa 4min die Zirkulationspumpe wieder abschalten. Wenn das so funktioniert, dann funktioniert der Wiffi-pump richtig!

Wenn es nicht funktioniert, dann sind nachfolgend einige mögliche Fehlerursachen aufgelistet:

  • Ist die Leitung für den NTC-Sensor nicht länger als 1 bis 2m und liegt möglichst nicht mit anderen Kabeln nah zusammen
  • Ist das Netzteil in Ordnung ? Oft neigen Billig-Netzteile zu Störungen.
  • Ist der NTC-Sensor an einem metallischen Rohr montiert ? Kunststoffrohre funktionieren nicht !
  • Hat der NTC-Sensor guten Wämekointakt mit dem Rohr am WW-Auslauf ?
  • Ist der Sensor auch nicht zu nah am WW-Auslauf positioniert, so daß bei  Erwärmung des WW_Speichers die Erwärmung bis in das WW-Auslaufrohr einwirkt.
  • Hat die Zirkulationspumpe eine sog. Schwerkraftbremse ? Bei modernen WW-Pumpen ist das Ventil in der Pumpe. Es gibt aber auch Rückschlagventile, um ein Zirkulation bei abgeschalteter Pumpe zu verhindern.
  • Wenn die Pumpe trotzdem zu häufig schaltet, dann kann in den Experteneinstellungen der Wert param[1] erhöht werden. Typischer Einstellbereich 4 (zu empfindlich)  bis 20 ( unempfindlich). Wenn param[11] vorhanden, dann diesen Wert nicht kleiner als param[1] einstellen.

Hier noch entsprechende Hinweise von der Help2-Seite des WIFFI-pump:

… wo gibt´s den Bausatz ?

Einen kompletten Bausatz des WIFFI-pump-2  kann man in meinem Webshop erwerben: 

Bausatz WIFFI-pump-2

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. Auch die notwendigen Eingriffe in das Heizungssystem dürfen nur von ausgebildeten Fachpersonal durchgeführt werden. Es sind die geltenden Sicherheitsvorschriften und die DVGW-Richtlinien einzuhalten.

Der WIFFI-WZ 2.0 … der Wohnzimmersensor

Der WIFFI-WZ 2.0 … der Wohnzimmersensor

Update:  Anpassung an optionalen CO2-Sensor MH-Z14, Integration IP-Symcon möglich

Das ist der  WIFFI-WZ !

Der WIFFI-WZ ist das erste Modul einer Reihe von weiteren Sensor- und Aktor-Modulen, die hauptsächlich zur  Erweiterung  und  Ergänzung der Hausautomation mit der Homematic konzipiert sind.  Die WIFFI´s sind allesamt Funkmodule , die das in nahezu jedem Haushalt vorhandene gesicherte WLAN-Funknetz verwenden, um mit der Homematic-CCU zu kommunizieren.

Der WIFFI-wz bringt  8 (!)  Sensoren und einen Warnmelder unter einen Hut:IR-Bewegungsmelder links

  • IR-Bewegungsmelder rechts
  • Temperaturmessung (mit DHT22)  (BME280 alternativ verfügbar)
  • Luftfeuchtemessung (mit DHT22)  (BME280 alternativ verfügbar)
  • Luftdruckmessung (mit BMP180 oder BMP280 oder BME280 )
  • Geräuschmelder mit einstellbarer Empfindlichkeit
  • Helligkeitsmessung /Luxmeter  mit BH1750
  • Luftgütesensor  mit MQ135 oder optional mit MH-Z14
  • Beeper als akustischer Warnmelder

Zusatzlich werden aus diesen Messwerten für die Hausautomation sehr nützliche Kennwerte berechnet und an die Homematic oder andere Server übertragen:

  • Elevationswinkel der Sonne  (für Rollladen- und Beschattungssteuerung)
  • Azimutwinkel der Sonne  (für Rollladen- und Beschattungssteuerung)
  • Taupunkt-Temperatur (für scimmelvermeidung und Steuerung von Lüftungen und Entfeuchter)
  • absolute Feuchtigkeit (für scimmelvermeidung und Steuerung von Lüftungen und Entfeuchter)
  • Luftdrucktrend zur Erkennung von Wetteränderungen

Und so sieht das Gerätchen im zusammengebauten Zustand aus. Mit einer Stromversorgung über ein einfaches 5v/1A-Steckernetzteil sind keine Batterien notwendig. Das macht auch Sinn, weil ja im Wohnraum eh eine Steckdose vorhanden ist und regelmäßiger Batteriewechsel nur nervt! Darüberhinaus benötigen fast alle Gassensoren eine Beheizung, die mit Batterien gar nicht sinnvoll darstellbar ist!

Der WIFFI-WZ ist ein Selbstbauprojekt; der Bausatz dafür mit bereits programmierten Chips kann über  meinen Webshop bezogen werden. Ein mitgelieferte bebilderte Bauanleitung macht den Nachbau auch für „Nicht-Nerds“ gut machbar. Lediglich etwas Erfahrung mit Elektronik-Bauteilen und Lötkolben ist notwendig. Der WIFFI selbst ist bereits programmiert. Die Eingabe der Zugangsdaten für den heimischen WLAN-Router und der IP-Adresse der eigenen Homematic-CCU erfolgt sehr komfortabel mit einem Smartphone/Tablet oder Notebook auf der eigenen Webseite des WIFFI-WZ .

Die Vorgeschichte

Eigentlich war dieser Sensor als reiner „Wohnzimmersensor“ konzipiert, aber die Diskussion hier zeigte, daß ein großes Interesse an einem solchen Sensor besteht und  eine universelle Verwendbarkeit in jedem Raum gewissermaßen als „Raumsonde“  für viele Hausautomatisierer sehr interessant ist. Entsprechende geeignete Multifunktionssensoren gibt es zumindest für die Homematic nicht, sondern man müßte die komplexe Multifunktion mit einer Vielzahl von Einzelsensoren darstellen, was nicht nur hohe Kosten bedeutet sondern auch wegen des dann verwendeten „Gemischtwarenladens“ auch sehr unschön aussieht! So ist unter dem Pseudonym „Wohnzimmersensor“ dieser nachfolgend als WIFFI-WZ  bezeichnete Multifunktionssensor entstanden, der die Anforderungen an eine anspruchsvolle intelligente Hausautomation ausgezeichnet erfüllt.

1. Der WIFFI-WZ  … 8 (!) Sensoren unter einem Dach!

Die Anforderungen an einen Raumsensor sind bestimmt durch die Anforderungen der in diesem Raum wohnenden Menschen an Funktionalität, Komfort und Lebensqualität. Und da spielen Licht, Luft, Geräusche und Bewegungen eine zentrale Rolle. Deshalb wurde die Auswahl der notwendigen Sensoren im Hinblick auf die entsprechenden Zustandsparameter des Wohnraumes vorgenommen. Mit den Eigenschaften der verwendeten Sensoren ergeben sich daraus die Technischen Eigenschaften des WIFFI-WZ:

Lufttemperatur, Messung mit DHT22, Technische Details hier: DHT22 Daten oder alternativ mit dem BME280
Luftfeuchtigkeit, Messung mit DHT22  oder alternativ mit dem BME280
Luftqualität, Messung mit MQ135, Technische Eigenschaften hier: MQ 135 Datenblatt
Luftdruck, Messung mit BMP180, Technische Eigenschaften hier: BMP 180 Datenblatt oder alternativ mit dem BME280
Helligkeit, Messung mit BH1750,  Datenblatt hier: BH 1750 Datenblatt
Geräusche / Lautstärke:   Messung mit Elektret-Mikrofon und Auswertung mit geeigneter Schaltung
–  2 Bewegungen in zwei Raumrichtungen: nach rechts und  links. Bewegungsmelder nach dem PIR-Prinzip, Datenblatt : http://www.mpja.com/download/31227sc.pdf

Insgesamt sind das 8  Sensorsignale, die abhängig von den Veränderungen der gemessenen Signale mehr oder weniger häufig an die Homematic-Zentrale gesendet werden. Die Übertragung der Sensorsignale  an die Homematic erfolgt ausschließlich drahtlos, natürlich  mit WPA2 abgesichertem WLAN.

2. Der WIFFI-WZ …  Nachbau ganz einfach!

Damit der Nachbau auch für den weniger versierten Elektroniker möglich ist, wurde ein Komplettbausatz entwickelt. Dabei ist die Basisplatine mit dem Prozessor ESP8266-12 und den den vielen kleinen SMD-Bauelementen bereits auf der Trägerplatine verlötet. Lediglich größere Steckverbinder müssen selbst konfektioniert und verlötet werden. Sorgfalt und der fachgerechte Umgang mit dem Lötkolben sind aber
schon erforderlich!

Folie2

Alle Teile und alle zu verlötenden oder steckbaren Sensoren sind beim Bausatz schon dabei. Das Netzteil wird allerdings nicht mitgeliefert. Benötigt wird ein 5V/1A Steckernetzteil mit 5,5mm/2.1mm Hohlstecker.  Dabei sollte man beim Netzteil auf gute Qualität achten, weil diese ja immerhin im Dauerbetrieb arbeiten.  Die einschlägigen Elektronikhändler bieten hier genügend Alternativen an.

In der Bauanleitung  hier wird Schritt für Schritt der Zusammenbau erklärt.  In deutlich weniger als einer Stunde müßte normalerweise ein erfolgreicher Zusammenbau  erledigt sein.

Folie4

Mehr Infos zum Selbstbau in der WIFFI-WZ Bauanleitung ab Firmware wiffi_wz_37

3. So sieht der WIFFI-WZ im Gehäuse aus

Damit der WIFFI-wz auch im Zimmer eine gute Figur macht und an geeigneten Stellen optisch ansprechend platziert werden kann, wurde eine kubische Gehäuseform entwickelt. Diese nimmt die Platinen mit allen Sensoren auf und ist im 3D-Druckverfahren hergestellt. Es muß nicht nachbearbeitet werden, da bereits alle Bohrungen und Ausschnitte enthalten sind. Das verwendete Kunststoffmaterial ist PLA-Filament. Deshalb ist kein Betrieb im Aussenbereich oder unter sehr warmen Umgebungsbedingungen möglich. Das Gehäuse ist formstabil bis ca. 60°C, was für den sinnvollen Betrieb des WIFFI-wz mit eingebautem Temperatursensor normalerweise ausreichend sein sollte. Die Oberfläche ist nicht völlig glatt sondern hat aufgrund des Herstellverfahrens eine schichtweise Struktur wie man in den beigefügten Bildern erkennen kann.


Das Gehäuse ist unten offen, damit die Eigenerwärmung der Platine und insbesondere des beheizten Gassensors mit den rückwärtigen Lüftungsschlitzen abgeführt wird. Der Temperatursensor ist ganz unten montiert, damit Fehlmessungen durch thermische Effekte im Gehäuse möglichst gering sind.

Folie46

Man kann das Gehäuse noch weiter „veredeln“ . Dazu sind die Gehäuseflächen möglichst glatt zu schleifen und ein sog. Dickschichtfüller aufzutragen (aus dem Autozubehörhandel). Dann kann man abschließend mit Acryllack die Deckschicht in der gewünschten Farbe aufbringen. Das Gehäuse ist aus 3D-Ausdruck in meinem Webshop als Option für den WIFFI-wz verfügbar. Wer einen eigenen 3D-Drucker hat, der kann auch das Gehäuse selber ausdrucken. Hier der stl-Datenfile als Download dazu: WIFFI-wz 3D-Gehäuse  Unter Windows 10 kann man sich das Gehäuse mit dem standardmäßig verfügbaren Programm  3D Builder ansehen und ggf. editieren bzw. anpassen.

Wer die Montage im Deckengehäuse vorzieht, für den ist diese Lösung gedacht:

4. Programmierung und Einstellung

Der WIFFI hat schon einen komplett programmierten Mikrocontroller mit WLAN auf dem Board. Die bei WLAN notwendigen Zugangsdaten für den heimischen Router können sehr komfortabel eingegeben werden, indem man den WIFFI-WZ als Hotspot arbeiten läßt.  Auf der eigenen Webseite des WIFFI-WZ kann man dann die notwendigen Daten und Einstellungen mit einem Browser durchführen. Dafür sind keinerlei Programmierkenntnisse notwendig, also alles sehr einfach :)) Die folgenden Schritte zeigen kochrezeptartig das Vorgehen:

1. RESET-Taster drücken, etwa 20sec warten bis die rote LED etwa alle 2sec blinkt (dabei versucht der WIFFI sich ins WLAN einzuloggen, was natürlich wegen des Fehlens der Zugangsdaten noch nicht geht)

2. Dann den PROG-Taster etwa 2sec drücken bis die rote LED in 1sec-Takt blinkt.  Jetzt ist der WIFFI-WZ im Hotspot-Modus. Achtung: nie den PROG-  und RESET-Taster gleichzeitig drücken, da das Modul dann in den Programmiermodus geht und u.U. die Firmware beschädigt wird.

3. Mit dem Smartphone oder besser Laptop  nach einem Hotspot mit dem Namen „wiffi“ suchen und die Verbindung herstellen. Da es eine gesicherte Verbindung ist, muß beim ersten Zugang das Kennwort „wiffi1234“ eingegeben werden. Danach müßte , wenn alles richtig funktioniert, eine gesicherte Verbindung zum „wiffi“ vorhanden sein.

4. Auf dem so im WLAN eingeloggten Smartphone oder Tablet in die Adresszeile des Browsers die Webseite des WIFFI-WZ  aufrufen mit: 192.168.4.1/? Die Antwort sieht dann so aus:

5. Jetzt die notwendigen Eingaben in der Adresszeile des Browsers machen. Das macht man mit folgenden Befehlen, die immer mit einem Doppelpunkt abgeschlossen werden:
192.168.4.1/?ssid:my_ssid:  dabei ist „my_ssid“ die SSID des eigenen Routers  (Achtung, die SSID darf keinen Doppelpunkt enthalten !)
192.168.4.1/?pwd:my_pwd:  dabei ist „my_pwd“ das Router-Passwort des eigenen Routers (Achtung, das PWD darf keinen Doppelpunkt enthalten!)
192.168.4.1/?ccu:my_ccu:  und „my_ccu“ ist die feste (!) IP der eigenen CCU1 oder CCU2

Wenn alle drei Daten richtig eingegeben sind und auf der Webseite auch richtig angezeigt werden, dann ist der WIFFI-WZ startbereit und kann mit Druck auf den RESET-Taster neu gestartet werden. Nach etwa 15 bis 30 sec blinkt die LED  solange im 2sec Takt bis der WIFFI sich im heimischen WLAN eingeloggt hat. Danach, im normalen Betrieb,  blinkt die rote LED immer dann, wenn die Bewegungsmelder „anschlagen“. Jetzt kann die Webseite des WIFFI-WZ im Heimnetz aufgerufen werden. Dazu schaut man im Router nach, welche IP der WIFFI bekommen hat und ruft dann einfach diese IP auf, indem man diese IP in die Adresszeile des Browsers eingibt. Oder man schreibt einfach in die Adresszeile: wiffi_wz.local.  Allerdings kann diese letzte Methode in manchen Heimnetzen nicht erfolgreich sein. Ich persönlich verwende immer die IP, dann hat man eine eindeutige Zuordnung. Deshalb stellt man dann auch sinnvollerweise den Router so ein, daß er dem WIFFI-WZ immer diese gleiche IP zuteilt.

Das ist eigentlich schon alles.  Für besondere individuelle Anforderungen gibt es noch mehr Befehle, die oben im Bild aufgelistet sind. Diese Befehle sind aber nur für besondere Anwendungen und werden weiter unten erklärt. Die Verbindung zur CCU wird über Systemvariablen hergestellt, deren Namen von mir vorgegeben sind (in rot). Allerdings lassen sich mit dem name-Befehl beliebige andere Namen definieren. Im ersten Schritt sollte man aber diese Vorgabe erst mal behalten! Darunter werden auf dieser Webseite die Sensorsignale des WIFFI-WZ dargestellt.  Diese Werte werden nicht automatisch in einem festen Zeitraster aktualisiert, um das Datenaufkommen zu begrenzen. Erst durch Aktualisierung der Webseite oder Klick auf den Link Aktualisierung der Messwerte wird die Anzeige auch aktualisiert. Später ist eine APP geplant, welche die Daten anzeigen und möglichst als Diagramm darstellen soll. Mit Klick auf die Buzzer-Links kann man manuell den Buzzer ein- und ausschalten. Natürlich geht das auch mit der CCU mit dem unten beschriebenen Skript. Die Webseite des WIFFI-WZ ist haupsächlich zum komfortablen Einstellen und Anschauen der Daten.

Die Kommunikation mit der CCU läuft im Hintergrund völlig automatisch ab.

5. Anlernen an die CCU

Das Anlernen des WIFFI-WZ an die CCU ist sehr einfach, weil für jedes Sensorsignal nur eine korrespondierende Systemvariable angelegt wird. Entsprechend der Vorgabe (rote Namen) sind folgende Systemvariablen inder CCU anzulegen:

wz_ip vom Typ „Zeichenkette“
wz_motion_left vom Typ „Logikwert“
wz_motion_right vom Typ „Logikwert“
wz_temp vom Typ „Zahl“ mit Maßeinheit „°C“
wz_taupunkt  vom Typ „Zahl“ mit Maßeinheit „°C“
wz_feuchte vom Typ „Zahl“ mit Maßeinheit „%“
wz_feuchte_abs  vom Typ „Zahl“ mit Maßeinheit „g/m3“
wz_lux vom Typ „Zahl“ mit Maßeinheit „lux“
wz_noise vom Typ „Logikwert“
wz_co2 vom Typ „Zahl“ mit Maßeinheit %
wz_baro vom Typ „Zahl“
wz_luftdrucktrend vom Typ „Zeichenkette“
wz_buzzer vom Typ „Logikwert“
… und wer optional die im WIFFI-wz berechneten Werte für den Sonnenstand in der CCU verwenden möchte, der muß noch zwei weitere Systemvariablen in der CCU definieren:
wz_elevation vom Typ  Zahl mit Maßeinheit °
wz_azimut  vom Typ  Zahl mit Maßeinheit °

Für die Lösung in der Deckenrosette kann man noch den Relaiszustand auslesen mit…
wz_relais vom Typ „Logikwert“

Die Aktualisierung aller genannten  Systemvariablen erfolgt automatisch, aber nur wenn sich die Messwerte ändern. Dadurch wird vorteilhafterweise der Datenfluss stark reduziert.
Anmerkung: Die oben genannten Systemvariablen sind „normale“ CCU-Systemvariablen, deren Zahl nicht wie bei den HM-Skriptvariablen auf  200 begrenzt sind !

6. Anzeige der LEDs

Die blaue LED zeigt den logischen Zustand des Geräuschmelders an. Damit kann die Empfindlichkeit mit dem Trimmpotentiometer einjustiert werden. Wenn diese LED bei völliger Ruhe gerade nicht leuchtet, ist  der Geräuschmelder richtig eingestellt. Für die CCU wird das Signal des Geräuschmelders standardmäßig auf 3min verlängert und bei jedem neuen Geräusch nachgetriggert. Die rote LED zeigt verschiedene Betriebszustände und Meldungen an. Wenn der WIFFI-WZ nach dem Reset versucht sich in das WLAN einzuloggen, dann leuchtet diese LED im 2sec Takt. Wenn das Einloggen erfolgreich war, dann zeigt alle 2sec  ein regelmäßiger „Herzschlag“  den ordnungsgemäßen Betrieb an:

> Ein ganz schwacher kaum sichtbarer einfacher Blitz signalisiert, daß weder WLAN- noch CCU-Verbindung da sind. > Ein etwas längerer einfacher Blitz signalisiert eine bestehende Verbindung mit dem WLAN > Ein Doppelblitz signalisiert die Verbindung mit WLAN und CCU

Aber dabei ist zu beachten, daß diese Blitzsignale von dem Status der Bewegungsmelder überschrieben wird, d.h. wenn einer der beiden  Bewegungsmelder „anschlägt“, dann leuchte die LED dauerhaft . Für die CCU werden die Signale der Bewegungsmelder standardmäßig auf 3min verlängert und bei jeder weiteren Bewegung nachgetriggert.

7. Auslösen des Buzzers von der Homematic-CCU

Mit jedem üblichen Browser kann man mit einem Befehl den Beeper des WIFFI-WZ für eine bestimmte Zeit einschalten. Dazu muß man aber die dem WIFFI-WZ im Router vergebene IP-Adresse wissen. Bei mir hat der WIFFI-WZ eine feste IP-Adresse 192.168.178.65 im Router zugewiesen bekommen. Dementsprechend ist der Buzzer-Befehl: 192.168.178.65/?buzzer:80:   „80“ ist Einschaltzeit des Buzzer in 0.1sec-Schritten, hier also 8,0 sec Da in der CCU auch die aktuelle IP des WIFFI-WZ in der Systemvariablen wz_ip abgelegt ist, kann man auch bei dynamischer IP-Adressenvergabe den Buzzer durch Ausführen eines geeigneten HM-Skriptes auslösen. Zum Beispiel so:
beeper_01

und das zugehörige HM-Skript ist:

HM-Skript   
!WIFFI-Beeper für 0,5 sec einschalten
string befehl = "/?buzzer:5:";   
string IP = dom.GetObject("wz_ip").Value();  !Holt IP_adresse des WIFFI_wz
var send_data = "http://" + IP  + befehl; !Befehl zusammensetzen
 
WriteLine(send_data);
string stdout; string stderr;           !und Befehl ausgeben
system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);
Natürlich kann man das Skript statt mit dem system.Exec Befehl auch mit analogen CuxD-Befehlen starten; das hat den Vorteil einer stabileren Arbeitsweise. Mehr dazu im Homematic-Forum.

8. Hinweis für den Geräuschmelder

Die Empfindlichkeit des Geräuschmelders ist mit dem Trimmpoti auf der Grundplatine einstellbar. Dazu wird das Trimmpoti soweit verdreht , bis die schwach leuchtende blaue LED ohne Geräusch gerade verlischt. Bei Geräuschen muß sie dann angehen. Die Einstellung ist etwas sensibel. Wenn die Einstellung zu empfindlich vorgenommen wird, dann führen manchmal Sendesignale des WLAN-Chips zu ungewolltem Auslösen des Geräuschmelders. Einstellungen zu unempfindlich führen dazu, daß nur laute Signale den Geräuschmelder auslösen. Hier ist etwas Probieren angesagt, um zu einer optimalen Einstellung zu gelangen.

9. Hinweis für den Temperatur- und Feuchtigkeitssensor

Verwendet wird ein Sensor vom Typ DHT-22, der sowohl Temperatur als auch Luftfeuchte relativ genau messen kann. Bei Verwendung des WIFFI-WZ als freistehende Platine kann dieser  Sensor einfach oben auf der Bestückungsseite eingelötet werden. Für die Verwendung im Gehäuse muß eine ungewollte Erwärmung des Sensors durch die Gassensor-Beheizung des MQ135 weitestmöglich verhindert werden. Deshalb ist bei Gehäuseeinbau dieser Sensor ggf. unterhalb der Platine zu platzieren. Die beste Lösung ist allerdings immer eine von den Wärmeerzeugern auf der Platine beispielsweise über kurze Zuleitungen (10 bis 20cm) getrennte Montage. Mehr dazu in der Bauanleitung ab Firmware wiffi_wz_37. Korrekturen des Anzeigewerte der Temperatur lassen sich ggf. mit den Expertenparametern (param 4) durchführen.

10. Hinweis für die IR-Bewegungsmelder

Die IR-Bewegungsmelder werden in die dreipoligen Fassungen auf der Platine eingesteckt. Vorher sind beide Einstelltrimmer in der Aufsicht erst mal ganz nach links bis zum Anschlag zu drehen und der Jumper wie im Bild zu stecken.  Mehr dazu im Datenblatt SR501 Das Potentiometer für die Einschaltdauer (im Bild unten das rechte Poti) bleibt immer auf kürzeste Zeit eingestellt, da der WIFFI-WZ die Zeit automatisch auf einen auf der Expertenseite  einstellbaren Wert verlängert. Mit dem  linken Poti kann durch Verdrehung nach rechts die Empfindlichkeit gesteigert werden. Die Empfindlichkeit sollte aber möglichst  weit nach links gedreht sein, weil eine zu hohe Empfindlichkeit, abhängig von Toleranzen des IR-Moduls und möglichen Störeinstrahlungen des  WLAN-Moduls, manchmal zu Fehlauslösungen führen kann. Insgesamt ist die optimale Einstellung der oft sehr „zappeligen “ IR-Bewegungsmeldern immer eine sensible und zeitaufwendige Sache, weil nach jeder Veränderung der Potentiometer die Module einige Zeit brauchen, um sich zu „beruhigen“. Ich kenne leider keine IR-Bewegungsmelder, bei denen das nicht so ähnlich ist !

Update: Störsicherheit der Bewegungsmelder verbessern
Die Bewegungsmelder haben relativ große Toleranzen und neigen manchmal  zu ungewollten Auslösungen. Dazu habe ich viele Versuche gemacht, um diese Module robuster zu gestalten. En Hauptproblem ist die nicht ausreichende Störsicherheit  der Bewegungsmelder auf elektromagnetische Einstrahlungen. Gerade bei geringem Abstand zwischen Bewegungsmelder und WLAN-Sendeantenne können Aussendungen des WLAN-Moduls zu Fehlauslösungen der Bewegungsmelder  führen. Beim WIFFI-wz ist der rechte Bewegungsmelder aufgrund der Nähe zur WLAN-Antenne besonders „gefährdet“. Manchen Bewegungsmeldern macht das gar nichts aus und sie arbeiten völlig normal, andere lösen sporadisch aus. Nach positiven Versuchen mit Kupferfolie oder aluminisiertem Karton (Milchtüte) zwischen dem WeMos und dem rechten Bewegungsmelder habe ich nach praktikableren Lösungen gesucht. Die einfachste Lösung  ist das Einlöten einen 100nf Kondensators zwischen Pin 12 und Pin13 des  ICs auf der Bewegungsmelder-Platine. Siehe dazu das folgende Bild:

bew_melder_aenderung

11. Hinweis für den Luftgütesensor

Der Luftgütesensor MQ135 ist ein hochempfindlicher Sensor für die verschiedensten Schadgase im Wohnraum. Es lohnt sich , die Spezifikation anzuschauen. MQ135 datasheet Das analoge Ausgangssignal wird als Prozent- Zahl zwischen 0 und 100% mit der Systemvariablen wz_co2 angezeigt.  Dieser Prozentwert ist nicht der  CO2-Prozentwert der Luft, sondern nur eine Zahl zur relativen Bewertung der Luftqualität. Ein Wert von 100% soll „reine“ Luft signalisieren, Werte darunter sollen  die Abweichung von diesem Bestwert quantitativ darstellen. Zur Eichung benötigt man Messgase, die man normalerweise natürlich nicht zur Verfügung hat. Ich habe folgenden „Eichvorgang“ gewählt:

> der WIFFI-WZ sollte einige Stunden bereits gelaufen sein, damit eine erste Eichung sinnvoll ist. > die Temperatur sollte bei der Eichung  ungefähr 21°C und die Feuchte etwa 50% sein > dann auf der WIFFI-WZ Webseite den Befehl /?calibrate: eingeben. Dieser Wert wird dann danach als 100% gesetzt. Luftverschlechterung reduziert diesen den %-Wert

Wichtig! Das Modul braucht einige Tage „Einbrennzeit“, bis die Werte einigermaßen stabil sind. Deshalb nach einigen Tagen den Eichvorgang wiederholen. Die aktuelle Einstellung des Sensors ist so, daß er sehr empfindlich ist. Bereits die Ausatmung einiger Menschen im Raum führt zu einer Werteveränderung! Es bleibt der Kreativität des Einzelnen überlassen, wie man die Werte der Luftqualität in der Homematic einsetzt. Denbar sind automatische Warnungen, Fensterlüftungen etc.

12. Hinweis für den Helligkeitssensor

Der verwendete Helligkeitssensor BH1750 ist ein hochgenauer Helligkeitsmesser. Die Anzeige ist direkt Lux. Je nach Positionierung und Ausrichtung des Sensors verändern sich natürlich die Anzeigewerte. Bei Verwendung eines Gehäuses muß man sicher stellen, daß dieser Sensor auch die Helligkeit im Raum „sieht“. Der kleinste Helligkeitswert ist 1 Lux; deutlich kleinere Werte wären wünschenswert, können aber vom Sensor nicht gemessen werden.

13. Hinweis für den Luftdrucksensor

Zur Luftdruckmessung wird der hochgenaue Barometersensor BMP180 eingesetzt. Zur Anzeige des auf den eigenen Standort bezogenen Luftdrucks ist die Höhe über N.N. einzugeben. „Werksseitig“ sind 100m eingestellt. Andere Höhen kann man  auf der WIFFI-WZ Webseite im Expertenmodus einstellen mit dem Befehl  /?param:13:198: Dabei ist die letzte Zahl (bei mir 198m)  die ganzzahlige Höhe des eigenen Wohnortes in Metern. Als alternative Lösung wird auch die Verwendung des neuen Bosch-Moduls BME280 angeboten. Damit wird nicht nur der Luftdruck sondern auch Luftfeuchte und Lufttemperatur mit sehr hoher Genauigkeit gemessen. Die aktuelle Firmware erkennt automatisch, ob der BME280 eingesteckt ist und übernimmt die Temperatur, Feuchte und Luftdruckmessung von diesem Sensor .

14. Befehlsliste des WIFFI-WZ

Mit folgenden Befehlen kann der WIFFI-WZ auf seiner Einstell-Webseite mit der über den Browser eingestellt oder bedient werden.

15. Einstellungen im Expertenmodus

Normalerweise ist im Expertenmodus keine Einstellung notwendig!!!!! Einstellungen sollten auch nur dann vorgenommen werden, wenn man wirklich weiß, was man verändert. Im ungünstigen Fall kann der WIFFI-WZ irreparabel beschädigt werden. Hier ist die Einstellungsseite:

16. Rückstellen in Werkszustand

Manchmal kann es notwendig sein, die im EEPROM abgelegten Daten zu löschen und den WIFFI-WZ in den Auslieferungszustand zu versetzen. Hierfür wird durch 1sec-Drücken des PROG-Tasters zuerst der Hotspot-Modus eingestellt, was durch 1sec- Blinken der roten LED angezeigt wird. Danach hält man den PROG-Taster  solange gedrückt, bis die rote LED dauerhaft leuchtet. Jetzt werden die EEPROM-Daten gelöscht. Läßt man die PROG-Taste wieder los, dann startet WIFFI neu und geht automatisch in den Hotspot-Modus, um so wieder neu an den Router angelernt zu werden. Achtung: nie den PROG- und RESET-Taster gleichzeitig drücken, da das Modul dann in den Programmiermodus geht und u.U. die Firmware beschädigt wird.

17. Update des WIFFI-WZ

1. Voraussetzung:  Ein Update des WIFFI kann ohne Demontage bzw. Geräteöffnung komplett über das WLAN erfolgen. Dabei ist der WIFFI vorher im Heimnetz über WLAN eingeloggt und seine Webseite ist mit der vom Router vergebenen IP-Adresse aufrufbar. Diese individuelle IP-Adresse wird nachfolgend als bezeichnet. Man kann die Webseite des des Wiffi-WZ alternativ auch mit wiffi_wz.local aufrufen.

2. Im Browser folgenden Befehl eingeben: (immer genauestens die Schreibweise beachten !!) /?update: es geht auch wiffi_wz.local/?update: Warten bis der Browser eine Fehlermeldung zeigt (normalerweise nach ca. 20 bis 30sec).

3.Erst jetzt im Browser den Update-Assistenten mit /update aufrufen. (Achtung die jetzt andere Schreibweise beachten !!!!)

4. Danach zeigt der Browser ein einfaches Bild mit zwei Buttons. Mit „Durchsuchen“ den aktuellen Update-File (extension .bin) aus dem ZIP-Update-Archiv auswählen und danach mit Druck auf den Update-Button hochladen. Nach einigen Sekunden kommt ein formloses „ok“, was ein erfolgreiches Update bestätigt. Danach sind alle Daten gelöscht ( auch die WLAN-Zugangsdaten!). Der WIFFI-WZ ist auf den upgedateten Auslieferungszustand zurück gesetzt und wird nun automatisch im Hotspot-Modus mit der festen IP 192.168.4.1 neu gestartet. Dabei blinkt die LED im Hotspot-Modus sehr schnell. ( 2Hz)

5. Mit einem Smartphone oder besser Windows-Laptop kann nun eine gesicherte WLAN-Verbindung mit diesem Hotspot hergestellt werden. Der Hotspot hat den Namen wiffi und das Zugangspasswort ist wiffi1234 Hinweis: – Bei Apple-Produkten kann es beim Einloggen wegen der strikten Sicherheitseinstellungen zu Problemen kommen. Möglichst Windows-Rechner verwenden ! Manchmal kann es notwendig sein, alte wiffi-Zugänge vorher zu löschen!

6. Wenn die Verbindung hergestellt ist, kann mit Browsereingabe der Hotspot-IP 192.168.4.1 die Webseite des WIFFI-WZ aufgerufen werden. Auf dieser Webseite erfolgt dann wie bei der Erstinbetriebnahme die Eingabe der Router- und CCU-Zugangsdaten (WLAN- Netzwerkname, Netzwerkschlüssel/ Passwort, CCU IP-Adresse) mit den Befehlen … 192.168.4.1/?ssid:DeinNetzwerkname: 192.168.4.1/?pwd:DeinPasswort: 192.168.4.1/?ccu:DeineCCU_IP 7.Mit der Browsereingabe 192.168.4.1/?reset: startet abschließend der WIFFI neu. Nach etwa 20sec kann im Browser mit : /? oder wiffi_wz.local die Webseite des WIFFI zur Eingabe weiterer Einstellungen wieder aufgerufen werden.

Hinweis: Ab der Firmwareversion wiffi_wz_60  ist das Update deutlich einfacher über die eigene Update-Webseite des WIFFI durchzuführen !

und hier sind die neuesten Updates zum runterladen:

Zum Update das ZIP-Archiv runterladen und entpacken. Zum Update nur die *.bin-Datei aus dem zip-Archiv hochladen.

16.09.2016:  wiffi_wz_41  viele Detailverbesserungen. Wenn DHT22 verwendet, dann andere Anschlussart beachten (siehe geänderte WIFFI-wz Bauanleitung)

02.11.2016:    wiffi_wz_48  da der abgekündigte Luftdrucksensor BMP180 durch den neuen BMP280 oder BME280 ersetzt wurde,  mußte die Firmware entsprechend angepasst werden :Folgende Sensorkonfigurationen sind nun möglich:  DHT22/BMP180  oder DHT22/BMP280  oder nur  BME280 .

04.12.2016:  wiffi_wz_53  Kleine Fehler behoben: im JSON-Telegramm, Alarm abschaltbar, Messwertübertragung erst 60sec nach Reset

08.01.2017:  wiffi_wz_56  Leerzeichen in WLAN-Zugangsdaten möglich, zusätzliche Berechnung von Tautemperatur und absoluter Feuchte

17.01.2017: wiffi_wz_60  Vereinfachtes Update u.a. mit Beibehaltung der WLAN-Zugangsdaten

03.03.2017:  wiffi_wz_64  DHT22 Treiber verbessert

27.03.2017:  wiffi_wz_69  Anpassung der 8181-Requests an die neue CCU2-Firmware 2.27.2, JSON-Telegramm angepasst

29.03.2017:  wiffi_wz_70  Sonnenstandsberechnung korrigiert

27.04.2017:  wiffi_wz_71 Lösung Deckenmotage integriert, param[34] neu, Komplett-Update notwendig !

28.05.2017:  wiffi_wz_74 Änderungen für die optionale Verwendung des CO2-Sensors MH-Z14

08.09.2017:  wiffi_wz_75 JSON Telegramm korrigiert

Der DHT22 kann wie bisher angeschlossen werden oder aber nach der neuen verbesserten Anschlussart. (siehe geänderte WIFFI-wz Bauanleitung)

18. Integration in IP-Symcon

Viele Homematic-User verwenden IP-Symcon zur erweiterten Visualisierung und Steuerung. Hier im IP-Symcon-Forum werden die Grundlagen für die Einbindung und Verwendung  des WIFFI-wz diskutiert und erläutert. Eine konkrete und  sehr hilfreiche Anwendungsbeschreibung beschreibt auch dieser Artikel hier : WIFFI-WZ Multisensor mit IP-Symcon betreiben.

… und wo kann man den Bausatz bekommen?

Für den Nachbauer  habe ich einige Bausätze zusammengestellt. Diese  können bei mir bezogen werden:  WIFFI-WZ 20 Bausatz Wer vorher einen Blick in die Bauanleitung werfen möchte, bitteschön:   WIFFI-WZ Bauanleitung

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.

Universelles Astro/Zeit-Skript für Rolladen, Lampen …

Universelles Astro/Zeit-Skript für Rolladen, Lampen …

Im Homematic Zeitmodul fehlen eine Reihe wichtiger Zeitfunktionen wie Datumsbereiche, Monate, Wochentage und Kalenderwochen. Aber besonders die Astrofunktion ist unbefriedigend, weil man nur selten genau zum Sonnenaufgang(SA) oder Sonnenuntergang(SU) etwas schalten möchte. Meist benötigt man nämlich Schaltvorgänge vor oder nach diesem Sonnenereignis.

Um diesen Mangel „auszubügeln“ , gibt es in den einschlägigen  Foren eine Vielzahl von mehr oder weniger gelungener Hilfslösungen, die aber meist nur auf spezielle Fragestellungen abgestimmt wurden. Mit diesem universell einsetzbaren Astro/Zeitskript werden verschiedene Systemvariablen berechnet, welche die verschiedenen Zeitinformationen abbilden. Die gewählte Benamung der Systemvariablen erklären selbstredend die Funktion.

Und das geht so:

1. Folgende Systemvariablen anlegen:

Minuten_vor_SA als Zahl , Wertebereich -1000 bis +1000
Minuten_vor_SU als Zahl , Wertebereich -1000 bis +1000
Tageszeit_hh.mm als Zahl in h
Datum_MM.TT als Zahl
Monat als Werteliste Januar;Februar; …
Monatstag als Werteliste 1;2;3; … ;31
Wochennummer als Zahl
Woche_gerade logisch wahr ist gerade , unwahr ist ungerade
Wochentag als Zahl
Jahrestag als Zahl
Jahr als Zahl

2. WebUI Programm anlegen, in dem beispielsweise alle 3min das folgende Astro/Zeit-Skript aufgerufen wird:

astro_skript1
Das Skript dazu verwendet nur eine (!) Skriptvariable, was für eine gute „Skripthygiene“ wichtig ist.

 

!Skript zur Berechnung der Minuten vor SA und SU        !  
!stall.biz  04.04.2016  Dieses Skript verwendet nur eine (!) Skript-Variable     
!folgende Systemvariablen anlegen
!Minuten_vor_SA"    als Zahl , Wertebereich  -1000 bis +1000
!Minuten_vor_SU"    als Zahl , Wertebereich  -1000 bis +1000
!"Tageszeit_hh.mm"  als Zahl  in h
!"Datum_MM.TT"    als Zahl  
!"Monat"    als Werteliste Januar;Februar;  ...  
!"Monatstag"    als Zahl 
!"Wochennummer"    als Zahl  
!"Woche_gerade"    logisch   wahr ist gerade , unwahr ist ungerade
!"Wochentag"    als Zahl  
!"Jahrestag" als Zahl
!"Jahr" als Zahl 
 
real c_zeit =(system.Date("%M").ToFloat()+ (60.0*system.Date("%H").ToFloat())); 
 
if (c_zeit >720.0) { dom.GetObject("Minuten_vor_SA").State(999); 
  c_zeit = system.SunsetTime("%M").ToFloat() + (60.0*system.SunsetTime("%H").ToFloat());
  c_zeit = c_zeit -  (system.Date("%M").ToFloat()+ (60.0*system.Date("%H").ToFloat()));
  dom.GetObject("Minuten_vor_SU").State(c_zeit); 
}
else {dom.GetObject("Minuten_vor_SU").State(999); 
  c_zeit = system.SunriseTime("%M").ToFloat() + (60.0*system.SunriseTime("%H").ToFloat());
  c_zeit = c_zeit - (system.Date("%M").ToFloat()+ (60.0*system.Date("%H").ToFloat()));
  dom.GetObject("Minuten_vor_SA").State(c_zeit); 
}
 
c_zeit = (1.0*system.Date("%H").ToInteger()) +(0.01*system.Date("%M").ToInteger());                      
dom.GetObject("Tageszeit_hh.mm").State(c_zeit);
 
c_zeit  = (0.01 * system.Date("%d").ToInteger()) + system.Date("%m").ToInteger();
dom.GetObject("Datum_MM.TT").State(c_zeit );
 
c_zeit   = system.Date("%Y").ToInteger();
dom.GetObject("Jahr").State(c_zeit);
 
 
c_zeit   = system.Date("%m").ToInteger();
dom.GetObject("Monat").State(c_zeit  -1);
 
c_zeit    = system.Date("%d").ToInteger();
dom.GetObject("Monatstag").State(c_zeit );
 
c_zeit =  system.Date("%V").ToInteger();
dom.GetObject("Wochennummer").State(c_zeit);
 
if ((c_zeit - 2*(c_zeit/2.0)) == 1) {dom.GetObject("Woche_gerade").State(0);} else {dom.GetObject("Woche_gerade").State(1);}
 
c_zeit = system.Date("%u").ToInteger();
dom.GetObject("Wochentag").State( c_zeit);
 
c_zeit = system.Date("%j").ToInteger();
dom.GetObject("Jahrestag").State( c_zeit);

3. Wer CuxD installiert hat, der kann den manchmal instabilen regelmäßigen Zeitaufruf des Astro/Zeit-Skripts mit einem CuxD-Timer realisieren. Wie das geht, ist an verschiedenen Stellen im Homematic-Forum bereits beschrieben, so daß hier auf eine weitere Erklärung verzichtet wird. Das Programm zum regelmässigen Aufruf des Astro/Zeit-Skriptes sieht mit einem CuxD-Timer dann so aus:

astro_skript5
Der Vorteil bei diesem Verfahren ist, daß fast die gesamten Zeitsteuerungen der WebUI-Programme nun über die neuen Astro/Zeit-Systemvariablen erfolgen kann. Und diese Systemvariablen werden nur über einen(!) viel zuverlässigeren CuxD-Timer aktualisiert. Damit wird das gesamte Zeitmanagement deutlich stabiler und zuverlässiger.

4. So wird das Astro/Zeit-Skript eingesetzt
Zum Beispiel eine Rollade so steuern, daß sie morgens 30min vor Sonnenaufgang hoch geht, aber nicht vor 6h45 und abends 45min nach Sonnenuntergang runter fährt,aber nicht später als 22h00.

Das WebUI -Programm dazu ist mit Verwendung der soeben definierten Systemvariablen ganz einfach:

astro_skript4
…und mit der Verwendung der Systemvariablen aus der Astro/Zeitsteuerung sind die WebUI-Programm viel besser lesbar, als mit dem „verkorksten“Zeitmodul!

Einige User hatten das Problem, daß bei dem obigen Programm der Rolladenaktor jedesmal „klickt“, wenn die Systemvariable Minuten_vor_SA alle 2 Minuten aktualisiert wird. Das kann man verhindern mit folgendem geänderten Programm:

rollladen_astro

 

Hier noch einige Erläuterungen zur Astrofunktion:
Da die meisten Steuerungsaufgaben sehr oft mit dem Sonnenaufgang und -untergang verknüpft ist, hat man die sog. Astrofunktion eingeführt. Diese ist aber oft unzureichend, weil man oft lieber einige Minuten vorher oder nachher den Schaltvorgang ausführen möchte. Dazu wurden in dem Astro/Zeit-Skript die zwei Systemvariablen Minuten_vor_SA und Minuten_vor_SU eingeführt. Der Wert dieser Variablen ändert sich über den Tagesverlauf entsprechend dem folgenden Bild:


Die Systemvariable Minuten_vor_SA ist nur von 00h00 bis 12h00 aktiviert und wird im zweiten Tagesabschnitt auf einen Wert von 999 gesetzt.
Bei der Systemvariablen Minuten_vor_SU ist es genau umgekehrt. Diese Definition hat Vorteile bei Anwendung in WebUI -Programmen.

Viel Spaß mit dem neuen „Zeitgefühl“

WIFFI-wz … der Multifunktionssensor nicht nur für´s Wohnzimmer

WIFFI-wz … der Multifunktionssensor nicht nur für´s Wohnzimmer

Der WIFFI … kurz und knapp!

Der WIFFI-wz ist das erste Modul einer Reihe von zukünftig geplanten weiteren Sensor- und Aktor-Modulen, die hauptsächlich zur  Erweiterung  und  Ergänzung der Hausautomation mit der Homematic konzipiert sind.  Die WIFFI´s sind allesamt Funkmodule , die das in nahezu jedem Haushalt vorhandene gesicherte WLAN-Funknetz verwenden, um mit der Homematic-CCU zu kommunizieren.

Der WIFFI-wz bringt  9 (!)  Sensoren und einen Warnmelder unter einen Hut:
– IR-Bewegungsmelder links
– IR-Bewegungsmelder mitte
– IR-Bewegungsmelder rechts
– Temperaturmessung (mit DHT22)
– Luftfeuchtemessung (mit DHT22)
– Luftdruckmessung (mit BMP180) (optional)
– Geräuschmelder mit einstellbarer Empfindlichkeit
– Helligkeitsmessung /Luxmeter  mit BH1750
– Luftgütesensor  (mit MQ135)
– Beeper als akustischer Warnmelder

Und so sieht das Gerätchen im zusammengebauten Zustand aus. Mit einer Stromversorgung über ein einfaches 5v/0.5A-Steckernetzteil sind keine Batterien notwendig. Das macht auch Sinn, weil ja im Wohnraum eh eine Steckdose vorhanden ist und regelmäßiger Batteriewechsel nur nervt!

Platine_wz03_schraegoben

Der WIFFI-wz ist ein Selbstbauprojekt; der Bausatz dafür mit bereits programmierten Chips kann über  meinen Webshop bezogen werden . Ein mitgelieferte bebilderte Bauanleitung macht den Nachbau auch für „Nicht-Nerds“ gut machbar. Lediglich etwas Erfahrung mit Elektronik-Bauteilen und Lötkolben ist notwendig. Die Programmierung des WIFFI  mit den Zugangsdaten für den heimischen WLAN-Router und der IP-Adrtesse der eigene Homematic-CCU erfolgt ganz einfach mit einem Smartphone oder Tablet auf der eigenen Webseite des WIFFI .

Die Vorgeschichte

Eigentlich war dieser Sensor als reiner „Wohnzimmersensor“ konzipiert, aber die Diskussion hier im Homematic-Forum : http://homematic-forum.de/forum/viewtopic.php?f=27&t=21815#p183408 zeigte, daß ein großes Interesse an einem solchen Sensor besteht und  eine universelle Verwendbarkeit in jedem Raum gewissermaßen als „Raumsonde“  für viele Hausautomatisierer sehr interessant ist. Entsprechende geeignete Multifunktionssensoren gibt es zumindest für die Homematic nicht, sondern man müßte die komplexe Multifunktion mit einer Vielzahl von Einzelsensoren darstellen, was nicht nur hohe Kosten bedeutet sondern auch wegen des dann verwendeten „Gemischtwarenladens“ auch sehr unschön aussieht!

So ist unter dem Pseudonym „Wohnzimmersensor“ dieser nachfolgend als WIFFI-wz  bezeichnete Multifunktionssensor entstanden, der die Anforderungen an eine anspruchsvolle intelligente Hausautomation ausgezeichnet erfüllt.

Der WIFFI-wz  … bis zu 9 (!) Sensoren unter einem Dach!

Die Anforderungen an einen Raumsensor sind bestimmt durch die Anforderungen der in diesem Raum wohnenden Menschen an Funktionalität, Komfort und Lebensqualität. Und da spielen Licht, Luft, Geräusche und Bewegungen eine zentrale Rolle. Deshalb wurde die Auswahl der notwendigen Sensoren im Hinblick auf die entsprechenden Zustandsparameter des Wohnraumes vorgenommen. Mit den Eigenschaften der verwendeten Snsoren ergeben sich daraus die Technischen Eigenschaften des WIFFI-wz:

Lufttemperatur, Messung mit DHT22, Technische Details hier: https://www.sparkfun.com/datasheets/Sensors/Temperature/DHT22.pdf

Luftfeuchtigkeit, Messung mit DHT22, Technische Details hier: https://www.sparkfun.com/datasheets/Sensors/Temperature/DHT22.pdf

Luftqualität, Messung mit MQ135, Technische Eigenschaften hier: https://www.olimex.com/Products/Components/Sensors/SNS-MQ135/resources/SNS-MQ135.pdf

Luftdruck, Messung mit BMP180, Technische Eigenschaften hier: https://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf

Helligkeit, Messung mit BH1750,  Datenblatt hier: http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf

Geräusche / Lautstärke:   Messung mit Elektret-Mikrofon und Auswertung mit geeigneter Schaltung

–  3 Bewegungen in drei Raumbereichen : nach vorne, rechts und  links. Bewegungsmelder nach dem PIR-Prinzip, Datenblatt : http://www.mpja.com/download/31227sc.pdf

Insgesamt sind das 9  Sensorsignale, die mehr oder weniger häufig an die Homematic-Zentrale übergeben werden.

Die Übertragung der Sensorsignale  an die Homematic erfolgt ausschließlich drahtlos, natürlich  mit WPA2 abgesichertem WLAN.

Der WIFFI-wz   Nachbau ganz einfach!

Damit der Nachbau auch für den weniger versierten Elektroniker möglich ist, wurde eine einfach zu verlötende Platine entwickelt. Hier sind keine ultrakleinen  SMD-Bauelemente dabei, sondern nur „normale“ bedrahtete Bauelemente und eine ganze Reihe fertiger Module, die nur einzustecken sind. Das Ganze gibt´s als Komplettbausatz mit bereits eingelötetem und programmierten Mikrocontroller ESP8266 -12.  In der mitgelieferten Bauanleitung wird Schritt für Schritt der Zusammenbau erklärt, so daß ein erfolgreicher Nachbau relativ einfach möglich ist.

Folie1

Eine kompakte Basisplatine nimmt alle Komponenten und Sensoren des WIFFI-wz auf. Steuereinheit ist ein hochintegrierter Wifi-Chip ESP8266-12.

Die Basisplatine selbst benötigt nur sehr wenige Standardbauelemente und ist einfach zusammen zu löten. Darüberhinaus werden komplexe Module verwendet, die mit der Basisplatine verlötet oder zusammen gesteckt werden. Die beim WIFFI-wz verwendeten Bauteile und Module zeigt das folgende Bild:
Folie7

 

Mehr Infos zum Selbstbau in der Bauanleitung: WIFFI-wz Bauanleitung

3. Programmierung und Einstellung

Der WIFFI hat schon einen komplett programmierten Mikrocontroller mit WLAN auf dem Board aufgelötet. Eine aufwendige Programmierung wie bei dem Homeduino entfällt. Damit aber der WIFFI mit dem häuslichen Router Kontakt aufnehmen kann, müssen die Router-Zugangsdaten noch  im WIFFI abgelegt werden. Dazu hat der WIFFI die herausragende Eigenschaft, daß er neben der hauptsächlichen Funktion als sog. Client im WLAN zusätzlich auch einen eigenen Hotspot zur Darstellung einer eigenen Einstell-Webseite öffnen kann. Der verwendete ESP8266 Chip ist hier so programmiert, daß bei Drücken des PROG-Tasters auf der Platine, der WIFFI in den Hotspot-Modus umschaltet. Jetzt stellt er nach außen einen eigenen Hotspot mit dem Namen „wiffi“  zur Verfügung. Nach Herstellung der Verbindung mit Passworteingabe kann man auf der  (einfachen) Webseite des WIFFI die wenigen notwendigen Einstellungen vornehmen. Dafür sind keinerlei Programmierkenntnisse notwendig, also alles sehr einfach :))

Die folgenden Schritte zeigen kochrezeptartig das Vorgehen:

a. Reset-Taster drücken. WIFFI-wz piept im Werkszustand einmal etwa 1sec.

b. nach etwa 15s den Progr-Taster ca. 1sec drücken. Es piept noch einmal und die rote LED blinkt . Jetzt ist der Hotspot solange aktiviert, bis mit dem Reset-Taster dieser Zustand beendet wird.

c. Mit dem Smartphone nach einem Hotspot mit dem Namen „wiffi“ suchen und die Verbindung herstellen. Da es eine gesicherte Verbindung ist, muß das Kennwort „wiffi1234“ eingegeben werden. Danach müßte , wenn alles richtig funktioniert, eine gesicherte Verbindung zum „wiffi“ vorhanden sein.

d. Auf dem so eingeloggten Smartphone oder Tablet in die Adresszeile eines Browsers die Webseite des WIFFI aufrufen mit: 192.168.4.1/?

Die Antwort müßte etwa so aussehen wie im folgenden Bild links :

wiffi_webseite
e. Jetzt die notwendigen Eingaben mit der Adresszeile machen, wie im Beispiel im Bild oben rechts.

Dazu gibt es folgende Befehle:

192.168.4.1/?ssid:myssid: „myssid“ ist die SSID des Routers

192.168.4.1/?pwd:mypwd: „mypwd“ ist das Router-Passwor t des Routers

192.168.4.1/?ccu:myccu: „myccu“ ist die feste (!) IP der CCU1 oder CCU2

192.168.4.1/?name:wz: „wz“ ist der Name des verwendeten WIFFIs. Fürs Wohnzimmer natürlich „wz“

Das ist eigentlich schon alles. Nur der Fachmann sollte die weiter unten erläuterten  Befehle verwenden, um besondere individuelle Anforderungen zu erfüllen:

Nach der kompletten Dateneingabe mit dem Reset-Taster den normalen Betrieb des WIFFI beginnen. Nach Reset wird die rote LED und der Buzzer für 1sec Dauer aktiviert. Dann versucht der WIFFI sich in das heimische WLAN einzuloggen. Bei Erfolg entsteht wieder ein 1sec-Signal an LED und Buzzer. Um festzustellen, ob die CCU auch da ist, wird nun die IP-Adresse des WIFFI-wz an die CCU übermittelt. Wenn das auch erfolgreich ist, dann erfolgt wieder eine Bestätigung mit 1sec.-Piepton bzw. LED. Bei normalem erfolgreichen Start des WIFFI entstehen somit 3 Pieptöne/LED-Signale.

Anmerkung: Wenn der WIFFI-wz die Browserbefehle nicht annimmt , dann evtl. einen anderen Browser ausprobieren.

 

Hier noch einige Erläuterungen zum Expertenmodus:

192.168.4.1/?xpert:1: „1“ oder „0“ schaltet den Expertenmodus ein/aus, standardmäßig ist der Expertenmodus ausgeschaltet. Änderungen dieser Einstellungen sind normalerweise nicht notwendig.

192.168.4.1/?param:13:200:  Damit können bestimmte Parameter geändert werden. In diesem Beispiel wird die Höhe des Wohnortes über N.N. für das Barometer auf 200m eingestellt

Das Vorgehen zur Änderung der verfügbaren Parameter ist folgendermaßen:

Zuerst muß mit dem Befehl 192.168.4.1/?xpert:1: der Expertenmodus eingeschaltet sein. Dann ergibt sich im Browser die Anzeige links im nächsten Bild:

Die Bedeutung der Kennwerte soll an diesem Ort nur für einige wenige wichtige Parameter erläutert werden:

  • param 0 :   Haltezeit der Bewegungssensoren in sec
  • param 1 :    Haltezeit des geräuschsensors in sec
  • param 13:   Höhe über N.N. in m

Man sollte die Kennwerte aber nur ändern, wenn man genau weiß, was man tut !!  Normalerweise ist das für den erfolgreichen Betrieb nicht notwendig.

Möglich Probleme beim Einloggen in den Hotspot

Wenn man mehrere WIFFI´s verwendet, dann merkt sich das Tablet oder Smartphone nicht nur die Zugangsdaten sondern auch die MAC-Adresse des Hotspots. Deshalb kann es notwendig sein, vorher die „gemerkten“ wiffi-Zugangsdaten zu löschen und sich neu mit Kennwort anzumelden.

4. Anlernen an die CCU

Das Anlernen des WIFFI-wz an die CCU ist sehr einfach, weil für jedes Sensorsignal nur eine entsprechende Systemvariable angelegt wird. Mit dem von mir gewählten WIFFI-Namen „wz“ ergeben sich folgende 9 Systemvariablen. (Wählt man einen anderen Namen, dann muß „wz“ durch diesen anderen Namen ersetzt werden!)

wz_IP vom Typ „Zeichenkette“
wz_motion_front vom Typ „Logikwert“
wz_motion_left vom Typ „Logikwert“
wz_motion_right vom Typ „Logikwert“
wz_temp vom Typ „Zahl“ mit Maßeinheit „°C“
wz_feuchte vom Typ „Zahl“ mit Maßeinheit „%“
wz_lux vom Typ „Zahl“ mit Maßeinheit „lux“
wz_noise vom Typ „Logikwert“
wz_co2 vom Typ „Zahl“
wz_baro vom Typ „Zahl“

Die Aktualisierung der Systemvariablen erfolgt automatisch, aber nur wenn sich die Messwerte ändern. Dadurch wird der Datenfluss stark reduziert.

5. Rückstellen in Werkszustand

Manchmal kann es notwendig sein, die im EEPROM abgelegten Daten zu löschen und den WIFFI-wz in den Auslieferungszustand zu versetzen. Hierfür wird durch 1sec-Drücken des Prog-Tasters zuerst der Hotspot-Modus eingestellt, was durch schnelles Blinken der roten LED angezeigt wird. Danach hält man den Prog-Taster für etwa 5 sec gedrückt, was mit einem 2sec-Piepser gefolgt von 2 kurzen Pieptönen bestätigt wird. Jetzt sind alle Zugangsdaten gelöscht.

6. Auslösen des Buzzers von der Homematic-CCU

Mit jedem üblichen Browser kann man mit einem Befehl den Buzzer des WIFFI-wz für eine bestimmte Zeit einschalten. Dazu muß man aber die dem WIFFI-wz im Router vergebene IP-Adresse wissen. Bei mir hat der WIFFI-wz eine feste IP-Adresse 192.168.178.65 im Router zugewiesen bekommen. Dementsprechend ist der Buzzer-Befehl:

192.168.178.65/?buzzer:ontime:   „ontime“ ist Einschaltzeit des Buzzer in 0.1sec-Schritten

Da in der CCU auch die aktuelle IP des WIFFI-wz in der Systemvariablen wz_IP abgelegt ist, kann man auch bei dynamischer IP-Adressenvergabe den Buzzer durch Ausführen eines geeigneten HM-Skriptes auslösen. Zum Beispiel so:

beeper_01

und das zugehörige HM-Skript ist:

HM-Skript   
!hiermit wird der WIFFI-Beeper für 0,5 sec eingeschaltet 
string befehl = "/?buzzer:5:";   
string IP = dom.GetObject("wz_IP").Value();  !Holt IP_adresse des WIFFI_wz
var send_data = "http://" + IP  + befehl; !Befehl zusammensetzen
 
WriteLine(send_data);
string stdout; string stderr;           !und Befehl ausgeben
system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);

Natürlich kann man das Skript auch mit CuxD-Befehlen starten; das hat den Vorteil einer stabileren Arbeitsweise. Mehr dazu im Homematic-Forum.

7. Hinweis für die IR-Bewegungsmelder

Die IR-Bewegungsmelder haben relativ große Fertigungsstreuungen. Mache sind sind sehr „zappelig“ und reagieren schon, wenn es auch nicht zu reagieren gibt. Auch die entsprechende kleinste Einstellung der Empfindlichkeit reicht oft nicht aus, diese Sensoren zu beruhigen. Nach etlichen Versuchen mit zusätzlichen Dämpfungskondensatoren ergab sich eine sehr gute Verbesserungslösung durch einfaches Entfernen eines kleinen Kondensators auf der Modulplatine. Wie das geht, kann man auf den folgenden Bildern erkennen:
Folie8

Darüber hinaus ist das Potentiometer für die Einschaltdauer nach links auf kleinsten Wert zu drehen, weil die Einschaltdauer bzw. Nachlaufzeit im WIFFI-wz auf etwa 60sec festgelegt ist. Das Potentiometer für die Empfindlichkeit bzw. Reichweite sollte man zu anfang auf die unempfindlichste Position ganz nach links drehen.

8. Hinweis für den Luftgütesensor

Der Luftgütesensor MQ135 ist ein hochempfindlicher Sensor für die verschiedensten Schadgase im Wohnraum. Es lohnt sich , die Spezifikation anzuschauen. Das analoge Ausgangssignal wird als Zahl zwischen 0 und 1000 mit der Systemvariablen wz_co2 angezeigt. Wichtig! Das Modul braucht einige Tage „Einbrennzeit“, bis die Werte stabil sind. Danach schaut man sich die Werte bei verschiedenen „Luftzuständen“ des Wohnraumes an und legt individuell in entsprechenden WebUI-Programmen fest, was bei Über- oder Unterschreiten bestimmter Messwerte passieren soll.

9. Hinweis für den Helligkeitssensor

Der verwendete Helligkeitssensor BH1750 ist ein hochgenaues Luxmeter. Vom 5-poligen Anschluss wird die Adressleitung nicht verwendet; deshalb das Modul auch nur in die 4-polige Buchsenleiste eingesteckt.

10. Hinweis für den Luftdrucksensor

Zur Luftdruckmessung wird der hochgenaue Barometersensor BMP180 eingesetzt. Dieser Sensor ist optional, da nicht jeder WIFFI-wz so einen Sensor zur Erkennung des Wohnraumzustandes benötigt.

… und wo kann man den Bausatz bekommen?

Für den Anfang habe ich nur einige Bausätze zusammengestellt und die können bei mir bezogen werden: https://www.stall.biz/produkt/wiffi-wz
Der Bausatzpreis ist nicht gerade niedrig, aber alle Sensoren und Module (bis auf das Gehäuse und Netzteil) sind bereits enthalten.
… und weniger als 8€ (!) für einen Sensorkanal sind schon günstig :D :D

Wer einen Blick in die Bauanleitung werfen möchte, bitteschön: Bauanleitung WIFFI-wz

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.

 

Externe Antenne für RaspberryMatic, OCCU, HM-MOD-RPI-PCB

Externe Antenne für RaspberryMatic, OCCU, HM-MOD-RPI-PCB

Weniger Fehlermeldungen und ein stabileres HM-System mit externer Stabantenne

Original haben die Homematic Aufsteckmodule HM-MOD-RPI-PCB nur ein Stückchen Draht als einfache sog Lambda-Viertel-Antenne.  Für funkmäßig günstige Wohnverhältnisse reicht das meistens aus. Aber immer häufiger hat man Wohnungen und Häuser mit viel Beton oder oder Fertighäuser mit eingebauten Dampfsperren aus Alufolie etc. wo die Funkverhältnisse u.U. sehr ungünstig sind . In diesen Fällen kann eine bessere Antennentechnik sehr viele Vorteile bringen bzw. vorhandene Probleme beseitigen. Weniger Fehlermeldungen und  meist deutlich stabilere und robustere Funkverbindungen zwischen den HM-Sensoren/Aktoren und der CCU oder dem Repeater sind Beweise für eine spürbare Verbesserung.

In früheren Threads wurden bereits die Vorteile von verschiedenen Antennenformen ausführlich  erläutert und diskutiert.

> Die 4 Radials Groundplane ist funkmäßig sehr gut (+++), erfordert aber einiges Bastelgeschick und läßt sich wegen der Abmessungen nicht ganz einfach im Raum platzieren.
Groundplane mit 4 Radials und hier im HM-Forum : Groundplane Antenne

Die2 Radials Flachantenne ist funkmäßig gut (++),  ist aber einfacher zu bauen und im Raum ideal hinter Schränken etc. zu platzieren
Flachantenne zum Selbstbau und hier im HM-Forum: http://homematic-forum.de/forum/viewtopic.php?f=31&t=27782&hilit=Flachantenne#p245961

Und jetzt kommt mit der Stabantenne noch eine weitere Alternative dazu:

> Die Stabantenne ist funkmäßig gut(++) , ist bereits fertig und kann entweder direkt am Gehäuse oder abgesetzt im Raum platziert werden

Die Stabantenne  ist  funktechnisch vielleicht nicht ganz so gut wie die vorgenannten Antennenformen, passt  aber optisch besser in die Verhältnisse iin Wohnräumen etc.  Gegenüber dem eingebauten Drahtstummel als Antenne hat diese Stabantenne  in jedem Fall deutliche funktechnische Vorteile  und ist deshalb nicht nur für die CCU1 oder CCU2  sondern auch auch für beliebige drahtlose Sensoren und Aktoren an funktechnisch ungünstigen Einbauorten die erste Wahl.

Was ist das für eine Stabantenne?

Die verwendete Stabantenne sieht zwar ähnlich aus wie die typischen WLAN-Antennenstummel, die hier verwendete Antenne ist aber speziell für die Homematic-Frequenz von 868Mhz ausgelegt; sie ist auch deutlich länger als die normalen WLAN-Stabantennen. Die Antenne hat einen sog. RP-SMA-Male Anschluss mit einem Gelenk, damit man die Stabantenne flexibel verstellen und dadurch ggf.  die Abstrahlung bzw. Empfangscharakteristik optimieren kann. Aufgeschraubt wird die Antenne auf eine RP-SMA-Female Einbaubuchse, welche im Gehäuse über eine Stück hochfexibles und verlustarmes Koaxkabel mit dem Sende/Empfangsmodul in der CCU1/2 oder anderen HM-Modulen kontaktiert wird.

Alle notwendigen Teile kann man im Webshop als Komplettbausatz erwerben.  Je nach den individuellen Funkverhältnissen  ist auch noch ein koaxiales Verlängerungskabel zu empfehlen, um die Antenne ggf. bis zu 3m abgesetzt vom HM-Modul platzieren zu können. Dieses 3m lange Verlängerungskabel kann optional mit der Antenne erworben werden. Das folgende Bild zeigt die Stabantenne mit dem Verlängerungskabel  an einem einfachen Wandhalter aus dem Baumarkt:

stabantenne_11

Wie wird die Antenne am HM-MOD-RPI-PCB angeschlossen?

Für die Herstellung eines Antennenanschlusses ist schon eine gewisse Löterfahrung notwendig, weil das relativ dünne Koaxkabel an die entsprechenden Anschlüsse im HM-Modul angelötet werden muß.  Nachfolgend wird schrittweise das Vorgehen erläutert:

Zuerst die Kabelpeitsche auf eine Länge von etwa 15cm einkürzen:

P1000528

Das Kabelende vorsichtig abisolieren und Mantel und Innenleiter y-förmig spreizen und verzinnen:

peitsche_ende

Am Aufsteckmodul HM-MOD-RPI-PCB den schwarzen Antennenstummel ablöten und den Innenleiter des Koaxkabels stattdessen anlöten. Die Abschirmung wird entsprechend dem folgenden Bild an die Lötlasche des Abschirmgehäuses angelötet. Dabei nicht zu lange löten, damit das Gehäuse nicht überhitzt wird.

P1000531

Im Raspberry-Gehäuse entsprechend dem Bild ein 6mm Loch einbringen und die Buchse der Kabelpeitsche verschrauben.

Wichtig:
Abschließend  mit dem Durchgangsprüfer oder Ohmmeter prüfen, daß Seele und Abschirmung keine Verbindung haben und ob die Seele im SMA-Stecker auch Durchgang mit dem Antennen-Lötpunkt am Sendemodul der CCU hat.

Jetzt die Stabantenne aufschrauben und alles ist gut !

Vergleich vorher/nachher

Natürlich entsteht  immer die Hauptfrage: Was bringt eigentlich die externe Antenne gegenüber der eingebauten Antenne? Allgemein kann man die Frage nur in einem idealen Versuchsumfeld (Freifeld) messen und beantworten. Aber „ideal“ nützt dem Einzelnen gar nichts , weil man die Frage  nur in bezug auf sein individuelles  HM-Umfeld  beantworten kann. Deshalb sollte man vor dem Umbau die Sende- Empfangs-Feldstärken der einzelnen HM-Module messen und dann nach dem Umbau die Messung zum Vergleich wiederholen. Als Meßwerkzeug kann man  dafür auf der CCU die Systemerweiterung „devconfig“ installieren. Damit kann man die Sende- und Empfangsfeldstärken der einzelnen Funkmodule abfragen. Mehr dazu im Homematic-Forum: Stichworte rssi und devconfig.http://homematic-forum.de/forum/viewtopic.php?f=31&t=26624&p=233643&hilit=rssi+devconfig#p233643

Wichtig ist bei der Messung mit „devconfig“ , daß man auch die entsprechenden HM-Module betätigt oder abgefragt hat, damit die ermittelten  Werte auch  mit der neuen Antenne gemessen wurden. Und auch wichtig, daß möglichst der Mittelwert von mehereren HM-Modulen vorher und nachher verglichen wird. Einzelne Messungen bringen wenig, weil die Signale stark streuen.

Viel Erfolg bei der praktischen Umsetzung !

Anmerkung:
Interessenten können den Komplettbausatz für die Stabantenne in meinem Webshop erwerben.

Haftungs- und Sicherheitshinweise

Nur HM-Module mit Spannungsversorgung aus Batterie oder galvanisch getrennten externen Netzteilen umrüsten. Keinesfalls HM-Module mit internem/integriertem Netzteil  oder 230V Netzspannung modifizieren, da über den  Antennenstecker gefährliche Berührungsspannungen entstehen können.

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.

Tipps für die Fehlersuche

Normalerweise ist der Anschluss der Antenne völlig problemlos und in wenigen Minuten erledigt. Wenn dennoch Probleme bleiben, dann können die nachfolgend aufgelisteten Lösungsvorschläge möglicherweise helfen:

  • Die Kabelpeitsche mit der SMA-Buchse muß an die entsprechenden Lötpunkte am Sendemodul angelötet werden. Beim Abisolieren kann durch zu heftiges Ziehen am Innenleiter der Innenstift der SMA-Buchse zurückgezogen werden. Deshalb beim Abisolieren den Innenleiter immer festhalten!
  • Nach dem Anlöten mit einem Ohmmeter prüfen, ob die Verbindung zwischen dem Innenstift der SMA-Buchse und dem Innenleiter-Lötpunkt am HM-Sendemodul vorhanden ist.
  • Mit dem Ohmmeter prüfen, ob der Aussenleiter (Abschirmung)  zwischen dem Gehäuse der SMA-Buchse und dem Abschirmungsanschluss am HM-Sendemodul auch  gute Verbindung hat
  • Mit dem Ohmmeter prüfen,  daß Innenleiter und Aussenleiter keinen Kurzschluss haben.
  • Bei Feldstärkemessungen mit devconfig ist zu berücksichtigen, daß die Zahlen negativ sind. Je kleiner die negativen Zahlen sind, umso besser! Weiterhin sind die angezeigten Werte vom letzten Datenverkehr und der kann u.U. sehr alt sein! Deshalb die für die Messung verwendeten Aktoren unbedingt manuell oder per Programm vor der Messung betätigen.
  • Feldstärkemessungen müssen mit mehreren Aktoren erfolgen und ein Mittelwert gebildet werden, weil die „chaotischen“ Wellenausbreitungen und Interferenzen im Haus an manchen Stellen zu Feldstärkeverberbesserungen aber auch zu Felstärkeminderungen führen können.
  • Der richtige Standort der Antenne ist von zentraler Bedeutung für gute Funkverbindungen im Haus. Leider kann kein Rezept dafür gegeben werden, weil im Haus eben durch Betondecken, Wände und aluminisierte Dampfsperren etc. eine völlig „chaotische“ Wellenausbreitung erfolgt. Antennen mit hoher Richtwirkung bzw. Gewinn sind deshalb im Haus völlig kontraproduktiv! Also Probieren und mit Verstand und Glück den richtigen Sendestandort finden.

 

Externe Stabantenne für viele HM-Funkmodule

Externe Stabantenne für viele HM-Funkmodule

Weniger Fehlermeldungen und ein stabileres HM-System mit externer Stabantenne

Original haben die drahtlosen HM-Module im Gehäuse nur ein Stückchen Draht als einfache sog Lambda-Viertel-Antenne.  Für funkmäßig günstige Wohnverhältnisse reicht das meistens aus. Aber immer häufiger hat man Wohnungen und Häuser mit viel Beton oder oder Fertighäuser mit eingebauten Dampfsperren aus Alufolie etc. wo die Funkverhältnisse u.U. sehr ungünstig sind . In diesen Fällen kann eine bessere Antennentechnik sehr viele Vorteile bringen bzw. vorhandene Probleme beseitigen. Weniger Fehlermeldungen und  meist deutlich stabilere und robustere Funkverbindungen zwischen den HM-Sensoren/Aktoren und der CCU oder dem Repeater sind Beweise für eine spürbare Verbesserung.

In früheren Threads wurden bereits die Vorteile von verschiedenen Antennenformen ausführlich  erläutert und diskutiert.

> Die 4 Radials Groundplane ist funkmäßig sehr gut (+++), erfordert aber einiges Bastelgeschick und läßt sich wegen der Abmessungen nicht ganz einfach im Raum platzieren.
Groundplane mit 4 Radials und hier im HM-Forum : Groundplane Antenne

Die2 Radials Flachantenne ist funkmäßig gut (++),  ist aber einfacher zu bauen und im Raum ideal hinter Schränken etc. zu platzieren
Flachantenne zum Selbstbau und hier im HM-Forum: http://homematic-forum.de/forum/viewtopic.php?f=31&t=27782&hilit=Flachantenne#p245961

Und jetzt kommt mit der Stabantenne noch eine weitere Alternative dazu:

> Die Stabantenne ist funkmäßig gut(++) , ist bereits fertig und kann entweder direkt am Gehäuse oder abgesetzt im Raum platziert werden

Die Stabantenne  ist  funktechnisch vielleicht nicht ganz so gut wie die vorgenannten Antennenformen, passt  aber optisch besser in die Verhältnisse iin Wohnräumen etc.  Gegenüber dem eingebauten Drahtstummel als Antenne hat diese Stabantenne  in jedem Fall deutliche funktechnische Vorteile  und ist deshalb nicht nur für die CCU1 oder CCU2  sondern auch auch für beliebige drahtlose Sensoren und Aktoren an funktechnisch ungünstigen Einbauorten die erste Wahl.

Was ist das für eine Stabantenne?

Die verwendete Stabantenne sieht zwar ähnlich aus wie die typischen WLAN-Antennenstummel, die hier verwendete Antenne ist aber speziell für die Homematic-Frequenz von 868Mhz ausgelegt; sie ist auch deutlich länger als die normalen WLAN-Stabantennen. Die Antenne hat einen sog. RP-SMA-Male Anschluss mit einem Gelenk, damit man die Stabantenne flexibel verstellen und dadurch ggf.  die Abstrahlung bzw. Empfangscharakteristik optimieren kann. Aufgeschraubt wird die Antenne auf eine RP-SMA-Female Einbaubuchse, welche im Gehäuse über eine Stück hochfexibles und verlustarmes Koaxkabel mit dem Sende/Empfangsmodul in der CCU1/2 oder anderen HM-Modulen kontaktiert wird.

Alle notwendigen Teile kann man im Webshop als Komplettbausatz erwerben.  Je nach den individuellen Funkverhältnissen  ist auch noch ein koaxiales Verlängerungskabel zu empfehlen, um die Antenne ggf. bis zu 3m abgesetzt vom HM-Modul platzieren zu können. Dieses 3m lange Verlängerungskabel kann optional mit der Antenne erworben werden. Das folgende Bild zeigt die Stabantenne mit dem Verlängerungskabel  an einem einfachen Wandhalter aus dem Baumarkt:

stabantenne_11

 

Wie wird die Antenne am HM-Modul angeschlossen?

Für die Herstellung eines Antennenanschlusses ist schon eine gewisse Löterfahrung notwendig, weil das relativ dünne Koaxkabel an die entsprechenden Anschlüsse im HM-Modul angelötet werden muß.  Am Beispiel der CCU2 wird nachfolgend schrittweise das Vorgehen erläutert:

Öffnen des CCU2-Gehäuses mit einem  Vielzahnschraubendreher, insgesamt 4 Schrauben:

Alte Antenne bzw. Drahtstück ablöten. (ist im Bild schon erfolgt!)

Folie2

Hier ist der vergrößerte Antennenanschluß zu sehen. (allerdings etwas „verbraten“ wegen der vielen Versuche)

Jetzt Koax-Anschlusskabel abisolieren:

…Abschirmung und Seele verzinnen und anlöten an den Antennenanschluß:

Folie7

 

… und die Koaxbuchse ins Gehäuse einschrauben. Dafür vorher eine 6mm-Bohrung in das Gehäuse einbringen:

Folie6

Wichtig:
Vor dem Zusammenschrauben mit dem Durchgangsprüfer oder Ohmmeter prüfen, daß Seele und Abschirmung keine Verbindung haben und ob die Seele im SMA-Stecker auch Durchgang mit dem Antennen-Lötpunkt am Sendemodul der CCU hat.

Vergleich vorher/nachher

Natürlich entsteht  immer die Hauptfrage: Was bringt eigentlich die externe Antenne gegenüber der eingebauten Antenne? Allgemein kann man die Frage nur in einem idealen Versuchsumfeld (Freifeld) messen und beantworten. Aber „ideal“ nützt dem Einzelnen gar nichts , weil man die Frage  nur in bezug auf sein individuelles  HM-Umfeld  beantworten kann. Deshalb sollte man vor dem Umbau die Sende- Empfangs-Feldstärken der einzelnen HM-Module messen und dann nach dem Umbau die Messung zum Vergleich wiederholen. Als Meßwerkzeug kann man  dafür auf der CCU die Systemerweiterung „devconfig“ installieren. Damit kann man die Sende- und Empfangsfeldstärken der einzelnen Funkmodule abfragen. Mehr dazu im Homematic-Forum: Stichworte rssi und devconfig.http://homematic-forum.de/forum/viewtopic.php?f=31&t=26624&p=233643&hilit=rssi+devconfig#p233643

Wichtig ist bei der Messung mit „devconfig“ , daß man auch die entsprechenden HM-Module betätigt oder abgefragt hat, damit die ermittelten  Werte auch  mit der neuen Antenne gemessen wurden. Und auch wichtig, daß möglichst der Mittelwert von mehereren HM-Modulen vorher und nachher verglichen wird. Einzelne Messungen bringen wenig, weil die Signale stark streuen.

Viel Erfolg bei der praktischen Umsetzung !

Anmerkung:
Interessenten können den Komplettbausatz für die Stabantenne in meinem Webshop erwerben.

Haftungs- und Sicherheitshinweise

Nur HM-Module mit Spannungsversorgung aus Batterie oder galvanisch getrennten externen Netzteilen umrüsten. Keinesfalls HM-Module mit internem/integriertem  Netzteil oder 230V Netzspannung modifizieren, da über den  Antennensteckers gefährliche Berührungsspannungen entstehen können.

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.

Tipps für die Fehlersuche

Normalerweise ist der Anschluss der Antenne völlig problemlos und in wenigen Minuten erledigt. Wenn dennoch Probleme bleiben, dann können die nachfolgend aufgelisteten Lösungsvorschläge möglicherweise helfen:

  • Die Kabelpeitsche mit der SMA-Buchse muß an die entsprechenden Lötpunkte am Sendemodul angelötet werden. Beim Abisolieren kann durch zu heftiges Ziehen am Innenleiter der Innenstift der SMA-Buchse zurückgezogen werden. Deshalb beim Abisolieren den Innenleiter immer festhalten!
  • Nach dem Anlöten mit einem Ohmmeter prüfen, ob die Verbindung zwischen dem Innenstift der SMA-Buchse und dem Innenleiter-Lötpunkt am HM-Sendemodul vorhanden ist.
  • Mit dem Ohmmeter prüfen, ob der Aussenleiter (Abschirmung)  zwischen dem Gehäuse der SMA-Buchse und dem Abschirmungsanschluss am HM-Sendemodul auch  gute Verbindung hat
  • Mit dem Ohmmeter prüfen,  daß Innenleiter und Aussenleiter keinen Kurzschluss haben.
  • Bei Feldstärkemessungen mit devconfig ist zu berücksichtigen, daß die Zahlen negativ sind. Je kleiner die negativen Zahlen sind, umso besser! Weiterhin sind die angezeigten Werte vom letzten Datenverkehr und der kann u.U. sehr alt sein! Deshalb die für die Messung verwendeten Aktoren unbedingt manuell oder per Programm vor der Messung betätigen.
  • Feldstärkemessungen müssen mit mehreren Aktoren erfolgen und ein Mittelwert gebildet werden, weil die „chaotischen“ Wellenausbreitungen und Interferenzen im Haus an manchen Stellen zu Feldstärkeverberbesserungen aber auch zu Felstärkeminderungen führen können.
  • Der richtige Standort der Antenne ist von zentraler Bedeutung für gute Funkverbindungen im Haus. Leider kann kein Rezept dafür gegeben werden, weil im Haus eben durch Betondecken, Wände und aluminisierte Dampfsperren etc. eine völlig „chaotische“ Wellenausbreitung erfolgt. Antennen mit hoher Richtwirkung bzw. Gewinn sind deshalb im Haus völlig kontraproduktiv! Also Probieren und mit Verstand und Glück den richtigen Sendestandort finden.

Haftungs- und Sicherheitshinweise

Durch diese Modifikationen verliert das Gerät ggf. die herstellerseitig zugesicherte gesetzliche Konformität. Bitte informieren Sie sich über die rechtlichen Konsequenzen.
Ich übernehme natürlich keinerlei Gewähr oder Haftung beim Nachbau.

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.

 

 

Externe Flachantenne für die Homematic und Vergleich mit anderen Antennen

Externe Flachantenne für die Homematic und Vergleich mit anderen Antennen

Warum überhaupt eine externe Antenne ?

Als Funkamateur hat man vielleicht ein anderes Verhältnis zur Hochfrequenz. Aber jeder Anfänger lernt als Erstes, daß die Antenne der beste Hochfrequenzverstärker ist. Die Antenne ist einfach das A und O einer Sende- und Empfangsanlage, man kann diesen Satz nicht genug betonen!

Die Homematic ist auch eine Sende- und Empfangsanlage , die auf 868Mhz arbeitet. Deshalb ist auch hier die Notwendigkeit einer guten Antenne die Vorrausetzung für einen stabilen  und störsicheren Sende- und Empfangsbetrieb. Allerdings wenn man in die geöffneten HM-Funkmodule reinschaut  und den dort als Antenne fungierenden Drahtstummel sieht,  dann weiß man sofort, welches Verbesserungspotential mit einer „richtigen“ externen Antenne möglich ist.

Natürlich lohnt eine externe Antenne nur dann, wenn man Verbindungsprobleme innerhalb des Homematic-Netzes hat. Haben die Module mehr oder weniger Sichtverbindung, dann muß man sich um eine Verbesserung der Antenne sicher nicht kümmern. Aber beispielsweise in einem  typischen 1 1/2-stöckigen Haus mit Keller , Erdgeschoss und Obergeschoss haben wir im ungünstigen Fall zwei Betondecken zwischen den HM-Kommunikationspartnern. Das kann schon zuviel sein, um einen störsicheren und zuverlässigen Betrieb sicher zu stellen.

Auf dieser Webseite wurden schon entsprechende Bauvorschläge veröffentlicht, wie man an der CCU1 , der CCU2 oder am Konfigurationsadapter einen Anschluss für eine externe Antenne herstellt und wie man sich im Selbstbau eine externe sog. Groundplane Antenne herstellt.

externe Antenne für die CCU1

externe Antenne für die CCU2

externe Antenne für den LAN Konfigurationsadapter

Warum eine Flachantenne ?

Die bisher sehr erfolgreich verwendete Antenne ist eine sog. Groundplane Antenne, die zwar klein ist aber doch aufgrund der räumlichen Antennenform nicht hinter dem Schrank oder  der Kommode unsichtbar versteckt werden kann. Deshalb kam der Wunsch nach einer flachen Antenne auf, die einfacher an einem geeigneten Ort platziert werden kann. Bei den sehr guten Funkeigenschaften der Groundplane habe ich versucht , auch bei der Flachantenne bei dem Konzept zu bleiben. Man könnte nämlich statt der vier räumlichen Radials auch nur zwei Radials verwenden , die in einer Ebene (Flachantenne) liegen. Die Berechnungen zeigen, daß dies sehr gut möglich ist und trotzdem nahezu eine Rundstrahlcharakteristik erreichbar ist (siehe folgendes Bild).

Die Maße der so berechnete Groundplane sind :

  • Vertikalstrahlerlänge  79,8mm
  • 2 Radials (45°) mit 82,0 mm Länge

Konzept und Selbstbau

Die praktische Umsetzung sollte auch mit wenig Bastelerfahrung möglich sein. Deshalb wurde eine Platine als Strahler konzipiert, an die einfach die Radials aufgelötet werden. Das folgende Bild sagt mehr als viele Worte:

hm_antenne_2

Die Radials sind Messingröhrchen mit 2mm Durchmesser aus dem Baumarkt. Sie sind auf eine Länge von 80mm abzuschneiden und wie auf dem Bild aufzulöten. Durch die Platine bekommt das Gebilde eine ausreichende Haltbarkeit.

Als Anschluss verwendet man typisches dünnes und biegsames 50-Ohm WLAN-Antennenkabel mit den gebräuchlichen SMA-Steckern.  Aber Achtung : SMA Stecker gibt es als Male und Female und für die innere Verbindung auch als Male- und Female-Ausführung. Es gibt also insgesamt 4 verschiedene Typen von SMA Steckern/Buchsen !! Also genau hinschauen, sonst kauft man die falschen Anschlüsse.  Weitere Fragen zum Anschluß der Antenne beantworten sicher die o.a. Artikel bzw. Links.

Ganz einfach ist natürlich mein Komplettbausatz, bei dem alle Teile schon dabei sind. Komplettbausatz Flachantenne

Wichtige Information für den Komplettbausatz: 
Bei dem mitgelieferten Koaxkabel darf beim Abisolieren des Innenleiters nicht zu heftig an dem Innenleiter gezogen werden, weil sonst im „männlichen“ Stecker der Innenstift nach hinten gezogen wird. Danach ist dann kein Kontakt mehr vorhanden , wenn man beide Stecker zusammenschraubt.
Sicherheitshalber am Schluß mit dem Ohmmeter prüfen, ob der Innenleiter durchgehend vom Antennenanschluss in der CCU  bis zum Mittelstrahler der Antenne auch  Durchgang hat. Zusätzlich sollte man mit dem Ohmmeter prüfen, daß dieser Innenleiter keinen Kurzschluß zur Kabelabschirmung hat >> der Widerstand zwischen Innenleiter und Abschirmung muß hochohmig sein!

hm_antenne_3

Für den weniger erfahrenen „Löter“ hier noch ein Bild, wie man die Koaxkabel mit einem scharfen Messer ablängt und verzinnt. Aufpassen, daß man mit dem Messer nur die Isolierung des Innenleiters  und nicht die Kupferadern des Innenleiters anschneidet. Es reicht wie im Bild oben,  die Kabelabschirmung nur an einer Seite zu verlöten, weil die Radials über die Platine miteinander verbunden sind.

antenne_kabel


Anschluß an die CCU mit/ohne Ringkern ?

Zum Anschluß der Antenne muß man natürlich das jeweilige Gerät öffnen und verliert dementsprechend u.U. die Garantie. Man sollte deshalb schon mit dem Lötkolben umgehen können und etwas von Elektronik verstehen. In verschiedenen Artikeln hierzu (siehe o.a. Links) wird Schritt für Schritt das Vorgehen erklärt, so daß eigentlich jeder „Eingriff“ erfolgreich sein sollte 😉

Bisher habe ich immer einen Ringkern zwischen CCU-Antennenanschluss und Lötanschluss auf dem CCU-Board empfohlen. Dies ist sicher der richtige Weg, wenn unklar ist, inwieweit die Platine beim „Abstrahlen“ ungewollt mitspielt.  Deshalb habe ich zu diesem Thema verschiedene Versuche mit und ohne Ringkern unternommen.

Das Ergebnis
ist eindeutig:
Bei einer externen Antenne für die Homematic-Module ist ein Ringkern nicht notwendig bzw. ein Ringkern bringt keine meßtechnisch wahrnehmbaren Vorteile!

Wie lang darf die Antennenleitung sein ?

Die Frage nach der maximalen Länge der Antennenleitung kann man eigentlich nur so beantworten, daß die Leitung zwischen Antenne und CCU so kurz wie möglich sein sollte. Jeder Meter mehr bringt zusätzlich Dämpfung und damit Verschlechterung der Performance.

Die Dämpfung hängt entscheidend von der Kabelqualität ab. Da gibt es Riesenunterschiede.

Wir vergleichen mal 4 Koaxkabel:

> RG174 > Durchmesser: 2,8 mm, > Dämpfung bei 1000Mhz: 1,05dB/m
> RG316 > Durchmesser: 2,5 mm, > Dämpfung bei 1000Mhz: 0.87dB/m
> SS405 > Durchmesser: 2,7 mm, > Dämpfung bei 1000Mhz: 0,40dB/m
> RG213 > Durchmesser: 10,0 (!) mm, > Dämpfung bei 1000Mhz: 0,24dB/m

Gehen wir mal davon aus, daß eine externe Antenne am gleichen Standort wie die CCU etwa 3dB Gewinn bringt.
Dieser Gewinn wird aufgebraucht durch eine mehr oder weniger lange Leitung.
Für 3dB Leitungsverlust darf die Leitungslänge bei den verschiedenen Kabelsorten maximal sein:

> RG 174 : 2,85m
> RG316 : 3,45m
> SS405 : 7,50m
> RG216 : 12,50m

Also keine Frage: Man sollte das RG216 verwenden! Aber wer verlegt im Wohnraum mal eben ein 10mm dickes Kabel,  ganz abgesehen von dem dicken Antennenstecker an der CCU.

Also bei einem langen Antennenkabel ist ein hochwertiges Koaxkabel ein Muß, bei einem kurzen Antennekabel (<3m) kann man auch eine ungünstigere aber preisgünstige Kabelqualität ertragen. Nochmal:

Genau überlegen, wohin kommt die Antenne und wohin die CCU, daß einerseits die Antenne möglichst günsdz´tige Abstarhlbedingungen hat und andererseits das Antennekabel so kurz wie möglich ist!!

Zum Thema Koaxkabel gibt´s auf dieser Webseite mehr Informationen:
http://www.koax24.de/koaxialkabel/uebersicht-50-o/24-32-mm-gr2/rg174-au.html

Vergleich mit anderen Antennen

Natürlich entsteht  immer die Hauptfrage: Was bringt eigentlich die externe Antenne gegenüber der eingebauten Antenne? Allgemein kann man die Frage nur in einem idealen Versuchsumfeld (Freifeld) messen und beantworten. Aber „ideal“ nützt dem Einzelnen gar nichts , weil jeder die Frage möglichst in bezug auf sein individuelles  HM-Umfeld  beantwortet haben möchte. Deshalb habe ich mit meiner eigenen wahrscheinlich typischen HM-Installation die Leistungsfähigkeit verschiedener Antennen vermessen.  Als Meßwerkzeug wurde auf der CCU die Systemerweiterung „devconfig“ installiert. Damit kann man die Sende- und Empfangsfeldstärken der einzelnen Funkmodule abfragen. Mehr dazu im Homematic-Forum: Stichworte rssi und devconfig.

http://homematic-forum.de/forum/viewtopic.php?f=31&t=26624&p=233643&hilit=rssi+devconfig#p233643

Gemessen habe ich vier verschiedene Antennen :

  • die Original CCU2-Antenne
  • meine „alte“ Groundplane mit 4 Radials
  • eine käufliche 868Mhz-Stabantenne aus China
  • die „neue“ Flachantenne aus diesem Beitrag

Gemessen wurde an einem sehr ungünstigen Aufstellort im Keller und an einem günstigen Aufstellort im Erdgeschoss meines 1 1/2 stöckigen Einfamilienhauses. Gemessen wurde mit 30 verschiedenen HM-Modulen , die naturgemäß im ganzen Haus verteilt sind. Die gemessenen Werte sind immer Mittelwerte aus den Signalstärken der 30 Module.

Hier die Ergebnisse:

Bei der Interpretation der Vergleichswerte ist wichtig zu wissen, daß kleine negative dBm-Werte besser sind. Also je länger der Balken im Bild umso besser! Die Werte für den Aufstellort Keller (blaue Balken)  sind naturgemäß sehr schlecht. Hier bringt eine externe Antenne besonders viel. Für den günstigen Aufstellort im Erdgeschoss sind die Werte naturgemäß deutlich besser. Im Mittel  ist die Empfangsleistung im Keller um 8,6dBm schlechter. Das enspricht einem Faktor von 7,2 !

Bei dem günstigen Aufstellort der Antennen im Erdgeschoss ist der Unterschied der verschiedenen Antennenformen nicht so groß.  Aber immerhin sind zwischen CCU-Antenne und den anderen Antennen so um die 3dB Unterschied auzumachen, was einer doppelten Empfangsleistung entspricht.

Nicht jeder ist mit dem logarithmischen Maß Dezibel vertraut, deshalb im folgenden Bild die Unterschiede der Signalleistung als Faktoren:

So kann sich jeder ein Bild machen, was meßtechnisch eine externe Antenne bringt. Subjektiv möchte ich anmerken, daß ich auf eine externe Antenne nicht mehr verzichten möchte, weil damit in meiner individuellen Hausumgebung erst ein stabiler und zuverlässiger Betrieb möglich war. Und die vielen Posts zu diesem Thema sprechen eine beredte Sprache !

 

Für schwierige Bedingungen: 2 Antennen an der CCU

Obwohl die beschriebene Antenne sehr viel bringt kann es unter schwierigen Ausbreitungsbedingungen immer noch Empfangsprobleme geben. Ursache sind meist  dicke stahlbewehrte Betondecken, die eine Ausbreitung der Funkwellen über mehrere Stockwerke stark dämpfen. Repeater sind können zwar eine Lösung sein,  jedoch verbrauchen sie dauernd Strom, kosten Geld und müssen entsprechend administriert werden.  Eine zweite Antenne kann hier eine gute und einfache Lösung sein.

Dazu müssen aber die zwei Antennen in geeigneter Weise an die CCU gekoppelt werden. Eine einfache Parallelschaltung funktioniert nicht, weil die Parallelschaltung von zwei 50 Ohm Antennen einen Wellenwiderstand von 25 Ohm ergibt und das würde an dem 50 Ohm Antennenausgang der CCU zu einer erheblichen Fehlanpassung und damit Leistungseinbuße führen. Der Lösungsansatz ist einfach und sehr kostengünstig. Mit einem Stück 75 Ohm-Sat-Kabel kann man leicht einen sog. Viertelwellen-Transformator aufbauen, der den Wellenwiderstand der  parallel geschalteten zwei Antennen (25 Ohm) auf wieder 50 Ohm hochtransformiert.  Das folgende Bild zeigt die Schaltung dazu:Folie10

Damit die zwei Sat-Kabel-Leitungsstücke für die praktische Realisierung nicht zu kurz sind, wurde eine Länge von 3/4 Lambda dewählt. Damit ergibt sich als Länge ein Wert von 21,2cm, was für den Aufbau einfacher und  praktikabel ist.

Die beiden Antennen können nun an exponierter Stelle in jeder Hausetage positioniert werden, so daß auf diese Weise auch sehr schwierige Ausbreitungsbedingungen eigentlich kein Problem mehr sein dürften.

Viel Erfolg bei der praktischen Umsetzung !

 

Anmerkung:
Interessenten können den Komplettbausatz für die Flachantenne in meinem Webshop erwerben. https://www.stall.biz/produkt/komplettbausatz-fuer-ccu-flachantenne

Haftungs- und Sicherheitshinweise

Nur HM-Module mit Spannungsversorgung aus Batterie oder galvanisch getrennten externen Netzteilen umrüsten. Keinesfalls HM-Module mit internem/integriertem  Netzteil oder 230V Netzspannung modifizieren, da über den  Antennensteckers gefährliche Berührungsspannungen entstehen können.

Beim Nachbau müssen natürlich alle wichtigen einschlägigen Sicherheitsvorschriften für den Umgang mit gefährlichen Spannungen  eingehalten werden. Fundierte theoretische und praktische Fachkenntnisse der Elektrotechnik und für den Umgang mit gefährlichen Spannungen sind unverzichtbar!! Durch eine unsachgemäße Installation gefährden Sie ihr Leben und das Leben ihrer Mitmenschen! Darüberhinaus riskieren Sie erhebliche Sachschäden , welche durch Brand etc. hervorgerufen werden können ! Für alle Personen- und Sachschäden durch falsche Installation etc. ist nicht der Hersteller sondern nur der Betreiber verantwortlich. Ich verweise hier unbedingt auf  die  „Sicherheitshinweise und Haftungsausschluss„-Seite dieses Blogs.

 

 

 

Für schwierige Funkbedingungen: 2 externe Antennen an einer CCU

Für schwierige Funkbedingungen: 2 externe Antennen an einer CCU

Daß man mit einer externen Antenne an der CCU oder anderen HM-Modulen die Stabilität des heimischen Funknetzes erheblich verbessern kann, haben bereits viele Homematiker praktisch ausprobiert. Die folgenden Links geben dazu mehr Informationen:
https://www.stall.biz/project/externe-flachantenne-fuer-die-homematic-und-vergleich-mit-anderen-loesungen
https://www.stall.biz/project/externe-antenne-an-ccu2-fur-ein-stabiles-hm-funknetz
https://www.stall.biz/project/externe-antenne-fur-den-lan-konfigurations-adapter

Obwohl die beschriebene externe Antenne sehr viel bringt kann es unter schwierigen Ausbreitungsbedingungen immer noch Empfangsprobleme geben. Ursache sind meist dicke stahlbewehrte Betondecken, die eine Ausbreitung der Funkwellen über mehrere Stockwerke stark dämpfen. Repeater sind können zwar eine Lösung sein, jedoch verbrauchen sie dauernd Strom, kosten Geld und müssen entsprechend administriert werden. Eine zweite Antenne kann hier eine gute und einfache Lösung sein.Dazu müssen aber die zwei Antennen in geeigneter Weise an die CCU gekoppelt werden. Eine einfache Parallelschaltung funktioniert nicht, weil die Parallelschaltung von zwei 50 Ohm Antennen einen Wellenwiderstand von 25 Ohm ergibt und das würde an dem 50 Ohm Antennenausgang der CCU zu einer erheblichen Fehlanpassung und damit Leistungseinbuße führen. Der Lösungsansatz ist einfach und sehr kostengünstig. Mit einem Stück 75 Ohm-Sat-Kabel kann man leicht einen sog. Viertelwellen-Transformator aufbauen, der den Wellenwiderstand der parallel geschalteten zwei Antennen (25 Ohm) auf wieder 50 Ohm hochtransformiert. Das folgende Bild zeigt die Schaltung dazu:

Damit die zwei Sat-Kabel-Leitungsstücke für die praktische Realisierung nicht zu kurz sind, wurde statt 1/4 Lambdaeine Länge von 3/4 Lambda gewählt. Damit ergibt sich als Länge ein Wert von 21,2cm, was für den Aufbau einfacher und praktikabel ist.

Die beiden Antennen können nun an exponierter Stelle in jeder Hausetage positioniert werden, so daß auf diese Weise auch sehr schwierige Ausbreitungsbedingungen eigentlich kein Problem mehr sein dürften.

Viel Erfolg bei der praktischen Umsetzung !

ESP8266 mit externer WLAN-Antenne für WIFFI, WeMos …

ESP8266 mit externer WLAN-Antenne für WIFFI, WeMos …

1 Ausgangssituation

Für viele Projekte in der Hausautomation werden die sehr leistungsfähigen und preisgünstigen Mikrocontroller der ESP8266 -Reihe verwendet. Dabei gibt es Versionen mit verschiedenem Layout und  unterschiedlicher Anzahl von Ports. Sie werden mit dem ergänzenden Kürzel ESP-01  bis ESP-12 gekennzeichnet. Fast alle Versionen haben eine gedruckte Antenne auf der Modulplatine, lediglich die Versionen ESP-02 , ESP-05  und ESP07 haben eine Pigtail-Buchse als  externen WLAN-Antennenanschluss.  Allerdings haben gerade diese Versionen nur wenige Ports und sind auch nicht so verbreitet wie zum Beispiel die „Vollversion“ ESP-12. Dieser letztgenannte Typ wird in sehr kostengunstigen Lösungen für die Arduino-Entwicklungsumgebung eingesetzt. Kleine fertige Mikrocontroller mit dem ESP8266 ESP-12 heißen Wemos, Nodemcu usw.

2 Warum eine externe Antenne ?

Ganz einfach, weil gerade im Haus wegen der Wände und Betondecken die Funkabdeckung mit dem hauseigenen Router manchmal zu schwach ist! Man kann zur Problemlösung zwar Repeater o.ä. einsetzen, aber mit einer verbesserten Antenne ist meistens eine deutlich bessere Verbindung sicher gestellt. Und das ohne  stromfressende Zusatzgeräte! Dazu kommt, daß die Platinenantennen der Module nicht so überragende Sende- Empfangseigenschaften haben können, einfach weil sie einfach räumlich sehr klein sind. Mit einer größeren externen Antenne ist da einiges an Reichweite zu holen.

3 Der Umbau

So ganz einfach ist der Umbau nicht, weil die zu verändernden Teile ausgesprochen klein sind.  Auch muß eine geeignetes Equipment vorhanden sein:
>> möglichst eine Leuchtlupe,
>> Lötstation mit feiner Lötspitze ,
>> Cuttermesser o.ä.

Und natürlich benötigt man zum Umbau eine kurze Koaxleitung mit SMA-Einbaubuchse, im folgenden nur Kabelpeitsche genannt . An die SMA-Einbaubuchse kann dann eine WLAN-Antenne angeschraubt werden. Wichtig ist, daß Antennenanschluss und Kabelpeitsche auch den zueinander passenden SMA-Anschluss haben.

esp8266_antenne7

Wichtig: Es gibt zwei SMA-Steckerfamilien: die einfachen SMA-Steckverbinder als Male und Female  und die sog. RP-SMA-Steckverbinder auch als Male und Female -Ausführung. Man muß darauf achten, daß Steckeranschluss und Antennenanschluss aus der gleichen Steckerfamilie stammen, sonst passt nichts zueinander !

Bei den ESP8266 ESP-12 Chips gibt es nach meiner Kenntnis zwei verschiedene Antennenformen (feiner Mäander und grober Mäander ) , die beim folgenden Umbau in den einzelnen Schritten bildmäßig auch erläutert werden.

Los geht´s.
Erst mit dem Cuttermesser  die Leitungen der Leiterplatten-Antenne unterbrechen. Dazu schneidet man vorsichtig die Leiterbahnen an den Stellen wie im folgenden Bild gezeigt.

wiffi1

 

wemos1Dann werden die Leiterbahnen zwischen den Schnitten durch vorsichtiges Kratzen mit dem Cuttermesser wie in folgendem Bild entfernt:

wiffi2

Übrig bleibt eine Lötinsel zum Anschluss der Koaxkabel-Seele . Diese Lötinsel wird jetzt verzinnt und auch das daneben liegende Gehäuse wird zum Anschluß der Koaxkabe-Abschirmung verzinnt. Aber nicht zu lange mit dem  Lötkolben erwärmen!

wiffi3

wemos2

Jetzt wird die Kabelpeitsche mit dem konfektionierten SMA-Stecker angelötet.

wemos3

Und so sieht das ganze dann im verlöteteten Zustand aus. Die Abschirmung des Koaxkabels ist mit dem Blechgehäuse des ESP8266 verlötet, so daß dies gleichzeitig auch eine gute Zugentlastung ist.

wiffi4

wemos4

Zum Schluss mit einem Ohmmeter nachprüfen, daß beim  Koaxkabel die Seele und die Abschirmung keine ungewollte Verbindung haben und daß der Innenanschluß der SMA-Buchse auch Durchgang hat zur Lötinsel auf dem ESP8266.

Nun die Antennenbuchse in das Modulgehäuse einschrauben und die WLAN-Antenne einstecken bzw. aufschrauben so wie beim WIFFI-wz in folgendem Bild :

esp8266_antenne4

4 Das Ergebnis

Das Ergebnis war bei mir überraschend gut,  deutlich mehr als 10dB Gewinn gegenüber der Leiterplattenantenne !!  Selbst im abgelegensten Winkel meines Hauses kann ich meinen  WIFFI-wz nun platzieren ohne einen Repeater o.ä. einzusetzen. Der Aufwand hat sich gelohnt.

Viel Erfolg beim Nachbau !

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

 

 

Homematic User-Treffen 2016: Alternative Aktoren und Sensoren mit Homeduino, WIFFI & Co.

Homematic User-Treffen 2016: Alternative Aktoren und Sensoren mit Homeduino, WIFFI & Co.

Folie2

____________________________________________________________________________________________________________________________________Folie3

_____________________________________________________________________________________________________________________________________Folie4

_____________________________________________________________________________________________________________________Folie5

_____________________________________________________________________________________________________________________Folie6

_____________________________________________________________________________________________________________________Folie7

_____________________________________________________________________________________________________________________Folie8

_____________________________________________________________________________________________________________________Folie9

_____________________________________________________________________________________________________________________Folie10

_____________________________________________________________________________________________________________________Folie11

_____________________________________________________________________________________________________________________Folie12

_____________________________________________________________________________________________________________________Folie13

_____________________________________________________________________________________________________________________Folie14

_____________________________________________________________________________________________________________________Folie15

_____________________________________________________________________________________________________________________Folie16

_____________________________________________________________________________________________________________________Folie17

_____________________________________________________________________________________________________________________Folie18

_____________________________________________________________________________________________________________________Folie19

_____________________________________________________________________________________________________________________Folie20

_____________________________________________________________________________________________________________________Folie21

_____________________________________________________________________________________________________________________Folie22

_____________________________________________________________________________________________________________________Folie23

_____________________________________________________________________________________________________________________Folie24

_____________________________________________________________________________________________________________________Folie25

_____________________________________________________________________________________________________________________Folie26

_____________________________________________________________________________________________________________________Folie27

_____________________________________________________________________________________________________________________Folie28

_____________________________________________________________________________________________________________________Folie29

_____________________________________________________________________________________________________________________Folie30

_____________________________________________________________________________________________________________________Folie31

_____________________________________________________________________________________________________________________Folie32

_____________________________________________________________________________________________________________________Folie33

_____________________________________________________________________________________________________________________Folie34

_____________________________________________________________________________________________________________________Folie35

_____________________________________________________________________________________________________________________Folie36

_____________________________________________________________________________________________________________________Folie37

_____________________________________________________________________________________________________________________Folie38

_____________________________________________________________________________________________________________________Folie39

_____________________________________________________________________________________________________________________Folie40

_____________________________________________________________________________________________________________________Folie41

_____________________________________________________________________________________________________________________Folie42

_____________________________________________________________________________________________________________________Folie43

_____________________________________________________________________________________________________________________Folie44

_____________________________________________________________________________________________________________________Folie45

_____________________________________________________________________________________________________________________Folie46

_____________________________________________________________________________________________________________________Folie47

_____________________________________________________________________________________________________________________Folie48

_____________________________________________________________________________________________________________________Folie49

_____________________________________________________________________________________________________________________Folie50

_____________________________________________________________________________________________________________________Folie51

_____________________________________________________________________________________________________________________Folie52

_____________________________________________________________________________________________________________________

Folie53

_____________________________________________________________________________________________________________________

Homematic User-Treffen 2016: Rollladen- und Lichtsteuerung mit dem Sonnenstandsskript

Homematic User-Treffen 2016: Rollladen- und Lichtsteuerung mit dem Sonnenstandsskript

Folie2

______________________________________________________________________________________________________________________________________Folie3

_____________________________________________________________________________________________________________________________________

Folie4

_____________________________________________________________________________________________________________________________________

Folie5

_____________________________________________________________________________________________________________________________________

Folie6

_____________________________________________________________________________________________________________________________________Folie7

 

___________________________________________________________________________________________________________________________________

Folie8

 

_____________________________________________________________________________________________________________________________________Folie9

 

_____________________________________________________________________________________________________________________________________Folie10

 

_____________________________________________________________________________________________________________________________________Folie11

 

____________________________________________________________________________________________________________________________________Folie12

 

____________________________________________________________________________________________________________________________________Folie13

 

___________________________________________________________________________________________________________________________________Folie14

 

____________________________________________________________________________________________________________________________________Folie15

 

____________________________________________________________________________________________________________________________________Folie16

 

____________________________________________________________________________________________________________________________________Folie17

 

____________________________________________________________________________________________________________________________________Folie18

 

____________________________________________________________________________________________________________________________________Folie19

 

____________________________________________________________________________________________________________________________________Folie20

 

____________________________________________________________________________________________________________________________________Folie21

 

____________________________________________________________________________________________________________________________________Folie22

 

____________________________________________________________________________________________________________________________________Folie23

 

____________________________________________________________________________________________________________________________________Folie24

 

____________________________________________________________________________________________________________________________________Folie25

 

____________________________________________________________________________________________________________________________________Folie26

 

____________________________________________________________________________________________________________________________________Folie27

 

____________________________________________________________________________________________________________________________________

Tutorial: So funktioniert die Homematic WebUI-Logik

Tutorial: So funktioniert die Homematic WebUI-Logik

Eigentlich scheint die Programmierung einer Homematic doch eine ganz einfache Sache zu sein. Die WENN…DANN-Sprache entspricht ja auch unserer Denklogik, aber speziell die Homematic WebUI-Logik hat mir persönlich anfangs doch einige Verständnisprobleme bereitet. Vielleicht war der Grund, daß ich mit Hardware- und Software-Logik beruflich vorbelastet bin und man dann leicht in bestimmten Denkmustern verfangen ist. Mit diesem Artikel möchte ich einerseits klar machen, was in der CCU wie funktioniert und möchte andererseits  Interessierten eine Hilfestellung zur Einarbeitung in die WebUI-Logik geben.

So funktioniert (vermutlich) die WebUI-Logik

Bewußt wurde in der Überschrift „vermutlich“ hinzugefügt, weil ich kaum entsprechende Erklärungen und Erläuterungen zum Thema gefunden habe. Im Homematic-Forum sind einige gute Hinweise zu diesem Thema, die für ein grundlegendes Verständnis hilfreich sind:

http://homematic-forum.de/forum/viewtopic.php?f=31&t=4251#p25607

Der Hauptunterschied der WebUI-Logik im Vergleich zu einer nahezu gleichzeitig und parallel arbeitenden Hardware-Logik (mit UND oder OR Gattern  usw.) ist, daß die Homematic-Software „ereignisorientiert“ funktioniert. Die Software arbeitet nicht kontinuierlich das programmierte Logikschema ab, sondern ist nur dann aktiv, wenn Ereignisse oder Veränderungen stattfinden. Das hat den Vorteil, daß  der jeweilige Prozess nur dann behandelt wird, wenn er auch Behandlung benötigt. Wenn in dem jeweiligen Prozess nichts passiert, dann nimmt der Prozess auch keine Rechenkapazität in Anspruch. So kann selbst ein relativ rechenschwacher Computer eine relativ große Zahl von Prozessen steuern und trotzdem relativ schnell reagieren.
Versuchen wir mal, mit einem einfachen Beispiel die Funktion kennenzulernen:

Folie3

Es handelt sich um die einfache UND-Verknüpfung von zwei Logiksignalen A und B. Nur wenn beide 1 sind , dann ist auch der Ausgang C=1. Die zeitliche Darstellung einer bestimmten Sequenz eines A-Signals und eines B-Signals führt mit der UND-Verknüpfung zu einem C-Signal, was exakt nur dann 1 ist , wenn A und B gleichzeitig 1 sind. So kennen wir die Logik und so denken wir manchmal, daß auch so die Homematic funktioniert. Die Homematic arbeitet aber ereignisorientiert: Die Eingangsbedingungen bekommen bei der WebUI-Programmierung dazu ein zusätzliches ereignisorientiertes Kennzeichen:

Entweder bei  Aktualisierung auslösen  oder  bei Änderung auslösen oder  nur prüfen .

Mit diesem Kennzeichen wird nun festgelegt, ob überhaupt und wie oft das Programm logisch durchlaufen wird. Zum Verständnis schauen wir uns mal das nächste Bild genauer an:

 

Folie2

Auf der CCU laufen vier Hauptprozesse ab:

– Program-Execution
Hier werden die vom Anwender erstellten WebUI-Programme abgearbeitet. Das Ergebnis sind in der Regel Aktorbefehle oder Wertzuordnungen für selbst definierte sog. Systemvariable.

– Outputs-Management
Die Aktorbefehle aus den User-Programmen werden in diesem Prozess in Stell- und Schaltgrößen für die verwendeten Aktoren umgesetzt.

– Events-Management
Hier sind alle Bedingungen aus allen User-Programmen gesammelt. Jeder Bedingung sind Programme zugeordnet, in denen genau diese Bedingung verwendet wird.

– Inputs-Management
In diesem Prozess  werden die Sensoren und Aktorzustände regelmäßig abgefragt. Ein Timer erzeugt ein aktuelles Zeitsignal.

Das Zusammenspiel der vier Prozesse ist folgendermaßen:
Im Inputs Management wird regelmäßig geschaut, ob sich der neue Wert vom alten Wert unterscheidet. Im Unterschiedsfall signalisiert dieser Prozess ein Ereignis (Event) an den Event-Manager. Wenn das Signal sich nicht verändert hat, dann passiert nichts. Wenn ein Event signalisiert wird, dann prüft das Events-Management in der Liste alle Bedingungen, ob und welche Bedingungen zutreffen. Diese positiven Bedingungen werden nun mit einem „roten Punkt“ gekennzeichnet . Jeder Event mit einem roten Punkt bekommt nun einer Behandlung in der Form, daß alle Programme, in denen diese konkrete Bedingung verwendet wird, ausgeführt werden müssen. Das Programmausführen übernimmt nun der Program-Execution-Prozess, indem er zyklisch beim Events-Management nachschaut , ob und welche Events mit einem roten Punkt gekennzeichnet sind. Wenn das Programm ausgeführt wurde, dann wird der rote Punkt wieder gelöscht; das zugehörige Ereignis wurde ja abgearbeitet. Auf diese Art und Weise kann die CCU eigentlich nicht überlastet werden, weil im Überlastfall fast alle Events mit roten Punkten gekennzeichnet sind und es eben länger dauert, bis alle behandelt werden. Im schlimmsten Fall werden die Events nochmal auf rot gesetzt, bevor überhaupt eine Behandlung(und damit Löschung des roten Punktes) stattgefunden hat. Dann „verschluckt“ die CCU möglicherweise einige Aktionen!
Aber man muß sehr positiv anmerken, daß eine solche ereignisorientierte Steuerung bei den in der Hausautomation vorkommenden meist langsamen Veränderungen eine ausgezeichnete und effektive Steuerungsart ist.

Die gute Frage:  Änderung,  Aktualisierung oder Prüfen

Bei der Programmierung eines neuen WebUI-Programmes hat der Anfänger oft ein Problem mit der  Entscheidung für das richtige Ereignis-Attribut: Änderung/Aktualisierung/Prüfen. Dabei ist die richtige Wahl entscheidend für die richtige Funktion des Programmes. Am Beispiel der UND-Verknüpfung zweier Eingangsgrößen A und B zur Ausgangsgröße C soll das verdeutlicht werden.

Folie4

Zuerst schauen wir uns an, was passiert, wenn beide Eingangsbedingungen  A und B das Attribut Änderung haben (Bild oben links) . In diesem Fall läuft das Programm insgesamt 4 mal durch; jedesmal wenn eine Eingangsbedingung sich verändert hat. Die Programmdurchläufe (violette Pfeile)  erfolgen kurz nach Eintritt der Änderungen. Wie lange „kurz“ ist hängt davon ab, wieviele Ereignisse gerade abgearbeitet werden. Dementsprechend zeitverschoben entsteht das Ergebnis C (blaue Linie).  Im Vergleich zu einer idealen UND-Verknüpfung ( grüne strichlierte Linie) haben wir durch die Zeitverzögerung nur geringe Unterschiede.

Im Beispiel oben rechts hat die Eingangsbedingung  A das Attribut Änderung, B wird nur geprüft. In diesem Fall werden nur zwei Programmdurchläufe angestossen, währenddessen die UND-Bedingung nicht erfüllt ist. Ergebnis ist, daß das Ausgangssignal null bleibt.

Im umgekehrten Fall, A hat Attribut Prüfen und B hat Attribut Änderung (Bild unten links), entsteht ein völlig anderes Ergebnis. Auch hier wird das Programm nur zweimal durchlaufen, aber während des ersten Durchlaufes geht C auf 1 und während des zweiten Durchlaufes geht C auf 0; aber viel später als bei der idealen UND-Verknüpfung!

Im letzen Beispiel (Bild unten rechts) mit beiden Eingangsbedingungen  mit dem Attribut Prüfen passiert am Ausgangssignal gar nichts.

Man sieht an den Beispielen, daß die Wahl des Ereignis-Attributs ganz entscheidend für die Funktion ist.

Mit dem Attribut Aktualisieren ( siehe folgendes Bild) wird die Sache noch komplizierter!  Wenn eine oder mehrere Eingangsbedingungen das Attribut Aktualisieren haben, dann wird jedesmal, wenn das Eingangssignal aktualisiert wird, das komplette Programm durchlaufen. Und das kann unter Umständen sehr häufig sein. Bei einem Temperatursensor beispielsweise alle 3 Minuten. Positiv ist, daß das Ausgangssignal sehr nahe an die ideale Verknüpfung kommt. Wenn Rechnerbelastung keine Rolle spielen würde, dann wären Lösungen mit dem Attribut Aktualisieren eigentlich sehr gut. Aber das ist nur theoretisch, denn in der Praxis führt ein häufiger Gebrauch von Aktualisieren zu einer Überlastung der CCU !

Also das Attribut Aktualisieren nur in Ausnahmfällen verwenden !

Folie5

Man muß immer berücksichtigen, daß bei einem Programmdurchlauf auch immer das komplette Programm mit sonst wenn und sonst durchlaufen wird. Gerade wenn viele verschiedene Eingangsgrößen logisch verknüpft werden, dann sollte man sich das verwendete Ereignisattribut jeder  Eingangsgröße genau überlegen, weil jede Größe mit Änderung die Häufigkeit für einen Programmdurchlauf erhöht.

Weitere Ergänzungen und Beispiele werden hier noch folgen.

Robuster Sonnensensor ganz einfach !

Robuster Sonnensensor ganz einfach !

Ein Sonnensensor ist sehr wichtig zur Steuerung der Rolladen , Jalousien und Markisen. Viele verwenden hierfür einen Helligkeitssensor, aber die große Dydnamik des Helligkeitssignals ist mit normalen Helligkeitssensoren meist nur unbefriedigend abzubilden, weshalb ich eigentlich von so einer Lösung abraten möchte.

Deshalb verwende ich einen einfachen und robusten thermischen Sonnensensor, der sich bereits seit Jahren ausgezeichnet für die Steuerung meiner Rolladen bewährt hat. Mehr dazu hier:

https://www.stall.biz/project/sonnensensor-fur-jalousien-und-rolladensteuerung

In diesem Post möchte ich einen noch einfacheren Sonnensensor vorstellen, der fast ohne Werkzeug auch von einem Nicht-Heimwerker nachgebaut werden kann. Dabei werden mit Bedacht nur Materialien verwendet, die eine langjährige Verwendung bei alle Wind- und Wetterbedingungen aushalten. Insbesondere Sonneneeinstrahlung und Feuchtigkeitseintritt sind immer wieder eine Herausforderung bei der Gestaltung von Sensoren!

Lange genug geredet, jetzt folgt das Kochrezept für den Nachbau!

Die wenigen Zutaten:

  • Ein Kleinverteilergehäuse aus Kunststoff, das  sehr gut wassergeschützt (Dichtung!) und für den Aussensatz geeignet ist. Geeignetes  Kunststoffmaterial ist oft glasfaserverstärkt und aus Hartplastik. Es muß der Sonne einige Jahre widerstehen können. Maße des Gehäuses in mm:  115 x 115 x 60. Bezugsquelle z.B. Baumarkt.
  • Ein Homematic Differenz-Temperatursensor HM-WDS30-OT2_SM . Bezugsquelle kennen wir!
  • Ein Röhrchen aus Messing oder Aluminium, das über den Sensor geschoben wird. Innendurchmesser 5mm, Aussendurchmesser ca. 6mm . Bezugsquelle z.B. Baumarkt.
  • Ein geeignetes Schnapsglas oder Stamper aus der Hausbar.

Das folgende Bild sagt mehr als viele Worte:

Folie1

Im Deckel des Kleinverteilergehäuses wird mittig ein 5mm-Loch zur Aufnahme des ersten  Temperaturfühlers gebohrt, in die Seite des Gehäuses wird ein weiteres 5mm-Loch für die Aufnahme des zweiten Temperaturfühlers gebohrt. Dann werden der Differenz-Temperatursensor und die Fühler so in das Gehäuse eingepasst wie man auf dem nächsten Bild sehen kann. Die langen Fühlerzuleitungen sollten so wie auf dem Bild sehr kompakt zusammengerollt werden, damit sie möglichst wenig die Funkabstrahlung behindern.

Folie2

Dann die Fühler mit Sekundenkleber fixieren und Gehäuse schließen. Der obere Sonnenfühler wird nun (optional) mit einem geschwärzten Messing- oder Aluröhrchen verlängert. Und zum Schluß noch mittig das Schnapsglas aufsetzen  und mit Silikon abdichten. Nicht vergessen, vorher noch ein möglichst kleines Loch (1 mm) neben dem Sensor anbringen, womit ein Druckausgleich erreicht werden soll.

… und fertig ist unser Sonnensensor!

Aufgestellt wird der Sonnensensor natürlich draussen an einem Ort, wo er möglichst den ganzen Tag die Sonne „sieht“. Wichtig ist dabei, daß der seitlich angebrachte Fühler möglichst unverfälscht  die Aussentemperatur mißt. Dazu ist diese Seite nach Norden auszurichten , so daß der Fühler permanent im Schatten ist.

Das WebUI-Programm dazu ist ganz einfach, weil ja bereits im Differenz-Temperatursensor sowohl die beiden Temperaturen als auch die Differenztemperaturen verfügbar sind. Man legt dazu eine logische Systemvariable Sonne_scheint an und verwendet das folgende WebUI-Programm:

sonnensensor_6

Damit bei Aprilwetter nicht die Beschattung dauernd ein- und ausgeschaltet wird, sorgt eine Temperatur- und Zeithysterese für entsprechende „Ruhe“ in der Steuerung. Die Schwellwerte für die Temperaturen muß jeder selbst nach eigenen Bedürfnissen festlegen. Aber das ist im praktischen Betrieb nach kurzer Erfahrung leicht möglich.

Damit auch nur die Rolladen betätigt werden, die von der Sonne bescheint werden, ist die Verwendung meines Skriptes zur Berechnung des Sonnenstandes sehr zu empfehlen.

https://www.stall.biz/project/sonnenstandsberechnung-2-0-fur-rolladen-markisen-lampen

… und weitere Erläuterungen zur Entwicklung geeigneter  Programme zur intelligenten Steuerung der Rolladen und Markisen sind hier:

https://www.stall.biz/project/so-steuert-man-rolladen-jalousien-und-markisen-mit-der-homematic

… und wer selbst keine Wetterstation hat kann sich ergänzende Wetterdaten aus dem Internet holen:

https://www.stall.biz/project/wunderground-wetter-mit-einfachem-hm-skript-holen

Ergänzung 15.09.2015:

Insbesondere wenn bei Aprilwetter die Sonne sehr häufig zwischen den Wolken hervor kommt, ist eine „Glättung“ der Differenztemperatur sinnvoll. Dies macht man mit einem kleinen Skript, das bei jedem neuen Messwert des Temperatursensors (das ist so alle 3 Minuten) ausgelöst wird. Dazu vorher eine Systemvariable sonne_diff_mittel vom Typ Zahl mit der Dimension °C anlegen.

Hier das WebUI-Programm:

webui_mittelwert

und das zugehörige HM-Skript:

!skript zur berechnung des mittelwertes der sonnentemperatur
real tau = 0.1;   ! 1 = keine mittelung ; kleinere werte, umso stärker ist mittelung
real Sonne_Diff_Tur = dom.GetObject("BidCos-RF.KEQ0543406:4.TEMPERATURE").Value();
!WriteLine(Sonne_Diff_Tur);
real Sonne_Diff_Mittel = dom.GetObject("sonne_diff_mittel").Value();
!WriteLine(Sonne_Diff_Mittel);
real Diff= Sonne_Diff_Tur - Sonne_Diff_Mittel;
Sonne_Diff_Mittel = Sonne_Diff_Mittel + (tau *Diff);
!WriteLine(Sonne_Diff_Mittel);
dom.GetObject("sonne_diff_mittel").State(Sonne_Diff_Mittel );

Danach muß nur noch im WebUI-Programm sonnescheint die gemessene Differenztemperatur durch die neue gemittelte Temperatur ersetzt werden. Das sieht dann so :

sonne_scheint

Das Ergebnis ist eine „geglättete“ bzw. gemittelte Differenztemperatur, wie man im folgenden Diagramm schön sehen kann. Aufgezeichnet ist typisches Aprilwetter:

Viel Erfolg beim Nachbau!

Tutorial:  So steuert man Rolladen, Jalousien, Markisen mit der Homematic

Tutorial: So steuert man Rolladen, Jalousien, Markisen mit der Homematic

Update 10.08.2015:
Änderungen im Programm roll_nacht_anders,  roll_schatten_pgm,  roll_nacht_pgm
– Systemvariable roll_zeit_hh_mm hinzugefügt
– Alternative kompaktere Rolladen-Programme , Methode 2 in Schritt 9

Update 25.10.2015:
– Umschaltung manuell/auto-Betrieb in allen Programmen geändert
– Änderungen in roll_schatten_pgm

1. Einleitung

Die Theorie mit der Homematic ist toll: Man kaufe sich eine CCU, einige Sensoren und Aktoren schon kann man (oder Frau) die lästige Bedienung der Rolladen, Jalousien und Markisen einfach automatisieren. Hab ich auch so gedacht, aber nach kurzer Zeit stellte sich Enttäuschung ein. Es war doch nicht so einfach mit der Programmierung!  Zwar waren einfache zeitgesteuerte Betätigungen schnell realisiert und sogar eine Astro-Funktion mit Sonnenauf- und untergang war schnell implementiert, aber bald erkennt man, daß mit diesen „Bordmitteln“ keine überzeugende Steuerung der Rolladen, Jalousien und Markisen möglich ist. Auch eine Hilfestellung seitens des Herstellers mit entsprechenden Beispielen ist zu diesem wichtigen Thema nicht vorhanden.

So entstanden über die Jahre eigene mehr oder weniger komplexe Lösungen, welche die Geduld der Hausbewohner mit anhaltenden Fehlbedienungen der Rolladen doch arg strapazierten!
Mittlerweile ist alles gut und mit viel Aufwand ist eine (für mich!) überzeugende Lösung einer Rolladensteuerung entstanden, die fast ohne eigenes Zutun die Bedürfnisse der Hausbewohner an Licht und Schatten gut abbildet.

Mit diesem Tutorial möchte ich die Struktur meiner aktuellen automatischen Steuerung erläutern, um Interessierten einen einfachen Nachbau zu erlauben.

2. Das Konzept

Wichtig sind anfangs die Überlegungen, was mit der Steuerung der Rolladen, Jalousien und Markisen eigentlich erreicht werden soll:

Ist es nur eine „Nachtfunktion“, bei der abends die Rolladen runter und morgens wieder hoch gehen soll ?
… oder möchte man im Sommer mit den Rolladen auch eine Beschattung realisieren ?
… oder möchte man bei Regenwetter die Rolladen gezielt runterfahren, um eine Verschmutzung der Fenster zu vermeiden?
… oder möchte man bei Einbruchalarm alle Rolladen runterfahren ?
… oder möchte man beim Fernsehen und starker Sonnenstrahlung automatisch die wichtigen Rolladen nicht ganz runter fahren aber doch zumindest in eine Beschattungsposition fahren ?
oder, oder, oder …

Man merkt schnell, daß eine Rolladensteuerung nicht trivial ist, sondern wenn sie gut gemacht ist, eine recht komplexe Angelegenheit sein kann!

Das hier erläuterte Konzept ist schematisch im nächsten Bild dargestellt.
Folie1
Die verwendeten Begriffe sind gleichzeitig die Bezeichnung der Sensoren, Systemvariablen und Programme. Links im Bild ist die verwendete Sensorik. Dabei gibt es einige unverzichtbare Sensoren und andere optionale Sensoren, die mit einem Stern gekennzeichnet sind.

Kernstück der Steuerung ist der sog. Sonnensensor, der die Sonnenstrahlung mit einem kleinen thermischen Sonnenkollektor erkennt. Die häufig verwendeten Helligkeitssensoren sind für diese Aufgabe viel weniger geeignet, weil die Sonneneinstrahlung einen sehr großen Signalbereich hat , der mit den herkömmlichen Photowiderständen kaum meßbar ist. Zudem benötigt man eine „Tiefpassfunktion“ damit das Signal zeitlich geglättet wird und nicht bei jeder Wolke ein- und ausgeschaltet wird. Wie man einen solchen thermischen Sonnensensor baut ist hier beschrieben: https://www.stall.biz/project/sonnensensor-fur-jalousien-und-rolladensteuerung oder als einfachere Lösung: https://www.stall.biz/project/robuster-sonnensensor-ganz-einfach

Von dem Temperatursignal temp_sonne kann man mit der Aussentemperatur temp_aussen eine Differenztemperatur temp_sonne_diff ableiten, die ein Maß für die Sonneneinstrahlung ist. Als Temperaturfühler kann man auch einen sog. Differenztemperaturfühler verwenden und muß dann nicht mehr die Meßgröße temp_sonne_diff berechnen, sondern der Sensor liefert die Differenzgröße gleich mit. Allerdings muß man dann den zweiten Temperaturfühler so platzieren, daß er auch die Aussentemperatur (Nordseite!) unverfälscht messen kann.

Weitere für die Rolladensteuerung sinnvolle verwendbare Sensorik sind eine optionale Wetterstation für Windgeschwindigkeit W-Windgeschwindigkeit und  W_Windrichtung für Windrichtung. Falls man in der Nähe einer Wunderground-Wetterstation wohnt, kann man diese Sensorsignale kostengünstig auch übers Internet mit meinem Skript wunderground_pgm holen. https://www.stall.biz/project/wunderground-wetter-mit-einfachem-hm-skript-holen

Ein optionaler Regenmelder ist hilfreich, wenn beispielsweise Markisen und Dachfenster gesteuert werden sollen. Und natürlich müssen einige Fensterkontakte bei Rolladen an Fenstertüren vorhanden sein, um zu verhindern, daß die Rolladen runter gehen, wenn man gerade draussen ist.

Damit man die Steuerung ein- und ausschalten kann, sind sog. virtuelle Taster oder auch Fernbedienungen sinnvoll. In der hier vorgestellten Grundausbaustufe sind zwei virtuelle vorhanden. Der eine (roll_auto_manuell) schaltet den Automatikmodus ein und aus. Der andere (roll_alle_hochrunter)  erlaubt alle Rolladen gleichzeitig hoch- und runterzufahren. Das kann auch als Paniktaster o.ä. verwendet werden. Darüber hinaus hat natürlich jeder Rolladenaktor eigene Funktionstaster, mit denen manuell jede Rollade bedient werden kann.

 

3. Die Programme

Im Folgenden werden kochrezeptartig alle verwendeten WebUI-Programme und Skripte beschrieben. Das ist dann der Grundstein für eigene Anpassungswünsche, die sicher individuell und reichlich bereits nach kurzer Nutzungszeit entstehen.

Schritt 1: Aktoren und Sensoren installieren und benamen

Ideal ist die Benamung der verwendeten Sensoren nach dem Schemabild oben, ansonsten müssen entsprechende Anpasssungen in den einzelnen Programmen gemacht werden. Der Sonnensensor muß ebenfalls vorhanden sein. Dann noch mindestens zwei virtuelle Taster neu benamen:

roll_auto_manuell  (ich habe dafür den „ccu-wired-taster 19 verwendet)

roll_alle_hochrunter (ich habe dafür den „ccu-wired-taster 18 verwendet)

 

Schritt 2: Systemvariablen anlegen

Folgende Systemvariable müssen angelegt werden: (bitte Schreibweise genaustens einhalten !!)

temp_sonne_diff     Typ:Zahl   Werte: -80 bis 80      Maßeinheit: °C

sonne_elevation      Typ:Zahl  Werte: -180 bis 180   Maßeinheit: grad

sonne_azimut          Typ: Zahl  Werte: 0 bis 360         Maßeinheit: grad

roll_schatten            Typ: Logikwert

roll_nacht                  Typ: Logikwert

roll_AutoManuell    Typ: Logikwert

roll_zeit_hh_mm  Typ: Zahl Werte 0,00 bis 23,59 Maßeinheit Stunden, Minuten (nur für Programm roll_nacht_anders)

Schritt 3: Programm sonnensensor_pgm installieren

Wenn zwei unabhängige Temperatursensoren für die Temperatur im Sonnensensor und für die Aussentemperatur verwendet werden, dann ist ein kleines Skript notwendig zur Berechnung der Differenztemperatur. Dazu wird erst ein WebUI-Programnm angelegt, mit dem das Skript aufgerufen wird.

sonnensensor_pgm_0

Das implementierte Skript verwendet die Seriennummern meiner verwendeten Temperatursensoren. Diese Nummern sind vom Anwender auf seine individuellen Seriennummern zu ändern!

HM-Skript   
!Berechnet Differenztemperatur Sonnensensor
real Aussen_Temperatur = dom.GetObject("BidCos-RF.HEQ0237327:1.TEMPERATURE").Value();
real Sonnen_Temperatur = dom.GetObject("BidCos-RF.IEQ0405570:1.TEMPERATURE").Value();
real deltat = Sonnen_Temperatur - Aussen_Temperatur;
dom.GetObject("temp_sonne_diff").State(deltat);

Einzelheiten zum verwendeten Sonnensensor  nochmal hier: https://www.stall.biz/project/sonnensensor-fur-jalousien-und-rolladensteuerung

und hier: https://www.stall.biz/project/robuster-sonnensensor-ganz-einfach

Schritt 4: Programm sonnenstand_pgm installieren

Das Programm für die Berechnung der Sonnenposition am Himmel ist ein besonders wichtiger Teil der Rolladensteuerung. Informationen hierzu in der genauen Funktionsbeschreibung dieses HM-Skriptes findet man hier: https://www.stall.biz/project/sonnenstandsberechnung-2-0-fur-rolladen-markisen-lampen
Mit dem Skript werden die Systemvariable sonne_elevation und sonne_azimut berechnet. Die Elevation ist der Positionswinkel der Sonne gegenüber dem Horizont. Er variiert in unseren Breiten so zwischen 40° im Sommer mittags und fällt nachts (auch wenn man die Sonne nicht sieht !) auf  etwa -40°. Die Sonne geht unter bei einem Elevationswinkel von 0°.

Der Azimut ist der Positionswinkel in der Horizontalen. Ost sind 90°, Süd sind 180° und dementsprechend ist West 270°.

Die Verwendung dieser Einflußgrößen läßt sich am folgenden Schemabild erklären:

rolladen_tutorial_sonne

Mit dem Azimutwinkel kann man festlegen, in welchem Winkelbereich der Sonnenposition in der Horizontalen eine Besonnung des jeweiligen Fensters möglich ist. Bei dem hier verwendeten Beispiel eines nach Süden ausgerichteten Fensters ist eine Besonnung nur möglich bei einem Azimutwinkel von 110° bis 230°. Man kann diesen Winkel theoretisch aus der Bauzeichnung ermitteln oder einfach über den Tag das Fenster beobachten, bei welchem Winkelbereich eine Besonnung entsteht bzw. eine Beschattung notwendig ist.

Die Bestimmung des Elevationswinkelbereiches erfolgt analog. Hier sind Dachüberhänge oder Abschattungen durch vorliegende Häuser, Hecken und Mauern zu berücksichtigen. Wenn keine Hindernisse vorhanden sind, wird der Elevationswinkel für das Beschattungsprogramm gar nicht benötigt.

Und so geht die Installation:

Erst das folgende WebUI-Programm installieren:

sonnenstand_pgm

Und hier das Skript dazu, das ganztägig alle 5 Minuten aufgerufen wird:

!berechg sonne_elevation, sonne_azimut; stand 14.03.2014
        !Verfasser: funkleuchtturm
        real phi = system.Latitude(); !Breitengrad holen
        phi = 0.017453292 * phi; !umwandeln in bogenmass
        !####### sin_phi und cos_phi mit taylorreihe berechnen
        real temp = phi * phi;
        real sin_phi =phi * ((temp * temp * 0.0083334) +1.0 - (temp * 0.1666667)); !sinus-naeherung
        real cos_phi = (temp *temp *0.0416667)  + 1.0 - (temp * 0.5); !cosinus-naeherung
        !### berechnung sonnenzeit, alle zeiten in minuten ########
        integer zeit_min = system.Date("%M").ToInteger() + 60*system.Date("%H").ToInteger();
        integer tagesbeginn_min = system.SunriseTime("%M").ToInteger() + 60*system.SunriseTime("%H").ToInteger();
        integer tagesende_min = system.SunsetTime("%M").ToInteger() + 60* system.SunsetTime("%H").ToInteger();
        integer sonnenzeit =zeit_min + 720 - 0.5 *(tagesbeginn_min +tagesende_min);
        if (sonnenzeit > 1440) {sonnenzeit = sonnenzeit -1440;}
        if (sonnenzeit < 1) {sonnenzeit = 1440 + sonnenzeit;}
        boolean nachmittag =false;
        if (sonnenzeit > 720) {sonnenzeit =sonnenzeit - 720; nachmittag = true; }
                           else {sonnenzeit =720 -sonnenzeit;}
        !##### berechnung sin_tau und cos_tau ############           
        real tau = 0.00436332313 * sonnenzeit;   ! 15/60  * pi /180 * sonnenzeit  [0 < tau < pi ]
        if (tau < 1.570796327)
                       {temp = tau * tau;
                         real sin_tau =tau * ((temp * temp *  0.0083334) +1.0 - (temp *0.1666667));
                         tau= 1.570796327 - tau;
                         temp = tau * tau;
                         real cos_tau =tau * ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667));}                   
                     else
                         {real tau1  =3.141592654 - tau;
                           temp = tau1 * tau1;
                           real sin_tau =tau1 * ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667));
                           tau = tau  -  1.570796327;
                           temp = tau * tau;
                           real cos_tau = (tau) *(-1.0)* ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667));}
        !##### berechnung delta #######################   
        integer tageszahl = system.Date("%j").ToInteger();
        tageszahl = tageszahl +10;
        if (tageszahl > 365) {tageszahl = tageszahl - 365;}
        if (tageszahl < 92) {real tag = 0.0172142 *tageszahl;temp = tag * tag;
                    real delta = (-0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
        if ((tageszahl >91) && (tageszahl < 184)) {tageszahl = 183 - tageszahl; real tag = 0.0172142 *tageszahl;
                      temp = tag * tag;  real delta = (0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
        if ((tageszahl >183) && (tageszahl < 275)) {tageszahl = tageszahl - 183; real tag = 0.0172142 *tageszahl;
                      temp = tag * tag;  real delta = (0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
        if ((tageszahl >274) && (tageszahl < 366)) {tageszahl = 365 - tageszahl; real tag = 0.0172142 *tageszahl;
                      temp = tag * tag;  real delta = (-0.410152) *((temp *temp *0.041666)  + 1.0 - (temp * 0.5));}
       !##### berechnung sin_delta, cos_delta  #######################   
        temp = delta * delta;
        real sin_delta =delta * ((temp * temp *  0.0083334) +1.0 - (temp * 0.1666667)); !sinus-naeherung
        real cos_delta = (temp *temp *0.0416667)  + 1.0 - (temp * 0.5); !cosinus-naeherung
        !##### berechnung tan_delta  mit stueckweiser linearisierung des tan  #######################   
        boolean vvorzeichen = true;
        if (delta< 0.0) {vvorzeichen = false; delta = (-1.0) *delta;}
        real tan_delta = 1.0233 * delta;
        if (delta >=0.2618) {tan_delta = (1.1822*delta) - 0.0416;}
        if (vvorzeichen == false) {tan_delta = (-1.0) * tan_delta;}
        !##### berechnung sin_elevation und tan_azimut #######################   
        real sin_elevation = (sin_phi * sin_delta) +( cos_phi * cos_delta * cos_tau);
        temp = sin_elevation * sin_elevation;
        real sonne_elevation = sin_elevation * (1.0 + (0.1666667 * temp) + (0.075 * temp * temp));     
        sonne_elevation = 57.29577951 * sonne_elevation;
        real nenner = (sin_phi*cos_tau) - (cos_phi * tan_delta);
        if (nenner < 0.0) {boolean plus180 = true;}
        real tan_azimut = sin_tau / nenner;
        !##### berechnung sonne_azimut mit stueckweiser linearisierung des arctan ############
        boolean vorzeichen = true;
        if (tan_azimut < 0.0) {vorzeichen = false; tan_azimut = (-1.0)*tan_azimut;}
        real sonne_azimut = 0.97723 * tan_azimut;
        if ((tan_azimut >=0.2679)&&(tan_azimut < 0.5774)) {sonne_azimut = (0.84588* tan_azimut) + 0.035189;}
        if ((tan_azimut >= 0.5774)&&(tan_azimut < 1.0)) {sonne_azimut = (0.6195* tan_azimut) + 0.1659;}
        if ((tan_azimut >= 1.0)&&(tan_azimut < 1.3032)) {sonne_azimut = (0.43173* tan_azimut) + 0.3537;}
        if ((tan_azimut >= 1.3032)&&(tan_azimut < 1.7321))  {sonne_azimut = (0.3052* tan_azimut) + 0.51856;}
        if ((tan_azimut >= 1.7321)&&(tan_azimut < 2.4142)) {sonne_azimut = (0.1919* tan_azimut) + 0.7148;}
        if ((tan_azimut >= 2.4142)&&(tan_azimut < 2.9459)) {sonne_azimut = (0.123* tan_azimut) + 0.88115;}
        if ((tan_azimut >= 2.9459)&&(tan_azimut < 3.7321)) {sonne_azimut = (0.083312* tan_azimut) + 0.9981;}
        if ((tan_azimut >= 3.7321)&&(tan_azimut < 5.0))  {sonne_azimut = (0.050792* tan_azimut) + 1.1194;}
        if ((tan_azimut >= 5.0)&&(tan_azimut <7.0)) {sonne_azimut = (0.02775* tan_azimut) + 1.23465;}
        if ((tan_azimut >= 7.0)&&(tan_azimut <12.0)) {sonne_azimut = (0.01175117* tan_azimut) + 1.346641;}
        if ((tan_azimut >= 12.0)&&(tan_azimut <20.0)) {sonne_azimut = (0.004147854* tan_azimut) + 1.437881;}
        if ((tan_azimut >= 20.0)&&(tan_azimut <50.0)) {sonne_azimut = (0.0009987* tan_azimut) + 1.5008639;}
        if (tan_azimut >= 50.0) {sonne_azimut = (0.000099983* tan_azimut) + 1.54579974;}
        if (sonne_azimut> 1.5707963278) {sonne_azimut = 1.5707963278;}
        if (vorzeichen == false) {sonne_azimut = (-1.0) * sonne_azimut;}
        sonne_azimut = 57.29577951 * sonne_azimut;
        if (plus180 == true) {sonne_azimut = sonne_azimut + 180.0;}
        !##### tageszeitliche korrektur und werte auf systemvariablen speichern ######
        if (nachmittag == false)
                        {sonne_azimut = 180.0 - sonne_azimut; sonnenzeit = 720 - sonnenzeit;}
                    else
                        {sonne_azimut = sonne_azimut + 180.0;sonnenzeit = 720 + sonnenzeit;}
        sonne_azimut = 0.1 *((sonne_azimut*10.0) .ToInteger());
        sonne_elevation = 0.1 *((sonne_elevation*10.0) .ToInteger());     
        dom.GetObject("sonne_elevation").State(sonne_elevation);
        dom.GetObject("sonne_azimut").State(sonne_azimut);

 

Schritt 5: Programm wunderground_pgm installieren

Wetterinformationen zu Wind und Regen sind für die Betätigung von Rolladen, Jalousien und Markisen schon wichtig. Wenn man für die Beschaffung der entsprechenden Sensorsignale eine Wetterstation hat ist das schön, man kann aber auch preiswert die Wetterdaten einer möglichst nah gelegenen Wetterstation aus dem Internet holen. Dazu ist mein HM-Skript  sehr gut geeignet:
https://www.stall.biz/project/wunderground-wetter-mit-einfachem-hm-skript-holen
Die Installationsschritte für das Wunderground-Skript sind hier auch nochmal in Kürze:

wunderground_pgm

Dieses WebUI-Programm ruft periodisch ganztägig alle 30min das folgende Skript auf:

!Stand 03.04.2014  http://homematic-forum.de/forum/viewtopic.php?f=31&t=17209
        !zuerst folgende Systemvariablen anlegen
        !Achtung: keine vergessen und exakte Schreibweise mit Drag&Drop
        !W_Station                        Zeichenkette
        !W_Aktualisierung             Zeichenkette
        !W_Bedingungen               Zeichenkette
        !W_Temperatur                  Zahl                     °C
        !W_Luftfeuchte                  Zahl                      %
        !W_Windbedingungen       Zeichenkette
        !W_Windrichtung               Zeichenkette
        !W_Windrichtg                   Zahl                       °
        !W_Windgeschwindigkeit   Zahl                     km/h
        !W_Windboeen                  Zahl                     km/h
        !W_Luftdruck                      Zahl                      mb
        !W_Luftdrucktrend             Zeichenkette
        !W_Taupunkt                      Zahl                     °C
        !W_UV                                Zeichenkette
 
        var url = "http://api.wunderground.com/api/xxxxxxxxxxxxx/conditions/lang:DL/q/Germany/Neuwied.xml";
 
        !hier ist die Abfrage mit CUxD
        dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#url#"'");
        dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
        string wetter_xml = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
 
        !hier ist die Abfrage mit system.Exec
        !string stdout;
        !string stderr;
        !system.Exec("wget -q -O - '"#url#"'", &stdout, &stderr);
        !WriteLine(stdout);
        !string wetter_xml = stdout;
        !WriteLine(wetter_xml);
 
        !Beim XML-File den ueberfluessigen Header entfernen
        integer laenge = wetter_xml.Length();
        integer wort_position = wetter_xml.Find("display_location");
        wetter_xml = wetter_xml.Substr(wort_position, (laenge - wort_position));
        !WriteLine(wetter_xml);
 
        !Daten mit Suchworten aus XML-File ausfiltern:
 
        !string word = "full";
        string word = "city";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Station").State(daten);
 
        !string word = "observation_time";
        string word = "observation_time_rfc822";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        !daten = daten.Substr(0, (word_position -2));
        daten = daten.Substr(0, (word_position -11));
        dom.GetObject("W_Aktualisierung").State(daten);
 
        string word = "weather";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Bedingungen").State(daten);
 
        string word = "temp_c";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        real zahl = daten.ToFloat();
        dom.GetObject("W_Temperatur").State(zahl);
 
        string word = "relative_humidity";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Luftfeuchte").State(zahl);
 
        string word = "wind_string";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Windbedingungen").State(daten);
 
        string word = "wind_dir";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        word_laenge =daten.Length();
        string anfangsbuchstabe = daten.Substr(0,1);
        ! Umlaute korrigieren
        !
        ! N # Nord ***
        if (anfangsbuchstabe == "N") {
           !
            if (daten == "Nordwest") {daten = "Nord-West" ;}
        }
 
        ! S # Süd ***
        if (anfangsbuchstabe == "S") {
           ! 4 # Süd
           if (word_laenge == 4)  {daten = "Süd";}
           ! 8 # Südwest
           if (word_laenge == 8)  {daten = "Süd-West";}
           ! 12 # Süd-Südost
           if (word_laenge == 12) {daten = "Süd-Süd-Ost" ;}
             ! 13
           if (word_laenge == 13) {daten = "Süd-Süd-West" ;}
        }
 
        ! W # Westen
        if (anfangsbuchstabe == "W") {
           ! 13 # West-Südwest
            if (word_laenge == 13) {daten = "West-Süd-West" ;}
        }
 
        ! O # Osten
        if (anfangsbuchstabe == "O") {
           ! 11 # Ost-Südost
           if (word_laenge == 11) {daten = "Ost-Süd-Ost" ;}
        }
        dom.GetObject("W_Windrichtung").State(daten);
        !WriteLine(daten);
 
 
        string word = "wind_degrees";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Windrichtg").State(zahl);
 
        string word = "wind_kph";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Windgeschwindigkeit").State(zahl);
 
        string word = "wind_gust_kph";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Windboeen").State(zahl);
 
        string word = "pressure_mb";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        integer zahl = daten.ToFloat();
        dom.GetObject("W_Luftdruck").State(zahl);
 
        string word = "pressure_trend";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        dom.GetObject("W_Luftdrucktrend").State(daten);
 
        string word = "dewpoint_c";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        real zahl = daten.ToFloat();
        dom.GetObject("W_Taupunkt").State(zahl);
 
        string word = "UV";
        integer word_laenge = word.Length();
        integer word_position = wetter_xml.Find(word);
        string daten = wetter_xml.Substr((word_position + word_laenge +1), 100);
        integer word_position = daten.Find(word);
        daten = daten.Substr(0, (word_position -2));
        real zahl = daten.ToFloat();
        dom.GetObject("W_UV").State(zahl);

… und aktualiert dementsprechend alle 30 Minuten die evtl. verwendeten Systemvariablen W_Windgeschwindigkeit und W_Windrichtg .


Schritt 6: Programm roll_schatten_pgm installieren

Für die Berechnung der logischen Systemvariablen roll_schatten , die den „Schattenbedarf“ signalisiert, ist das folgende WebUI-Programme zu installieren:

rollschatten_pgm

Dabei kann man mit der Veränderung der Werte für temp_sonne_diff festlegen, wie sensibel die Beschattung auf Sonneneinstrahlung reagieren soll. Bei großen Temperaturwerten reagiert die Beschattung nur auf starke Sonneneinstrahlung, bei kleinen Werten dementsprechend feinfühliger. Wichtig ist die zeitliche Hysterese (hier 20min)  im  Programm roll_schatten_pgm, damit bei wolkigem Aprilwetter die Rolladen nicht alle 5 Minuten hoch- und runterfahren.

Schritt 7: Programm roll_nacht_pgm installieren

Die Systemvariable roll_nacht wird mit dem folgenden  WebUI-Programm berechnet. Diese logische Systemvariable signalisiert, ob die Rolladen zur Nacht herunter gefahren werden sollen:
roll_nacht_pgm

Mit der Zeitsteuerung von 19h00 bis zum maximal spätesten Sonnenuntergang 22h30 und dem Elevationswinkel kleiner als 3° wird die Systemvariable (roll_nacht =wahr) aktiviert. Morgens ist die Nacht zu Ende (roll_nacht = falsch) wenn Der Elevationswinkel -2° überschreitet, aber nicht vor 6h45.

Diese Werte müssen individell angepasst werden, je nach Lebenswandel !

Schritt 7a: Programm roll_nacht_anders  installieren

Alternativ zum Programm roll_nacht_pgm kann man zur Berechnung der Systemvariablen roll_nacht  auch ein anderes Programm roll_nacht_anders installieren. Hier wird die Nacht im Winter anders als im Sommer berechnet. Dadurch wird u.a. berücksichtigt, daß die Dämmerungsphase im Winter länger dauert als im Sommer. Mehr zu dieser etwas anderen „Philosophie“ hier: https://www.stall.biz/project/jede-nacht-ist-anders-dynamische-rolladenbetatigung   .Mir persönlich gefällt diese Betätigungsstrategie besser, aber das ist Geschmackssache.

Zuerst richtet man ein WebUI-Programm ein, das alle 5 Minuten (periodisch, ganztägig) von 16h bis 23h55  ein Skript aufruft:

roll_nacht_anders

Das zugehörige HM-Skript ist sehr einfach:

!setzt abends Systemvariable "roll_nacht" auf "wahr" 
!www.stall.biz 10.08.2015
!Berechnung Sonnenuntergangszeit. Zeitberechnung immer im Minutenschema, 
integer SU = system.SunsetTime("%M").ToInteger() + 60* system.SunsetTime("%H").ToInteger();
!Berechnung aktuelle Zeit
integer zeit = system.Date("%M").ToInteger() + 60*system.Date("%H").ToInteger();
!Rolladen-Schliesszeit ROLL berechnet sich aus der aktuellen Sonnenuntergangszeit SU
real ROLL = 595.0 + 0.58* SU; !frühere Alternative: real ROLL = 433.0 + 0.68* SU;
if (zeit > ROLL) {dom.GetObject("roll_nacht").State(1);}
 
!Umformen von der Minutendarstellung von ROLL in Stundendarstellung hh,mm
!und abspeichern auf Systemvariable "roll_zeit_hh_mm"
real su_zeit = 0.0166 *ROLL;
real su_zeit_h = su_zeit.ToInteger();
real su_zeit_m = (su_zeit - su_zeit_h) *60.0;
su_zeit_m =0.01 * su_zeit_m.ToInteger();
real su_zeit= su_zeit_m + su_zeit_h;
dom.GetObject("roll_zeit_hh_mm").State(su_zeit);

Morgens wird die Systemvariable roll_nacht im Sommer frühestens um  6h45 auf falsch gesetzt (von 6h45 bis 9h00) . Im Winter erfolgt das später, wenn die Elevation der Sonne größer als -2° ist.

Schritt 8: Programm roll_auto_pgm installieren

Die Rolladenautomatik kann man mit dem virtuellen Taster roll_auto_manuell ein und ausschalten. Das ist wichtig, wenn man eine atypische Lebenssituation hat und dann nicht den normalen Rolladenrhytmus haben möchte. Mit dem folgenden WebUI-Programm erfolgt die Umschaltung der logischen Systemvariablen roll_AutoManuell:

roll_auto_pgm

Bei Verwendung von Fernbedienungen ist es u. U. sinnvoll, daß die Fernbedienungen nicht direkt in die Rolladensteuerung eingreifen, sondern über die virtuellen Taster.
Schritt 9 (Methode 1):  Programme für die verwendeten Rolladenaktoren installieren

Jetzt kommen wir zu den wichtigen WebUI-Programmen, die die einzelnen Rolladen, Jalousien oder Markisen steuern. Für jede Aktor-Einheit werden jeweils drei kleine WebUI-Programme angelegt.

Das erste WebUI-Programm, am Ende der Programmbezeichnung  immer mit der Ziffer 0 gekennzeichnet, steuert die Rollade in die heruntergefahrene Position (hier im Beispiel 14%).
Das zweite Programm, am Ende  der Programmbezeichnung  immer mit der Ziffer 1 gekennzeichnet, steuert die Rollade in die Beschattungsposition(hier im Beispiel 20%).
Das dritte WebUI-Programm, am Ende  der Programmbezeichnung  immer mit der Ziffer 2 gekennzeichnet, steuert die Rollade in die hochgefahrene Position (100%).

Für jede Rollade muß man sich nun überlegen, welche Betätigungsstrategie diese Rollade haben soll. Zur Betätigung stehen entsprechend dem Schemabild oben eine ganze Reihe von Sensorsignalen oder Systemvariablen zur Verfügung, die nun für diese Rollade logisch verschaltet werden können. An folgenden  Beispielen soll das Vorgehen erläutert werden:

1. Beispiel Westfenster
Zuerst wird am Beispiel eines einfach zu betätigendes Fensters rollade_kinder_west die grundsätzliche Funktion aufgezeigt. Hierbei handelt es sich um zwei nach Westen ausgerichtete Fenster, welche zur Nachtzeit und  und zur Beschattung betätigt werden. Bei Regen und bei einer bestimmeten Windgeschwindigkeit und Windrichtung werden die Fenster automatisch in die Beschattungsfunktion (20% runtergefahren) gesetzt. Die weiteren Funktionen sind eigentlich selbst erklärend.

Bitte Fehler korrigieren: bei den folgenden 6 Bildern ist roll_AutoManuell nicht nur prüfen sondern auf bei Änderung auslösen einzustellen!!

Hier das erste Programm dazu, Damit werden die Rolladen zur Nacht runtergefahren :

roll_kinder_west_0

Im folgenden zweiten Programm werden bei der Systemvariablen sonne_azimut die Grenzwerte einzeln abgefragt.

roll_kinder_west_1

Und mit dem dritten Programm werden die Rolladen wieder hochgefahren:

roll_kinder_west_2


2. Beispiel Ost-Fenstertür

Beim zweiten Beispiel handelt es sich um eine nach Osten ausgerichtete Fenstertür mit einem Fensterkontakt zur Öffnungserkennung. Ähnlich wie beim ersten Beispiel werden die Rolladen mit drei WebUI-Programmen ausgelöst:

roll_kueche_ost0

 

roll_kueche_ost1

 

roll_kueche_ost2

In diesem Beispiel wird neben dem Fensterkontakt auch noch ein Signal von einem Geräuschmelder verwendet, um die Beschattung der Küchentür nur dann auszulösen, wenn die Hausbewohner nicht da sind (keine Geräusche!). So kann man ganz individuell jeden einzelnen Rolladen „verdrahten“ und seinen Wünschen anpassen. Ich verwende beispielsweise im Wohnzimmer ein logisches Signal, das wahr ist, wenn der Fernseher an ist. In diesem Fall gehen dann nur einige bestimmte Rolladen bei Sonnenwetter runter, um die Helligkeit für das Fernsehen zu reduzieren.

Die Sache mit dem Häkchen:
Der aufmerksame Leser hat sicher schon bemerkt, daß die normalerweise selbsttätig gesetzten Häkchen für den Retrigger deaktiviert wurden. Der Grund ist, daß beim Rolladenprogramm aus Gründen der „Funkhygiene“ alle Rolladen mit Zeitverzögerung  betätigt werden. Und zudem werden alle Rolladen jeweils mit in diesem Fall drei unabhängigen Programmen betätigt. Da die einzelnen Programme aber nicht exakt gleichzeitig abgearbeitet werden, kann dies dazu führen, das manchmal einige schon mit Zeitverzögerung laufende Aktivitäten „verschluckt“ werden. Dies führt praktisch dazu, daß manchmal einige Rolladen „vergessen“ werden.  Auf solche Effekte führe ich viele seltsame Fehler zurück, die in der Vergangenheit manchmal völlig unerklärlich auftraten. Also Vorsicht und Bedacht bei Verwendung des Häkchens, wenn an mehreren Stellen der gleiche Aktor betätigt wird!

Hier eine Diskussion des Problems:  http://homematic-forum.de/forum/viewtopic.php?f=19&t=17864&p=146468&hilit=h%C3%A4kchen+retrigger#p146433

Schritt 9  (Methode 2) : Programme für die verwendeten Rolladenaktoren installieren

Insbesondere wenn man viele Rolladen hat ist eine kompaktere Gestaltung der Software sinnvoll, um eine übersichtlichere Darstellung zu bekommen. Bei dieser Methode werden für jede  Rollade nur zwei WebUI-Programme erstellt. Meine persönliche Empfehlung ist die Methode 2 !

Das erste Programm ist für den Nachtbetrieb der Rollade sowohl für HOCH als auch RUNTER verantwortlich.
Das zweite Programm ist für die Beschattung verantwortlich, auch in diesem Fall für die Funktionen HOCH und RUNTER.
Will man noch eine Abdunkelung des Raumes bei TV-Betrieb, dann fügt man eine entsprechendes drittes Programm hinzu.

1. Beispiel Westfenster
Hier die beiden Programme rollade_kinder_nacht für den Nachtbetrieb und rollade_kinder_schatten für die Beschattung:

rollade_kinder_nacht

rollade_kinder_schatten

Den „Regen“-Teil des Programmes kann man weglassen, wenn kein Regenschutz der Rolladen gewünscht ist.


2. Beispiel Ost-Fenstertür

Die folgenden beiden Programme rollade_kueche_nacht und rollade_kueche_schatten steuern die Rolläden einer Fenstertür. Mit einem Fensterkontakt  man sicher, daß man sich nicht draußen ausschließt.

rollade_kueche_nacht

rollade_kueche_schatten

3. Beispiel Südfenster

Der Vollständigkeit halber werden nachfolgend die Programme für ein Südfenster dargestellt:

rollade_dt_nacht

rollade_dt_schatten

Wichtig ist immer, daß man sich überlegt, wann und wie oft die Programme durchlaufen werden. Denn oft ist die Ursache dafür, daß die Rolladen unerwartet  in der Nacht hochgehen nicht das zuerst vermutete Nachtprogramm sondern das Schatten-Programm, welches  nachts wegen einer Variablen mit „bei Änderung auslösen“ unerwartet durchläuft und im SONST-Zweig dann die Rolladen hochfahren läßt. Die Auslöselogik bzw. die ereignisgesteuerte Funktion des WebUI ist manchmal nicht einfach zu verstehen, eigene Programmierfehler sind aber in fast allen Fällen die Ursache für ein „seltsames“  Verhalten der Rolladen!

4. Ausblick

Wichtig ist auch, daß bei Verwendung von Funk-Rolladenaktoren die verschiedenen Rolladen und Markisen nicht alle gleichzeitig hoch- oder runtergehen, wenn die die entsprechenden Systemvariablen roll_nacht oder roll_schatten umschalten.  Dabei kann so ein reger Funkverkehr entstehen, daß die eine oder andere Rollade nicht richtig betätigt wird. Die Lösung ist für jede Rollade eine unterschiedliche Zeitverzögerung von etwa 1 bis 2sec. Dabei sollte man den Rolladen mit Fenster- oder Türkontakt die kürzeren Zeiten geben, weil bei Türöffnung eine möglichst schnelle Reaktion erfolgen sollte. Ach ja, die Fenster- und Türkontakte funktionieren auch zuverlässiger, wenn in den Geräte-Einstellungen eine Meldeverzögerung von 1 bis 2sec eingestellt wird.

Und hier noch ein paar Anregungen für eigene Erweiterungen:

– Integration in die Alarmanlage: z.B. Rollen alle hoch oder runter wenn Alarm

– Verbesserung des „Fernsehvergnügens“: Rolladen machen aktive Beschattungsscenarios, wenn TV an

– Besuchs- oder Partymodus: dann bleiben die Rolladen hoch!

– im Winter den Beschattungsmodus teilweise abschalten, damit die wenige Sonnenstrahlung nutzbringend ins Haus gelangt.

– Markisen nach Wind und Wetter betätigen

– Dachfenster automatisch öffnen und schließen

– Beleuchtung im und am Haus mit den verwendeten Rolladenscenarien steuern und koordinieren

– …

Wenn man erst mal das Grundkonzept mit den verschiedenen Sensorsignalen und Systemvariablen installiert hat, dann ist die kreative Gestaltung nach den verschiedensten Wünschen an die Rolladenautomation kein Problem mehr.

Viel Spaß für mehr Licht und Schatten im Haus!

 

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.

 

 

 

 

USV für Homematic-CCU2 und Raspberry  mit wirkungsvollem Überspannungsschutz

USV für Homematic-CCU2 und Raspberry mit wirkungsvollem Überspannungsschutz

Motivation für eine unterbrechungsfreie Stromversorgung (USV) ?

Das Stromnetz ist in den meisten Gegenden Deutschland eine relativ zuverlässige Sache. Langanhaltende Stromunterbrechungen sind sehr selten. Aber kurze Stromunterbrechungen sind gar nicht so selten. Beispielsweise habe ich in meiner Wohnung eine GSM-Schaltbox, die per SMS geschaltet werden kann. Funktioniert recht gut, hat aber nur einen Nachteil, daß bei jeder kleinsten Stromunterbrechung eine Info-SMS abgeschickt wird. Seit Beginn des Jahres habe ich schon mehr als 10 solcher SMS bekommen !! Und das scheint wohl auch so richtig zu sein, denn wenn man diesen Artikel liest:
http://vik.de/pressemitteilung/items/aktuelle-vik-untersuchung-zeigt-stromversorgungsqualitaet-unter-hohem-druck-mehr-als-90-prozent-der-stromunterbrechungen-werden-.html
dann ist eine kurze  Stromunterbrechung ein gar nicht seltenes Phänomen. Darüberhinaus scheinen neben dem eigentlichen Stromausfall auch andere Probleme wie Überspannung, Unterspannung, Spannungsspitzen und hochfrequente Steuersignale zu stromausfallähnlichen Störungen zu führen. Deshalb habe ich mich entschieden, auch für meine Homematic eine sog. „unterbrechungsfreie Stromversorgung“ anzuschaffen, die genau diese Probleme beseitigen soll.

Welcher Energiespeicher für die USV?

Nach umfangreicher Google-Befragung und der verschiedenen Diskussionen  zum Thema USV im Homematic-Forum  z.B. hier : http://homematic-forum.de/forum/viewtopic.php?f=31&t=17398&start=30&hilit=usv  habe ich eine eigene USV mit Verwendung von Supercaps gebaut. Der Grund für Supercaps war die erkennbaren Lebensdauer Probleme mit chemischen Energiespeicher wie Bleibatterien, NiMH- und Lithium-Akkus bei einer notwendigen Dauerladung des Energiespeichers. Und da mittlerweile die Supercaps oder Doppelschicht-Kondensatoren sowohl preislich als auch größenmäßig sehr günstig geworden sind, habe ich mich für diese Art des Energiespeichers entschieden. In der stillen Hoffnung, daß diese Energiespeicher eine deutlich höhere Lebensdauer besitzen und keinerlei Wartung benötigen 😉

Die Schaltung

Allerdings hat so ein Kondensator anwendungstechnisch seine Tücken, weil die Spannung quadratisch mit dem Energieinhalt abnimmt. Demgegenüber haben die chemischen Akkus über einen weiten Energiebereich eine fast konstante Spannung! Um also die Energie eines Kondensators gut auszunutzen ist ein Spannungswandler (DC/DC-Konverter)  erforderlich, der den relativ großen Spannungshub des Speicherkondensators in eine konstante Spannung (bei uns 5V) umsetzen kann.Das folgende Bild zeigt den Schaltplan meiner  5V-USV:

usv_CCU2_1

Von dem Netzteil wird die USV mit 5V versorgt. Über eine Schottky-Diode mit nur 0,3V Spannungsabfall wird ein sog. Step-up DC/DC Konverter angesteuert, der daraus eine konstante Spannung von 5V macht. Das funktioniert mit dem von mir eingesetzten Modul selbst bei Eingangsspannungen bis runter  zu etwa 1,5V erstaunlich gut! Allerdings sollte man exakt das gleiche Modul verwenden, weil es sehr unterschiedlich leistungsfähige DC/DC-Konverter im Markt gibt. Dazu habe ich bestimmt 5 verschiedene solcher Fertigmodule (sog. Breakouts) detailliert durchgemessen. Das beste Modul war das hier im Bild gezeigte Modul aus der „Bucht“: http://www.ebay.de/itm/400770776961?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT oder Suchen nach Stichworten wie:  „Step Up Power Supply Module“

Für die Überbrückung des Stromausfalls werden insgesamt vier 100F(!) Doppelschicht-Kondensatoren eingesetzt. Da diese normalerweise nur 2,7V ertragen, sind sie für eine 5V-Versorgung entsprechend dem Schaltplan in Reihe verschaltet. Zusätzlich sind zur sog. Symmetrierung noch Widerstände und Zenerdioden notwendig. Die Zuschaltung bei Stromausfall erfolgt automatisch mit der zweiten Schottky-Diode vom Typ BYV10.

Zum Überspannungsschutz ist eine wirkungsvolle sog. Suppressordiode vom Typ 1N5908 eingebaut. Damit und in Verbindung mit dem DC/DC Konverter dürften Überspannungen aus dem Netz kaum zur CCU „durchschlagen“. Angezeigt wird der Status der USV mit einer DUO-LED. Leuchtet sie gelb, dann  ist alles o.k. bzw. die CCU2 wird mit 5V versorgt und vom Netzteil sind auch 5V da. Leuchtet sie rot, dann ist die Netzversorgung ausgefallen.

Eingebaut habe ich dieSchaltung in ein Kleingehäuse. Eine gedruckte Platine lohnt bei den  wenigen Bauteilen wohl kaum! Für den versierten Elektroniker ist der Aufbau sicher kein Problem. Aber bei der Verschaltung der Supercaps darauf achten, daß sie über einen Widerstand vorher entladen wurden, weil sonst Kurzschlüsse etc. zu einer Beschädigung führen können. Das ist genauso wie bei Akkus!
gehaeuse1

Etwas Theorie

Die Energie des Kondensators nimmt während des Entladens näherungsweise linear ab (siehe blaue Kennlinie im nachfolgenden Bild). Die auf 5V aufgeladenen Kondensatoren können theoretisch die CCU2 etwa 10min versorgen. Mit Verlusten und mit Berücksichtigung einer für den DC/DC-Konverter noch gut verwertbaren Minimalspannung von 2.0V ist zwar nicht die gesamte Kondensatorenergie nutzbar, aber  bei der hier gewählten Konstellation sind doch beachtliche  84% der Kondensatorenergie zur Notstromversorgung nutzbar!

entladekurve2
Meßergebnisse

Letztlich entspricht die theoretische Entladekurve auch dem praktischen Entladeverhalten. In Verbindung mit der CCU2 kann eine Zeit von 9 Minuten überbrückt werden, wenn die Kondensatoren vorher vollgeladen sind. Meßwerte für einen Raspberry-Notbetrieb habe ich noch nicht ermittelt. … wird wohl etwas weniger sein!

 

Update: Mit preisgünstigen „super capacitors“ mit 500F (2 Stück für 10€!) wären sogar deutlich mehr als 20 Minuten möglich!
http://de.aliexpress.com/item/Free-Shipping-2pcs-Super-Capacitor-Black-2-7V-500F-Farad-Capacitor-Power-Capacitor-10001/32292279913.html?recommendVersion=1

 

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.

 

Impulsgeber für den Wasserzähler selbst gebaut

Impulsgeber für den Wasserzähler selbst gebaut

Warum ein Impulsgeber für den Wasserzähler so schwierig ist!

Im Rahmen der Hausautomation ist die Information über die aktuellen Verbräuche von Strom,Gas und Wasser relativ wichtig, weil diese  Signale für verschiedenste Steuerungs- und Regelmechanismen notwendig sind. Zwar gibt es heute bereits schon entsprechende Zähler mit Impulsausgängen, aber vielfach sind noch alte Geräte eingebaut, die nur mehr oder weniger aufwendig mit geeigneten Impulsgebern ausgerüstet werden können.
Bei den Stromzählern kann man mit Reflex-Lichtschranken die rote Markierung auf der Drehscheibe abtasten und als Impulssignal weiter berarbeiten. Entsprechende Fertiggeräte gibt es bereits für diese Aufgabe und im Internet kursieren auch viele Bauanleitungen zum Selbstbau.
Bei den Gaszählern ist oft schon ein Magnet im Zählwerk vorhanden, der mit einem Reedschalter als Impulsgeber sehr einfach „digitalisiert“ werden kann.
Problematisch ist die Nachrüstung der Wasserzähler, da in der Wasseruhr die Zeiger sehr klein sind und auch die Zahnscheibe eine äußerst kleine Verzahnung hat, die mit Reflexions-Lichtschranken ohne spezielle Optik kaum zu detektieren sind.
Ich habe dazu verschiedene Versuche mit einer Infrarot Reflexions-Lichtschranke gemacht, wie sie u.a. für Stromzähler verwendet werden. Diese Sensoren werden im Internet für wenige Euros als sog. Breakouts (das sind kleine Platinen) verkauft. Das Ergebnis der Versuche mit diesen Sensoren war immer, daß die Justage extrem empfindlich und eigentlich kein reproduzierbar stabiles Impulssignal erreichbar ist.
Weitere Tests mit preiswerten Lasermodulen ergaben zwar deutlich bessere Ergebnisse, aber die Laserdioden haben meist nicht lange im Dauerbetrieb gehalten! Nach dem gleichen Prinzip arbeiten professionelle Laser-Reflexionssensoren wie der  SunX EX-26B, mit dem lt. einem Internetbeitrag wohl eine Abtastung des Wasserzählers möglich sein soll.

Wenn man die  zu dem Thema veröffentlichten Artikel zusammenfaßt, dann ist die Nachrüstung des Wasserzählers offensichtlich ein relativ schwieriges Problem. Und ich kann nach den eigenen Versuchen dies nur bestätigen!

(M)ein Lösungsansatz

Geht man wieder zurück zu der Lösung, die einem normalerweise bei dieser Meßaufgabe einfällt, dann ist man wieder wieder bei der  Infrarot-Reflexions-Lichtschranke. Die hat aber beim Wasserzähler bisher nicht richtig funktioniert, weil zu kleine Zeiger  usw. zu einem zu kleinen Nutzsignal führten.

Also was kann man tun, um das Nutzsignal zu verbessern ?
1. Man kann die Fotodiode besser fokussieren entweder mit einer Optik ( zu aufwendig!) oder mit einer Lochblende.
Ich habe dafür ein längeres Röhrchen gewählt, in das die Fotodiode eingeklebt ist.
2. Man kann die roten Zeiger mit einem Licht bestrahlen, was die Komplementärfarbe hat. Bei rot wäre das grünes Licht, was mit einer entsprechenden LED einfach darstellbar ist.

Erste Versuche mit dem grünen Licht anstelle dem infrarotem Licht waren erstaunlich besser. Die Zeiger sind mit der grünen Beleuchtung fast schwarz gegenüber dem weißen Hintergrund und haben offensichtlich einen viel besseren Kontrast. Deshalb wurde auf Basis dieser beiden Ansätze der folgende Impulsgeber  konzipiert. Hier das Kochrezept zum Nachbau:

Die elektronische Hardware

Man besorgt sich eine sog. Infrarot Reflexions-Lichtschranke. Anbieter findet man u.a. bei ebay mit den Stichworten “ TCRT5000 reflective module“. Dieses Modul hat eine Infrarot LED und eine Infrarot Photodiode, die wir für unseren Einsatz entfernen müssen. Man kann sie auslöten oder einfach mit einem Seitenschneider wegklipsen. Zur besseren Signalverarbeitung müssen wir noch einen 10kOhm SMD-Widerstand  ablöten oder wegschneiden. Im folgenden Bild sind die Änderungen erkennbar:

wasser_1

Dann brauchen wir noch eine grüne 3mm-LED und einen Phototransistor vom Typ Osram „SFH 309-5“ und verschalten das ganze entsprechend dem Schaltplan im oberen Bild.

Übrigens den Schaltplan zum Modul findet man aktuell hier:
http://www.google.de/imgres?imgurl=http%3A%2F%2Fg04.s.alicdn.com%2Fkf%2FHT1fT8kFGpbXXagOFbXP%2F220671527%2FHT1fT8kFGpbXXagOFbXP.jpg&imgrefurl=http%3A%2F%2Fwww.alibaba.com%2Fproduct-detail%2FTCRT5000-IR-Barrier-Line-Track-sensor_1800749503.html&h=586&w=750&tbnid=BdcAZhuLe2NkWM%3A&zoom=1&docid=zZ3LYeDVN9vQ8M&ei=nObpVNuOMImiygOY14HoBg&tbm=isch&iact=rc&uact=3&dur=4230&page=3&start=112&ndsp=62&ved=0CH4QrQMwKDhk

 

Die Mechanik

Die mechanische „Verpackung“ der grünen LED und des Phototransistors ist im folgenden Bild erklärt. Für die Aufnahme des Phototransistors habe ich ein 40mm langes Messingröhrchen mit Durchmesser 6mm (Baumarkt) verwendet, das zusmmen mit der seitlich angeordneten grünen Led in eine 17er-Mutter mit Sekundenkleber eingeklebt wird. Ggf. muß das Gewinde mit einem 10er-Bohrer aufgebohrt werden. LED und Phototransistor werden entsprechend dem Schaltplan verlötet und die Leitungen mit Schrumpfschluch o.ä. isoliert. Das folgende Bild sagt mehr als viele Worte.

wasser_2

Dann probiert man den Impulsgeber aus, um die richtige Position zu finden. Ich verwende für die Abtastung den Zeiger für die Literanzeige, d.h. eine Umdrehung entsprechen ein Liter Wasser. Man muß nun die richtige Position finden, indem man mit einem Voltmeter die Spannung am Phototransistor mißt. Das schon eine etwas diffizile Arbeit, um die richtige Position mit dem größten Spannungshub pro Umdrehung zu finden. Bei mir ist der Spannungshub etwa 0.15V bei einer mittleren Spannung von etwa 2,7 V (diese Spannung hängt von der Beleuchtungsstärke und vom Phototransistor ab!) .Aber die mittlere Spannung sollte etwa zwischen 1,5 u 3,5V liegen. In dieser Position kann nun der Impulsverstärker auf dem Breakout mit dem Trimmpotentiometer so eingestellt werden, daß die grüne LED auf dem Breakout an ist und nur wenn der Zeiger am Sensor vorbeigeht für kurze Zeit aus geht.

Jetzt muß der Sensor im Schauglas der wasseruhr so fixiert werden, daß  zuverlässig und haltbar die Meßposition eingehalten wird. Man kann den Sensor einkleben, aber das könnte Probleme mit dem Wasserwerk geben. Ich habe mit einfachen Mitteln einen schweren Einsatz gebaut: Dazu wurde die Sensormutter im Schauglas mit einer Reihe von anderen Mittern zusammen geklebt, so daß der Mutterverbund spielfrei im Schauglas sitzt. Vorher habe ich das Schauglas mit Küchenfolie abgedeckt, damit der Kleber nicht am Glas haftete.  Nachdem alles stabil ausgehärtet ist, wird der Mutternverbund mit 2-Komponenten-Kleber vergossen, so daß eine stabile und schwere Scheibe entsteht.

Wasserzaehler6

Diese Scheibe bekommt noch eine Markierung, daß man sie zum Ablesen der Wasseruhr einfach entnehmen kann und daß beim Wiedereinsetzen die Meßposition sicher eingestellt ist. Das sieht zwar recht bastelmäßig aus, aber die Funktion ist gut und nicht jeder hat eine Drehbank, um sich ggf. eine schwere Metallscheibe als Aufsatz bzw. Einsatz zu basteln.

That´s it!

Viel Erfolg beim Nachbau
… und bei der Justage nie die Geduld verlieren, weil das schon etwas Fingerspitzengefühl verlangt 😉

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. Auch die notwendigen Eingriffe in das Wasser- und Heizungssystem dürfen nur von ausgebildeten Fachpersonal durchgeführt werden. Es sind die geltenden Sicherheitsvorschriften und dieDVGW-Richtlinien einzuhalten.

 

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 }, //<<u