Wettbewerbsbeitrag: Blumenwächter

Beitrag zum Kalenderwettbewerb 2015 von Leander Hackmann: Jeder hat Topfpflanzen. Sie verschönern unseren Alltag, benötigen jedoch auch häufig unsere Aufmerksamkeit in Form von Pflege. Um den besten Standort herauszufinden und das regelmäßige Giessen nicht zu vergessen, habe ich folgende Anwendung mit dem Iot-Board entworfen und umgesetzt: ein Datenlogger für Licht und Feuchtigkeit. Download des Programms Das Programm //Blumenwaechter für das NanoESP-Board //2016 von Leander H. //Misst alle 30min. Feuchtigkeit und Helligkeit //Mit Druck auf Taster kann ein Nullpunkt in der Messung als markanter Punkt gesetzt werden# //Es werden zwei Channels auf Thingspeak.com verwendet (API-Keys in "LightKEY und "MoistureKEY") //Über "threshold" kann der Pegel zur Warnung eingestellt werden //Code und Idee von Leander H. -- Funktionen von Fabian Kainka #include SoftwareSerial.h> #include Time.h> //Setup-Bereich #define SSID "[SSID]" #define PASSWORD "[Passwort]" #define LightKEY "[API-KEY]" #define MoistureKEY "[API-KEY]" #define threshold 400 // #define DEBUG true #define LED_WLAN 13 SoftwareSerial esp8266(11, 12); // RX, TX int ledGreen = 5; int ledYellow = 4; int ledRed = 3; int sensorPower = 2; int moistSensor = 2; String lastminute; const byte thingPost[] PROGMEM = { 80, 79, 83, 84, 32, 42, 85, 82, 76, 42, 32, 72, 84, 84, 80, 47, 49, 46, 49, 10, 72, 111, 115, 116, 58, 32, 97, 112, 105, 46, 116, 104, 105, 110, 103, 115, 112, 101, 97, 107, 46, 99, 111, 109, 10, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 58, 32, 99, 108, 111, 115, 101, 10, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 120, 45, 119, 119, 119, 45, 102, 111, 114, 109, 45, 117, 114, 108, 101, 110, 99, 111, 100, 101, 100, 10, 67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 32, 42, 76, 69, 78, 42, 10, 10, 42, 65, 80, 80, 69, 78, 68, 42, 10 }; void setup() { pinMode(ledGreen, OUTPUT); pinMode(ledYellow, OUTPUT); pinMode(ledRed, OUTPUT); pinMode(sensorPower, OUTPUT); Serial.begin(19200); esp8266.begin(19200); while(!espConfig()){ //Failsafe für WLAN delay(200); } digitalWrite(LED_WLAN, HIGH); while(!getTime("chronic.herokuapp.com", "/utc/in+one+hours") == false){ //Failsafe für Zeitsynchro delay(200); } sendThingPost(LightKEY, analogRead(A0)); //Erste Übermittlung digitalWrite(sensorPower, HIGH); delay(200); int tmp = analogRead(A2); sendThingPost(MoistureKEY, tmp); digitalWrite(sensorPower, LOW); if(tmp threshold){ digitalWrite(ledRed, HIGH); digitalWrite(ledGreen, LOW); }else{ digitalWrite(ledRed, LOW); digitalWrite(ledGreen, HIGH); } } void loop() { String shour, sminute, ssecond; if (hour() 9) shour = "0" + String(hour()); else shour = String(hour()); // adjust for 0-9 if (minute() 9) sminute = "0" + String(minute()); else sminute = String(minute()); if (second() 9) ssecond = "0" + String(second()); else ssecond = String(second()); //debug(shour + ":" + sminute + ":" + ssecond); if(sminute == "0" || sminute == "30"){ //Wird zur halben und vollen Stunde ausgeführt if(sminute != lastminute){ digitalWrite(ledYellow, HIGH); if(sendThingPost(LightKEY, analogRead(A0) == false)){ while(sendThingPost(LightKEY, analogRead(A0) == false)){ sendThingPost(LightKEY, analogRead(A0)); delay(200); } } digitalWrite(ledYellow, LOW); delay(500); digitalWrite(ledYellow, HIGH); digitalWrite(sensorPower, HIGH); delay(100); if(sendThingPost(MoistureKEY, analogRead(A2) == false)){ while(sendThingPost(MoistureKEY, analogRead(A2) == false)){ sendThingPost(MoistureKEY, analogRead(A2)); delay(200); } } digitalWrite(sensorPower, LOW); digitalWrite(ledYellow, LOW); digitalWrite(sensorPower, HIGH); delay(100); int tmp = analogRead(A2); digitalWrite(sensorPower, LOW); if(tmp threshold){ digitalWrite(ledRed, HIGH); digitalWrite(ledGreen, LOW); }else{ digitalWrite(ledRed, LOW); digitalWrite(ledGreen, HIGH); } lastminute = sminute; } } if(analogRead(A1) > 500){ //Button zum Setzen eines Nullpunktes digitalWrite(ledYellow, HIGH); sendThingPost(LightKEY, 0); digitalWrite(ledYellow, LOW); delay(500); digitalWrite(ledYellow, HIGH); sendThingPost(MoistureKEY, 0); digitalWrite(ledYellow, LOW); delay(1000); } } //Verwendete Funktionen von Fabian Kainka folgen ab hier: //-----------------------------------------ThingsSpeak Functions------------------------------------ boolean sendThingPost(String key, int value) { boolean succes = true; String Host = "api.thingspeak.com"; String msg = "field1=" + String(value); succes &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK"); String postRequest = createThingPost("/update", key, msg); if (sendCom("AT+CIPSEND=" + String(postRequest.length()), ">")) { esp8266.print(postRequest); esp8266.find("SEND OK"); if (!esp8266.find("CLOSED")) succes &= sendCom("AT+CIPCLOSE", "OK"); } else { succes = false; } return succes; } String createThingPost(String url, String key, String msg) { String xBuffer; for (int i = 0; i sizeof(thingPost); i++) { char myChar = pgm_read_byte_near(thingPost + i); xBuffer += myChar; } String append = "api_key=" + key + "&" + msg; xBuffer.replace("*URL*", url); xBuffer.replace("*LEN*", String( append.length())); xBuffer.replace("*APPEND*", append); return xBuffer; } String createThingGet(String url, String key) { String xBuffer; for (int i = 0; i sizeof(thingPost); i++) { char myChar = pgm_read_byte_near(thingPost + i); xBuffer += myChar; } String append = "api_key=" + key; xBuffer.replace("POST", "GET"); xBuffer.replace("*URL*", url); xBuffer.replace("*LEN*", String( append.length())); xBuffer.replace("*APPEND*", append); return xBuffer; } String createThingGet(String url, String key, String msg) { String xBuffer; for (int i = 0; i sizeof(thingPost); i++) { char myChar = pgm_read_byte_near(thingPost + i); xBuffer += myChar; } String append = "api_key=" + key + "&" + msg; xBuffer.replace("POST", "GET"); xBuffer.replace("*URL*", url); xBuffer.replace("*LEN*", String( append.length())); xBuffer.replace("*APPEND*", append); return xBuffer; } String getTCP(String Host, String Subpage) { boolean succes = true; succes &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK"); String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n\r\n"; succes &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">"); return sendCom(getRequest); } boolean getTime(String Host, String Subpage) { boolean succes = true; int xyear, xmonth, xday, xhour, xminute, xsecond; //lokal variables succes &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK"); String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n"; succes &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">"); esp8266.println(getRequest); if (esp8266.find("+IPD")) { if (esp8266.find("\r\n\r\n")) { xyear = esp8266.parseInt(); xmonth = esp8266.parseInt(); xday = esp8266.parseInt(); xhour = esp8266.parseInt(); xminute = esp8266.parseInt(); xsecond = esp8266.parseInt(); if (xday 0) xday *= -1; //Because of date seperator - parseInt detects negativ integer if (xmonth 0) xmonth *= -1; //Because of date seperator - parseInt detects negativ integer setTime(xhour, xminute, xsecond, xday, xmonth, xyear); sendCom("AT+CIPCLOSE", "OK"); return true; } else return false; } else return false; } //-----------------------------------------Config ESP8266------------------------------------ boolean espConfig() { boolean succes = true; esp8266.setTimeout(5000); succes &= sendCom("AT+RST", "ready"); esp8266.setTimeout(1000); if (configStation(SSID, PASSWORD)) { succes &= true; debug("WLAN Connected"); debug("My IP is:"); debug(sendCom("AT+CIFSR")); } else { succes &= false; } //shorter Timeout for faster wrong UPD-Comands handling succes &= sendCom("AT+CIPMODE=0", "OK"); //So rum scheit wichtig! succes &= sendCom("AT+CIPMUX=0", "OK"); return succes; } boolean configTCPServer() { boolean succes = true; succes &= (sendCom("AT+CIPMUX=1", "OK")); succes &= (sendCom("AT+CIPSERVER=1,80", "OK")); return succes; } boolean configTCPClient() { boolean succes = true; succes &= (sendCom("AT+CIPMUX=0", "OK")); //succes &= (sendCom("AT+CIPSERVER=1,80", "OK")); return succes; } boolean configStation(String vSSID, String vPASSWORT) { boolean succes = true; succes &= (sendCom("AT+CWMODE=1", "OK")); esp8266.setTimeout(20000); succes &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\"" + String(vPASSWORT) + "\"", "OK")); esp8266.setTimeout(1000); return succes; } boolean configAP() { boolean succes = true; succes &= (sendCom("AT+CWMODE=2", "OK")); succes &= (sendCom("AT+CWSAP=\"NanoESP\",\"\",5,0", "OK")); return succes; } boolean configUDP() { boolean succes = true; succes &= (sendCom("AT+CIPMODE=0", "OK")); succes &= (sendCom("AT+CIPMUX=0", "OK")); succes &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.255.255\",90,91,2", "OK"); //Importand Boradcast...Reconnect IP return succes; } //-----------------------------------------------Controll ESP----------------------------------------------------- boolean sendUDP(String Msg) { boolean succes = true; succes &= sendCom("AT+CIPSEND=" + String(Msg.length() + 2), ">"); //+",\"192.168.4.2\",90", ">"); if (succes) { succes &= sendCom(Msg, "OK"); } return succes; } boolean sendCom(String command, char respond[]) { esp8266.println(command); if (esp8266.findUntil(respond, "ERROR")) { return true; } else { debug("ESP SEND ERROR: " + command); return false; } } String sendCom(String command) { esp8266.println(command); return esp8266.readString(); } //-------------------------------------------------Debug Functions------------------------------------------------------ void serialDebug() { while (true) { if (esp8266.available()) Serial.write(esp8266.read()); if (Serial.available()) esp8266.write(Serial.read()); } } void debug(String Msg) { if (DEBUG) { Serial.println(Msg); } } Das Programm misst zur vollen und halben Stunde (Zeit wird aus dem Internet bezogen) Helligkeit und Feuchtigkeit, um diese dann in zwei Graphen auf Thingspeak.com zu schreiben. Bei zu trockener Erde (der Wert „threshold“ muss individuell angepasst werden, bei mir lag der Wert für feuchte Erde bei rund 400) leuchtet dann eine rote LED und ansonsten eine grüne. Die Stromzufuhr für den Feuchtigkeitssensor (ein Spannungsteiler), wird nur periodisch eingeschaltet, um Elektrolyse in der Erde zu vermeiden. Außerdem müssen Graphitelektroden (z.B. Bleistiftminen) verwendet werden, um die Pflanze nicht durch Ionen einer Elektrolyse zu vergiften (besonders bei Kupfer besteht Gefahr). ...

