2015
HOME
Steuern mit Bluetooth
Steuern mit WLAN I
Steuertn mit WLAN III

Dauerbetrieb mit ESP8266 - Weltweites Schalten/Steuern - IoT
LED-Chat oder
Steuern mit WLAN II

Ergänzung zum eBook "Messen und Steuern mit dem Smartphone"
Mit EasyTCP kann man mit dem ESP8266 via WLAN chatten. Sprachsteuerung per Handy.
Vor über fünfzehn Jahren fanden auf dieser Seite Versuche zum Messen und Steuern über das Internet statt. Damals liefen große und laute Desktop-PC auf beiden Seiten und die Internetverbindung erfolgte über Telefon-Modem. Heute kann mit einem Gespann aus Arduino und ESP8266 drahtlos und energiefreundlich von jedem Internetanschluss der Welt gesteuert und gemessen werden.

Als Szenario soll ein Ferienhaus dienen, in dem einige Dinge über das Internet (IoT) gesteuert werden sollen. Ein Wlan-Router z.B. eine alte Fritzbox, sei dort vorhanden und dauerhaft online. Vor Ort befindet sich ein Grundaufbau, wie er hier schon eingesetzt wurde.

Eine solche Steuerung muss allerdings einige Bedingungen erfüllen, damit sie wartungsfrei funktioniert. Um dieses Ziel zu erreichen, waren einige Dauertests nötig, die mit der Version 1 des ESP8266 und der Betriebssystemversion 0018000902-AI03 schließlich erfolgreich für einen möglichen privaten Anwendungsfall endeten.
Noch wechselt hier die externe IPv4 in jeder Nacht, so dass eine dynamische IP - übrigens wie vor 15 Jahren - benutzt werden muss. Der TCP-Commander nimmt zur Zeit nur numerische IP-Adressen an, viele andere Apps aber auch eine URL, so wie das nebenstehende EasyTCP aus dem Play-Store. Damit kann man dann quasi per Chat die Dinge im Internet steuern. Im Beispiel wird allerdings nur die "1" ausgewertet, der Rest ist reine Spielerei, muss es aber nicht bleiben. RFO-Basic unterstützt erfreulicherweise in seinem Aufruf SOCKET.CLIENT.CONNECT ebenfalls URL-Namen.


Reset Hosenträger und Gürtel

Der hier verwendete Aufbau funktioniert recht zuverlässig, es treten jedoch ab und zu Fehler auf, die nicht immer reproduzierbar sind. Ein ungekoppeltes Bluetooth-Gerät z.B. könnte in der Nacht zu Aussetzern geführt haben, was in einem unsteuerbaren Zustand endete. Um diese und andere Probleme im Dauerbetrieb aus der Welt zu schaffen wird quasi die Holzhammer-Methode benutzt - oder auch brute, force and ignorance.

Ein Timer sorgt dafür, dass in regelmäßigen Abständen ein Reset des ESP8266 erfolgt. Damit der Baustein nicht automatisch in den Tiefschlaf fällt, erfolgt zusätzlich noch ein periodischer 'Chat'. Im Detail kann das dann so aussehen:

unsigned long t0,t1,tg;
void espReset()
{if(analogRead(A0)==0 || millis()>(t1+RRTIME))
{Serial.println("AT+RST");espReadLine(3000);t1=millis();}
 for(int i=0;i<5;i++)
 {Serial.println(startup[i]);espReadLine(0);}
}

Dabei sind die drei Zeitvariablen t0, t1 und tg für diese Zeitaufgaben deklariert. Im Setup werden sie initialisiert, die Zeitintervalle selber sind als Konstanten definiert:

#define RTIME   180000 //TRIGGER ESP every RTIME  ms (3 min)
#define RRTIME  900000 //RESTART ESP every RRTIME ms (15 min) 
#define GOTIME  (8*RRTIME) //GOIP-Refresh 2 hour interval