25.01.2016 · 7 Minuten · Fabian Kainka

Schnellstart mit dem NanoESP - Teil2

In diesem Artikel finden Sie Auszüge aus einem meiner ersten Bücher „Schnellstart mit dem Arduino Micro“. Ich habe den Text etwas für das NanoESP-Board angepasst. Screenshots etc. können aber immer noch Text für einen anderen Arduino enthalten. Gedacht ist dieser Artikel vor allem für diejenigen, die sich für das NanoESP-Board (Pretzelboard) interessieren, aber noch nie mit Arduino gearbeitet haben. Vorbereitung Nach dem theoretischen Einstieg in die Arduino-Welt ist es nun an der Zeit, sich mit den praktischen Grundlagen zu beschäftigen. Als ersten Schritt sollte man sich ein praktikables System für die Hardwareaufbauten aneignen. Für den NanoESP bietet sich ein mittleres bis großes Steckboard an. ...

07.12.2015 · 12 Minuten · Fabian Kainka

Schnellstart mit dem NanoESP für Arduino Neulinge

In diesem Artikel finden Sie Auszüge aus einem meiner ersten Bücher “Schnellstart mit dem Arduino Uno”. Ich habe den Text etwas für das NanoESP-Board angepasst. Screenshots etc. können aber immer noch Text für einen anderen Arduino enthalten. Gedacht ist dieser Artikel vor allem für diejenigen, die sich für das NanoESP-Board (Pretzelboard) interessieren, aber noch nie mit Arduino gearbeitet haben. Teil 1: Schnellstart Schnellstart Ich schätze es juckt Ihnen schon seit dem Öffnen des Paketes in den Fingern, ein Programm auf Ihrem Arduino auszuprobieren. Deshalb gibt es hier noch vor anderen wichtigen Informationen eine Schnellstartanleitung und ein paar Beispiele. ...