void setup()
{pinMode(LED,OUTPUT); Serial.begin(9600); 
 t0=millis();t1=t0;tg=t0;
 espReset();
}

Der eigentliche Timer ist nur eine Abfrage, ob die entsprechende Zeit schon verstrichen ist und erfolgt am Ende der Hauptschleife:

void loop()
{
 ...
 if(millis()>(t0+RTIME)){espReset();t0=millis();}
 ...
}

Nach 3 Minuten erfolgt eine Initialisierung, die aber die Verbindungen nicht trennt. Alle 15 Minuten erfolgt zusätzlich ein Reset, der dafür sorgen soll, mögliche Fehler oder Hänger zu beheben. Für die hiesige Anwendung führte das zu 'erträglichen' Zeiten bei sporadisch auftretenden Blockierungen oder Fehlern.

Dynamische IP Feste Internetadresse
Autonomes Dauer-'testbed' mit ESP8266, TFT-Display und einem iPod-Touch 2G.
Um immer unter der selben URL erreichbar zu sein ist normalerweise eine feste IP erforderlich. Da die Provider hier jedoch meist in der Nacht eine neue IP im privaten Bereich verteilen, nutzt die IP von 'gestern' heute nichts mehr.

Viele Router bieten Lösungen, mittels eines Anbieters dieses Problem zum Zeitpunkt der Neuvergabe zu lösen. Die hier vorhandene FritzBox weigert sich jedoch den Anbieter 'goip.de' richtig zu benachrichtigen. Da eine vom Router unabhängige Methode sowieso vor zu ziehen ist, soll dies über den ESP8266 selber erledigt werden.

Bei goip.de erfolgt die Aktualisierung mit dem folgenden Aufruf im Browser nach dem Muster:

http://www.goip.de/setip? username=meinname&password=meinpasswort

Die URL wäre dann "meinname.goip.de" und eine feste IP ist dann nicht mehr erforderlich. Um global erreichbar zu sein, muss im Router noch der Port freigegeben sein. Im Testlauf war das Port 333 für den ESP als Gerät 192.xxx.xxx.26 im lokalen Netz (AT+CIFSR).

Da der Aufruf nicht zu oft erfolgen darf, wird hier ein Intervall von 2 Stunden fest eingestellt, wodurch möglicherweise in der Nacht nach dem Wechsel etwa 120 Minuten keine (Fern-)Steuerung erfolgen kann. Die Abfrage der externen IP ist mit AT-Befehlen möglich und könnte mit der alten IP verglichen werden, um die goip-Aufrufe zu minimieren. Hier der Teil des Sketches zur Aktualisierung im 2 Stunden-Takt:

#define URL "goip.de"
#define DOMAIN "GET http://www.goip.de/setip?username=meinname&password=...\r\n"

void goip()
{char s[80];
 String cmd="AT+CIPCLOSE=4";// disconnect #4 if con
 Serial.println(cmd);espReadLine(0);
 cmd="AT+CIPSTART=4,\"TCP\",\"";cmd+=URL;cmd+="\",80";
 Serial.println(cmd);espReadLine(1000);
 cmd=DOMAIN;sprintf(s,"AT+CIPSEND=4,%d",cmd.length());
 Serial.println(s);  espReadLine(1000);
 Serial.print(cmd);  espReadLine(1000);
}

Als Antwort erhält der ESP8266 in etwa:

***********************************************************

GoIP.de Updater

***********************************************************

Aktualisierung wurde erfolgreich durchgeführt.


EOT

Dabei werden mögliche Empfangsfehler ignoriert, da nur die richtige Anfrage bei goip.de wichtig ist. Dieses Verfahren könnte auch mit anderen Dynamischen Diensten bei entsprechender Anpassung erfolg haben.