02.12.2015 · 10 Minuten · Fabian Kainka

Der Kalender-Wettbewerb 2015: Sensoren im Internet Of Things

Zur Liste mit allen Beiträgen Entwickeln Sie ein eigenes Projekt mit den Bauteilen aus den Elektronik-Kalender 2015 und dem Internet of Things Kalender in Verbindung mit dem NanoESP-Board (im IoT-Kalender enthalten) und nehmen Sie am Wettbewerb teil! Falls Sie den Kalender nicht haben, können Sie trotzdem teilnehmen, denn die Bauteile sind leicht zu besorgen. Der NanoESP wird ab Anfang Dezember ebenfalls im Einzelverkauf erhältlich sein. Der Aufbau kann gesteckt oder gelötet sein, ganz egal wie. Einsendeschluss ist der 31.01.2016. Aber Sie können jetzt schon loslegen und Ihren Beitrag einsenden oder selbst auf Instructables.com veröffentlichen. ...

09.11.2015 · 2 Minuten · Fabian Kainka

Der Conrad Adventskalender: Internet of Things

In den letzen Monaten war ich ziemlich eingespannt. Grund dafür war, dass Franzis am Anfang des Jahres zu mir gekommen ist mit dem Auftrag, einen Adventskalender mit dem Thema Internet of Things zu entwickeln. Eine spannende Aufgabe wie ich fand und habe mich gleich ans Werk gemacht. Heraus kam nicht nur ein Adventskalender, sondern auch ein Entwicklungsboard, dass ich NanoESP getauft habe (denn es besteht quasi aus einem Arduino Nano Replikat und einem ESP8266 WLAN Modul). Franzis verkauft ab Anfang Dezember das Board unter dem Namen Pretzelboard und Conrad wollte auch eine eigene Version, die den Namen C-Controll IoT WiFi Board trägt. Der Inhalt ist allerdings immer der selbe: eine WLAN fähiges, Arduino kompatibles Entwicklungsboard für einen moderaten Preis (Einzelverkaufspreis 29,95€). Zum Zeitpunkt, an dem ich den Artikel schreibe, ist das Board allerdings nur im Adventskalender zu bekommen. Dieser enthält neben dem Board noch einige praktische Bauteile. Welche genau wird an dieser Stelle noch nicht verraten. Details zum Board kann man aber auf der eigens für das Thema Internet of Things und NanoESP erstellten Webseite ...

01.11.2015 · 2 Minuten · Fabian Kainka

Grafikdisplays programmieren

In Zusammenarbeit mit Thomas Baum ist ein spannendes und vielseitiges Lernpaket rund um das Thema Grafikdisplay programmieren entstanden. Hauptbestandteil des Pakets ist ein stromsparendes Display-Shield für Arduino Boards, auf dem sich zusätzlich noch zwei programmierbare Buttons befinden. Anhand von 20 praxisnahen Versuchen bekommt der Leser Schritt für Schritt die Grundlagen des Displayprogammierung vermittelt. Egal ob es um das einfach Darstellen von Text oder das Zeichnen von geometrischen Figuren geht, für jeden Anwendungsbereich gibt es ein praktisches Projekt. Egal ob handliches Oszilloskop für die schnelle Messung nebenbei oder grafische Statusmonitor eines SmartHomes, man bekommt immer gleich einen Eindruck für was das Gelernte gut sein könnte. Um das Paket abzurunden gibt es am Ende noch ein Spiel, nämlich das beliebte Flappy Birds. So kann man nach all dem neuen Wissen noch einmal richtig abschalten. ...

01.10.2015 · 2 Minuten · Fabian Kainka

RGB Crossfade Library

Die Crossfade-Library von Radek Wierzbicki ist aus einem Arduino Artikel zum Thema Crossfade entstanden. Sie ermöglicht es unter anderem Farben zu definieren, und zwar nach dem Schema: RGBColor white = RGBColor(100, 100, 100); Die Werte werden in Prozent angegeben, das Maximum ist also 100. Quellen: Crossfade-Library Auf Github in Unterordner Libraries/RGB-LED Diese Farben können dann per Crossfade-Befehl oder per setColor-Befehl ausgegeben werden. Funktionen der Library: RGBLED(int redPin, int greenPin, int bluePin, int hold, int wait, int commonAnode); void crossfade(RGBColor &color); void setColor(RGBColor &color); void setIntensity(int intensity); void setCrossfadeWait(int wait); void setCrossfadeHold(int hold); In der Initialisierungsfunktion RGBLED werden in den ersten drei Parametern die einzelnen Pins angegeben, an denen die Farben liegen. Danach folgen die Festlegung der Standartwere für Hold und Wait. Zuletzt kann man noch festlegen ob die RGB-LED eine gemeinsame Anode (int = 1) oder Kathode (int = 0) hat. Dies ist wichtig, da bei einer gemeinsamen Anode die PWM-Werte umgekehrt werden müssen. ...