End of Test Nach einer Woche
Ein Endcheck wurde in 200 km Entfernung über drei Tage durchgeführt. Dabei waren quasi nur die Standorte vertauscht. Sowohl die erweiterte RFO-Basic-Variante als auch die EasyTCP-App funktionierten wie erwartet. Auch die eingeplanten kurzen Intervalle, die zu Verbindungsproblemen führen können, traten auf; sie waren aber nach drei Minuten wieder beseitigt. Der Gesamtsketch ohne TFT-Ansteuerung sieht dann so aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// ----------------------------------------------
// ESP8266/ARDUINO : Relay/Relais Pin 7 
// H000 - H255     : PWM Pin 6
// DynDNS/GOIP     : Global Control (IoT)
// http://hjberndt.de/soft/ardesp8266goip.html
// ----------------------------------------------

#define LED 7 // Relais/Relay
#define SLD 6 // Helligkeit/Brightness
#define RTIME   180000 //TRIGGER ESP every  RTIME ms (3 Min)
#define RRTIME  900000 //RESTART ESP every RRTIME ms (15 Min) 
#define GOTIME  (8*RRTIME) //GOIP-Refresh 2 hour interval
#define URL "goip.de"
#define DOMAIN "GET http://www.goip.de/setip?....\r\n"

char *startup[]={"ATE0","AT+CWMODE=3","AT+CIPMUX=1",
                 "AT+CIPSERVER=1","AT+CIPSTATUS"};

unsigned long t0,t1,tg;

void espReset()
{if(analogRead(A0)==0 || millis()>(t1+RRTIME))
 {Serial.println("AT+RST");delay(2000);espReadLine(1000);
  t1=millis();}
 for(int i=0;i<5;i++)
 {Serial.println(startup[i]);espReadLine(0);}
}

void goip()
{char s[80];
 String cmd="AT+CIPCLOSE=4";// disconnect #4 if con
 Serial.println(cmd);espReadLine(0);
 cmd="AT+CIPSTART=4,\"TCP\",\"";cmd+=URL;cmd+="\",80";
 Serial.println(cmd);espReadLine(1000);
 cmd=DOMAIN;sprintf(s,"AT+CIPSEND=4,%d",cmd.length());
 Serial.println(s);  espReadLine(1000);
 Serial.print(cmd);  espReadLine(1000);
}

void setup()
{pinMode(LED,OUTPUT); Serial.begin(9600); 
 t0=millis();t1=t0;tg=t0;
 espReset();
}
 
char *espReadLine(int ms)
{char t[20],s[80]; //buffer
 if(ms)delay(ms);
 int len=Serial.readBytesUntil('\n',s,sizeof(s)-4); s[len]=0;
 return s;
}  

void loop()
{int id,len;char t[10],s[80]; 
 if(3==sscanf(espReadLine(0),"+IPD,%d,%d:%s",&id,&len,s))
 {switch (s[0])
  {case '0':digitalWrite(LED,LOW);break;
   case '1':digitalWrite(LED,HIGH);break;
   case 'H':analogWrite (SLD,(atoi(strncpy(t,&s[1],3))));break;
  }
  sprintf(s,"AT+CIPSEND=%d,12",id);// +\r\n
  Serial.println(s);espReadLine(0);// message to id
  Serial.println(digitalRead(LED)?"LED is ON ":"LED is OFF");
 }
 if(millis()>(t0+RTIME)){espReset();t0=millis();}
 if(millis()>(tg+GOTIME)){goip();tg=millis();}
}


Fazit
Für den privaten Gebrauch gewinnt hier die WLAN-Lösung im Vergleich zu Bluetooth aufgrund der Reichweite. Das ist zwar so nicht vergleichbar, aber nur über TCP/IP sind globale Distanzen zu überwinden.


Weitere Software
.
Startseite Bücher Software Digital RTV Musik Kontakt

Für Inhalt und weitere Verzweigung externer Links sind die Betreiber der dortigen Seiten verantwortlich - H.-J. Berndt