19.04.2015 · 2 Minuten · Fabian Kainka

Remote App - NetIO

In diesem Artikel möchte ich eine einfache Möglichkeit vorstellen sich eine eigene Smartphone Fernbedienung zusammenzustellen. Ich möchte gleich am Anfang darauf hinweisen, dass die App leider nicht kostenlos ist. Für Android Geräte kostet die App zu dem Zeitpunkt an dem der Artikel geschrieben wurde 4.99€. In Apples App-Store muss man sogar 10,99€ bezahlen. Dennoch denke ich, dass der Preis bei dem Service nicht völlig ungerechtfertigt ist. Die Webseite Das Designen einer eigenen Steueroberfläche geschieht einfach über die Internetseite: ...

12.04.2015 · 2 Minuten · Fabian Kainka

Arduino IR RGB Controller

In diesem Projekt habe ich mich daran versucht, einen gängigen RGB-Controller mit leichten Veränderungen nachzuprogrammieren. Diese RGB-Controller werden meist beim Bestellen von RGB-Bändern mitgeliefert und sind über eine ebenfalls mitgelieferte IR-Fernbedienung steuerbar. Es gibt zwei gängige Varianten: 24-Taste und 44-Taste. In diesem Projekt habe ich eine 24-Tasten Fernbedienung verwendet. In das Programm habe ich einige Veränderungen gegenüber den bekannten RGB-Controllern eingebaut. Zum einen erfolgt der Farbwechsel immer über ein Crossfade von ca. einer Sekunde. Außerdem ist die Startfarbe immer ein Gelbton, ebenfalls innerhalb von einer Sekunde gefaded, um die Augen an den Lichtwechsel zu gewöhnen. Die automatischen Programme sind ebenfalls angepasst. Sie lassen sich im Programm einfach anpassen. Dazu später mehr. ...

05.04.2015 · 4 Minuten · Fabian Kainka

ESP8266 in der Arduino IDE

Vor kurzem kam die Meldung bei verschiedenen Online-Magazinen, dass findige Entwickler nun eine eigene Arduino IDE mit integriertem Support für das WLAN-Modul ESP8266 entwickelt haben (Beitrag auf Electronic-Lab ; Link ESP8266.com ; Github mit Download). Es handelt sich hierbei um eine angepasste Arduino IDE, die man alternativ zur eigentlichen IDE installieren kann. Beim stöbern im Forum habe ich aber auch eine Möglichkeit entdeckt, bei der die notwendigen Dateien einfach in die bestehende Arduino Version (ab 1.6) eingebunden werden können ...

01.04.2015 · 3 Minuten · Fabian Kainka