Archiv der Kategorie: WiFi

OTA, ESP8266 und Arduino IDE – ein starkes Team

gks_ota0

Einleitung

In letzter Zeit habe ich mich viel mit dem ESP8266 beschäftigt und in einigen Blogbeiträgen bereits darüber berichtet. Jetzt bin ich auf ein neues Thema gestoßen, dass ich sofort weiter teilen muss. OTA over-the-air, also Upload eines Programmes über die WiFi Schnittstelle ist vor allem da hilfreich und sinnvoll, wo ich die Schaltung nicht mehr im Zugriff habe oder wo ich keinen USB-Seriell-Wandler anschließen möchte, weil die Schaltung mit Netzspannung betrieben wird (z.B. SONOFF). Meine Begeisterung für OTA möchte ich in diesem BlogPost ausdrücken.

Obwohl ich heute meine Programme hauptsächlich auf dem WeMos D1 Mini entwickel, weil er mit seinem USB-Seriell Wandler einfach zu handhaben ist und sehr kompakt baut (Bezug z.B. über: http://stores.ebay.de/modulink) werde ich in diesem Post beschreiben, wie OTA auf einem ESP-12E funktioniert, der ja von Hause aus keinen USB-Seriell-Wandler mit sich bringt und deshalb ist OTA hier besonders interessant. Leider funktioniert OTA nicht mit dem ESP-01. 512k Speicher sind für OTA einfach zu wenig. Für OTA muss der Chip mindestens doppelt so viel Flash bereits stellen, wie das kompilierte Programm groß ist. Der OTA Loader für sich braucht schon ca. 240k.

Der OTA Loader

Als ersten Schritt muss man auf den ESP ein Programm laden, dass die Schnittstelle für OTA bereit stellt. Für diesem Schritt benötigt man natürlich einen USB-Seriell-Wandler, der wie hier beschrieben angeschlossen wird. Das von mir präferierte OTA-Basis Programm ist in einer Library enthalten, die über den Library Manager geladen wird. Dazu gehen wir in der Arduino IDE auf Sketch->Bibliothek einbinden->Bibliotheken verwalten und geben als Suchbegriff OTA ein. Die ArduinoOTA Library sollte dann als oberstes Suchergebnis erscheinen.

gks_ota1

Diese Library installieren. Unter Datei->Beispiele->ArduinoOTA->BasicOTA laden wir jetzt das Programm. Dieses Programm muss nur an zwei Stellen angepasst werden. Der ESP verbindet sich mit einem WLAN. Dafür muss im Programm die SSID und das WLAN Passwort eingetragen werden.

gks_ota2

Das Programm unter neuem Namen abspeichern. Es wird später dann als Basic Programm immer wieder als Grundgerüst verwendet.Vor dem Upload des Programms wird noch unter Werkzeuge->Board das ESP Board auswählen – in meinem Fall für den ESP-12E das NodeMCU-1.0(ESP-12E Module).

gks_ota6

Unter Werkzeuge->Port muss noch der richtige Port eingestellt werden unter dem der USB-Seriell-Wandler sichtbar ist. Im nächsten Schritt erfolgt der Upload des Programms dann wie immer mit der Abfolge
– ESP in den Programmiermodus versetzen, dazu GPIO0 auf LOW ziehen und den ESP aus- und wieder einschalten oder resetten. (Bei anderen ESP Varianten entfällt dieser Schritt ggf)
– Upload des Programms

Nach dem Upload des Programms zeigt der serielle Monitor das Einbuchen des ESP ins WLAN. Der ESP macht jetzt nichts weiter als auf ein neues Programm zu warten.

gks_ota4Nach einem Neustart der Arduino IDE sieht man jetzt einen neuen Port, der jetzt für den OTA Upload ausgewählt wird.

gks_ota5 Der Rechner, von dem die Programmierung und der Upload erfolgt, muss sich natürlich im gleichen Netz befinden.

zusätzlich benötigt – Python 2.7

Bevor es mit dem OTA Upload losgehen kann, muss noch folgendes geprüft werden. Für den Upload over-the-air nutzt die IDE ein Python Script. Dafür muss auf dem Rechner Python in der Version 2.7 installiert sein (die Version 3.x funktioniert hier nicht). Windows User können die Version 2.7 hier downloaden. Auf Linux und OSx Systemen sollte Python bereits vorinstalliert sein. Auch hier auf die Version achten. Anleitungen zur Installation von Python gibt es zahlreiche im Netz, deshalb gehe ich hier nicht ins Detail. Für Windows Nutzer ist noch wichtig, dass der Installationspfad von Python der Path Variablen hinzugefügt wird. Das kann bei der Installation als zweiter Schritt beim Setup ausgeführt werden. Unter Customize Python Add Python to path auswählen.

Erster Upload

Bis zu diesem Punkt ist der ESP mit dem BasicOTA Programm geflasht, dass momentan nichts anderes macht, als auf ein neues Programm zu warten. Das eigene Programm wird dem BasicOTA Programm hinzugefügt. Wichtig ist jetzt der Befehl  ArduinoOTA.handle();, der ganz oben in der loop() steht, dieser Befehl muss zyklisch immer wieder aufgerufen werden, weil hier geprüft wird, ob ein OTA Update ansteht. Das USB Kabel könnte jetzt prinzipiell entfernt werden, es ist aber ganz interessant beim ersten OTA Upload die Ausgabe mal anzusehen. Allerdings muss dafür eine zweite Instanz von  der Arduino IDE oder ein anderes Terminalprogramm benutzt werde. Ich nutze dafür unter Linux CuteCom, unter Windows könnte man Putty nutzen.

Als Beispiel habe ich das BasicOTA Programm um eine Ausgabe in der loop() erweitert, alle 5s wird über die serielle Schnittstelle ein Status ausgegeben. In der loop() sollte kein delay() benutzt werden, weil damit der Test, ob ein OTA Update ansteht (s.o.) für diese Zeit nicht ausgeführt würde und die IDE einen Fehler melden würde, da sie keine Antwort vom ESP bekommt.

 void loop() {
ArduinoOTA.handle();
if (millis() - lastmillis >  5000) {
Serial.print("still running since ");
Serial.print(millis()/1000);
Serial.println(" seconds");
lastmillis = millis();
}
} ... 

(edit nach Hinweis von Wolfgang) Zusätzlich wird die globale Variable

unsigned long lastmillis; 

im oberen Teil des Programms definiert.
Das Programm wird jetzt wie gewohnt über den Upload Button auf den ESP geladen. Es ist nicht notwendig, den ESP in den Programmiermodus zu versetzen oder zu resetten. Ein sehr erfreulicher Nebeneffekt ist beim Upload zu sehen, der Upload geht sehr viel schneller als über die serielle Schnittstelle. Wenn ein Terminal offen ist, wird der Upload Fortschritt auch hier angezeigt. Sobald der Upload abgeschlossen ist, resettet sich der ESP und startet das neue Programm.

gks_ota7

Anmerkungen zur Sicherheit

Solange man sich im eigenen Netz befindet und man sich sicher fühlt, kann man das BasicOTA so nutzen, wie es bereitgestellt wird. Es wäre aber prinzipiell möglich für jemanden, der sich im selben Netz befindet, einen SW Upload zu starten. Es gibt 2 Möglichkeiten, das zu erschweren. Im BasicOTA Code kann der IP-Port, unter dem der ESP gefunden wird, verändert werden, standardmäßig ist hier Port 8266 gesetzt. Zusätzlich kann man ein Passwort setzen, dass dann in der IDE vor dem Upload abgefragt wird.
Darüber hinaus muss man sich genau überlegen, was das laufende Programm möglicherweise gerade macht, wenn der Upload beginnt. Hat der ESP gerade das Wasserventil geöffnet, um den Garten zu bewässern, muss man sichergehen, dass das Ventil geschlossen wird, bevor der Upload beginnt.
Im BasicOTA Code sind deshalb Programm-Module vorgesehen, die beim Upload zu einem bestimmten Status aufgerufen werden.

   ArduinoOTA.onStart([]() {
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});

Hier kann man eigenen Code einbauen, der einen definierten Zustand herstellt, also die o.g. Ventile schließt oder einen Status ins EEPROM schreibt. Da nach dem Upload der ESP resettet wird, wird eh das gesamte setup() durchlaufen.

Ausblick

Das Verfahren des Programm Uploads over-the-air in der beschriebenen Form ist für den Entwicklungsprozess aus der IDE vorgesehen. Für Schaltungen, die sich in anderen Netzen befinden gibt es die Möglichkeit des Uploads über Webserver (von einem Rechner aus dem gleichen Netz) z.B. von jemandem, der mit der Arduino IDE nicht vertraut ist oder über einen Server in einem anderen Netz, wo sich der ESP selbstständig eine neue Software abholt. Diese Varianten habe ich aber noch nicht erprobt, deshalb kann ich nicht näher darauf eingehen.

 

 

Werbung

Sony Camera Remote Control mit ESP8266

Einleitung

Seit kurzem bin ich begeisterter Besitzer einer Sony DSC-HX90V. Für die Fernsteuerung dieser Kamera hat Sony eine WiFi Schnittstelle eingebaut und bietet eine App für Smartphones an, siehe PlayMemories. Leider gibt es keine weitere Schnittstelle (IR, elektrisch, Funk) um die Kamera remote zu bedienen.

Die Idee

Warum also sollte man die Kamera nicht über die WiFi Schnittstelle fernsteuern und damit gleichzeitig eine Schnittstelle per Mikrocontroller schaffen. Eine Realisierung einer WiFi Remote für eine GoPro wurde vor kurzem auf Hackaday vorgestellt. Eine Suche nach entsprechenden Programmen für Sony Kameras war ohne Erfolg. Auch die Sony Dokumentation der API brachte mich nicht weiter, da ich kein Android programmiere.
Über das ESP8266 Forum, fand ich zumindest Interessierte mit der gleichen Idee, aber keine Lösung.

ESP_Sony3

Reverse Engineering zur Lösung

Durch Zufall stieß ich auf die TimeLapse App von Thibaud Michel.
Mit Hilfe eines WiFi PacketAnalysers habe ich mir auf dem Tablett das Protokoll näher angeschaut und dann mit der Sony Doku der APK verglichen.
ESP_Sony1
Nach einiger Recherche fand ich heraus, dass es sich um ein einfaches HTTP POST Verfahren handelt mit der Übergabe der Parameter in einem json Format. Das nachzubilden mit dem ESP8266 war nur noch Fleißarbeit.

Proof of Concept

Die hier vorgestellte Lösung ist ein erster „Proof of Concept“ ohne jegliches Fehlerhandling und soll zunächst nur die Funktion des Schnittstelle darstellen. An einem ESP8266-01 ist lediglich ein Pushbutton zur Auslösung der Kamera angeschlossen der Rest ist Programm. Als Test wurde das Programm auf meinem Prototyp Board entwickelt. Auf diesem Board ist die 3,3V Stromversorgung und der FTDI zur Programmierung und zur Ausgabe von Debug Informationen fest verbunden. Der ESP8266 ist steckbar. Einzige zusätzliche Komponente ist der Pushbutton zur Fernauslösung der Kamera. Eine Beschreibung des Protoboards und die Einbindung der ESP8266 Libraries in die Arduino IDE findet sich hier. Die prinzipielle Verschaltung hier. Der Code ist ausführlich kommentiert und weicht nicht erheblich von den bekannten WiFiClient Codes ab, sollte also leicht verständlich sein. Auf eine Auswertung der json Antworten der Kamera wurde verzichtet.

//----------------------------------------------------------------------------------------------------------------------
// This program is based on: WiFiClient from ESP libraries
//
// Camera handling by Reinhard Nickels https://glaskugelsehen.wordpress.com/
// tested with DSC-HX90V, more about protocol in documentation of CameraRemoteAPI https://developer.sony.com/develop/cameras/
// 
// Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence:
// http://creativecommons.org/licenses/by-sa/3.0/
//
// Requires Arduino IDE with esp8266 core: https://github.com/esp8266/Arduino install by boardmanager
//----------------------------------------------------------------------------------------------------------------------

#include <ESP8266WiFi.h>
#define DEBUG 1
#define BUTTON 2   // pushbutoon on GPIO2
volatile int counter;

const char* ssid     = "DIRECT-GKC2:DSC-HX90V";
const char* password = "5uv2LSwj";     // your WPA2 password

const char* host = "192.168.122.1";   // fixed IP of camera
const int httpPort = 8080;

char JSON_1[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"getVersions\",\"params\":[]}";
char JSON_2[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"startRecMode\",\"params\":[]}";
char JSON_3[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"startLiveview\",\"params\":[]}";
char JSON_4[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"stopLiveview\",\"params\":[]}";
char JSON_5[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"actTakePicture\",\"params\":[]}";
// char JSON_6[]="{\"method\":\"getEvent\",\"params\":[true],\"id\":1,\"version\":\"1.0\"}";


unsigned long lastmillis;

WiFiClient client;

void setup() {
  Serial.begin(115200);
  delay(10);

  pinMode(BUTTON, INPUT_PULLUP);
  attachInterrupt(2, pulleddown, FALLING);  // handled by interrupt to debounce

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {   // wait for WiFi connection
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);
  httpPost(JSON_1);  // initial connect to camera
  httpPost(JSON_2); // startRecMode
  httpPost(JSON_3);  //startLiveview  - in this mode change camera settings  (skip to speedup operation)
}

void loop() {
  if (buttonpressed()){
    Serial.println("pressed..");
    httpPost(JSON_4); //stopLiveview    (skip to speedup operation)
    httpPost(JSON_5);  //actTakePicture
    httpPost(JSON_3);  //startLiveview    (skip to speedup operation)
    }
}

void httpPost(char* jString) {
  if (DEBUG) {Serial.print("Msg send: ");Serial.println(jString);}
  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  else {
    Serial.print("connected to ");
    Serial.print(host);
    Serial.print(":");
    Serial.println(httpPort);
  }

  // We now create a URI for the request
  String url = "/sony/camera/";

  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("POST " + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n"));
  client.println("Content-Type: application/json");
  client.print("Content-Length: ");
  client.println(strlen(jString));
  // End of headers
  client.println();
  // Request body
  client.println(jString);
  Serial.println("wait for data");
  lastmillis = millis();
  while (!client.available() && millis() - lastmillis < 8000) {} // wait 8s max for answer

  // Read all the lines of the reply from server and print them to Serial
  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  Serial.println();
  Serial.println("----closing connection----");
  Serial.println();
  client.stop();
}

void pulleddown()  // Interrupt handler
{
  counter++;
}

boolean buttonpressed() {  // function to check if pressed
  if (counter!=0) {  
    counter=0;
    delay(10);     // je nach Schalter 
    if (counter==0 && !digitalRead(BUTTON)) return true;
  }
  return false;
}
 

ESP_Sony2

Bedienung

Für die Funktion muss auf der Kamera die aktuelle Version der Smart-Fernbedienung (das Gegenstück für die PlayMemories App) installiert sein.

Im Programm muss die SSID und das Passwort der benutzten Kamera eingetragen werden. Die Kamera wird nach dem Einschalten über das Menue in den Fernsteuermodus gebracht. Nach dem Einschalten des ESP8266 wird die Verbindung zur Kamera hergestellt und die Kamera wird in einen Modus versetzt, wo Einstellungen (Zoom, Blende, Zeit, …) möglich sind.

Ein Druck auf den Pushbutton löst die Kamera aus und die Kamera kehrt in den vorhergehenden Modus zurück.

Über die serielle Schnittstelle werden Debug Informationen ausgegeben, hier ein Beispiel nach dem Einschalten des ESP bis nach der ersten Fernauslösung der Kamera.

Connecting to DIRECT-GKC2:DSC-HX90V 
....... 
WiFi connected 
IP address:  
192.168.122.115 
Msg send: {"version":"1.0","id":1,"method":"getVersions","params":[]} 
connecting to 192.168.122.1 
connected to 192.168.122.1:8080 
Requesting URL: /sony/camera/ 
wait for data 
HTTP/1.1 200 OK
Connection: close
Content-Length: 51
Content-Type: application/json

{"result":[["1.0","1.1","1.2","1.3","1.4"]],"id":1} 
----closing connection---- 
 
Msg send: {"version":"1.0","id":1,"method":"startRecMode","params":[]} 
connecting to 192.168.122.1 
connected to 192.168.122.1:8080 
Requesting URL: /sony/camera/ 
wait for data 
HTTP/1.1 200 OK
Connection: close
Content-Length: 21
Content-Type: application/json

{"result":[0],"id":1} 
----closing connection---- 
 
Msg send: {"version":"1.0","id":1,"method":"startLiveview","params":[]} 
connecting to 192.168.122.1 
connected to 192.168.122.1:8080 
Requesting URL: /sony/camera/ 
wait for data 
HTTP/1.1 200 OK
Connection: close
Content-Length: 75
Content-Type: application/json

{"result":["http:\/\/192.168.122.1:8080\/liveview\/liveviewstream"],"id":1} 
----closing connection---- 
 
pressed.. 
Msg send: {"version":"1.0","id":1,"method":"stopLiveview","params":[]} 
connecting to 192.168.122.1 
connected to 192.168.122.1:8080 
Requesting URL: /sony/camera/ 
wait for data 
HTTP/1.1 200 OK
Connection: close
Content-Length: 21
Content-Type: application/json

{"result":[0],"id":1} 
----closing connection---- 
 
Msg send: {"version":"1.0","id":1,"method":"actTakePicture","params":[]} 
connecting to 192.168.122.1 
connected to 192.168.122.1:8080 
Requesting URL: /sony/camera/ 
wait for data 
HTTP/1.1 200 OK
Connection: close
Content-Length: 108
Content-Type: application/json

{"result":[["http:\/\/192.168.122.1:8080\/postview\/memory\/DCIM\/100MSDCF\/DSC01272.JPG?size=Scn"]],"id":1} 
----closing connection---- 
 
Msg send: {"version":"1.0","id":1,"method":"startLiveview","params":[]} 
connecting to 192.168.122.1 
connected to 192.168.122.1:8080 
Requesting URL: /sony/camera/ 
wait for data 
HTTP/1.1 200 OK
Connection: close
Content-Length: 75
Content-Type: application/json

{"result":["http:\/\/192.168.122.1:8080\/liveview\/liveviewstream"],"id":1} 
----closing connection---- 
 

Video

Video (Downloadlink):

Fazit und Ausblick

Dieser Blogeintrag beschreibt in einfacher Weise die grundsätzliche Funktion der WiFi Fernsteuerung einer Sony Kamera. Die Funktionsweise lässt sich zumindest auf die Kameras übertragen, die PlayMemories kompatibel sind. Möglicherweise ist dann die Serveradresse der Kamera zu modifizieren. Der Schritt zu komplexeren Lösungen ist reine Programmierarbeit. Ersetzt man den Pushbutton mit einer Zeitschleife kann man sehr einfach die Einzelbilder für TimeLapse Videos (Zeitraffer) aufnehmen. Die Auslösung kann natürlich auch durch Sensoren (Annäherung, Bewegung, …) erfolgen. Prinzipiell ist auch der Start und Stop einer Videoaufnahme (Kamera im Videomodus) möglich. Die entsprechenden json Kommandos sind in der Doku der APK enthalten. Wenn man auf den Modus „Liveview“ verzichtet ist die Auslöseverzögerung nur minimal (siehe Kommentar im Code, diese Zeilen dann auskommentieren), allerdings verliert man dann die Möglichkeit Kameraeinstellungen zu ändern. Für einen Batteriebetrieb ist der ESP8266 bekanntermaßen nicht so gut geeignet, aber für einen einzelnen Shot braucht es nicht viel Zeit. Für Timelapse Projekte wäre es sicher sinnvoll den Sleep Mode des ESP zu nutzen (was bei der Bauform ESP-01 nicht funktioniert ohne Modifikation). Ich würde hier das Modell ESP-12 empfehlen, das außerdem CE und FCC zertifiziert ist.

 

Addendum2 zum Tutorial – Speicherung von MySQL DB Werten mit ESP8266

Nachdem ich mich in meinen letzten Blogs intensiv mit dem ESP8266 auseinandergesetzt habe, steht logischerweise eine Erweiterung meines Tutorials zur Speicherung von Messwerten in eine MySQL DB unter Verwendung des ESP8266 an. Das Programm wurde weitestgehend analog dem bisherigen Programm aufgebaut, so dass es relativ einfach zu verstehen sein sollte.  Im Programm müssen noch die persönlichen Daten für das WLAN und den Host eingetragen werden.

/* 
 Programm zur Speicherung von Messwerten in einer webbasierten MySQL DB
  based on standard programs of the ESP8266Wifi library 
  and examples on sparkfun.com
 */
 
#include <ESP8266WiFi.h>
#define CYCLE 60000

const char* ssid     = "hier deine SSID";
const char* password = "und das Passwort des WLANs";
const char* host = "hier deinen Host eintragen";
unsigned long value = 0;
unsigned int lastcall = CYCLE;
int conn_time;

void setup() {
  Serial.begin(115200);
  delay(10);

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    conn_time++;
    if (conn_time > 20) {
      break;
    }
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
  }
  else {
    Serial.println("");
    Serial.println("no WiFi connection");
    ESP.deepSleep(100000);
    Serial.println("gone to sleep");
  }
}

void loop() {
  while (millis() - lastcall < CYCLE) {
    delay(1);
  }
  lastcall = millis();
  ++value;

  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  // We now create a URI for the request
  String url = "/w2mysql.php";
  url += "?A0=";
  url += millis();
  url += "&A1=";
  url += value;
 
  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(1000);

  // Read all the lines of the reply from server and print them to Serial
  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }

  Serial.println();
  Serial.println("closing connection");
}

Arduino WiFi für unter 3 Euro – der ESP8266

IMG_20150116_090344

In den letzten Monaten ist ein regelrechter Hype ausgebrochen um den ESP8266, ein Chip aus chinesischer Entwicklung, der auf einer winzigen Fläche sowohl Access Point als auch WiFi Client sein kann. Inzwischen exisitieren verschiedene Breakout Boards, die zunächst eine UART-WiFi Schnittstelle bereitstellen und auf eBay für unter 3 Euro gehandelt werden. Da der Chip einen 32bit Prozessor enthält kann er aber auch mit eigener Firmware bestückt werden. Ich möchte mich hier nicht näher mit Details beschäftigen, da es bereits viele Webseiten zu diesem Thema gibt. Eine kurze und knappe Zusammenfassung auf deutsch mit Verlinkung zu weiteren Seiten hat das FabLab Nürnberg erstellt.

Inzwischen konnte ich einige Erfahrungen mit diesem Modul machen und solange man kein Highspeed WiFi braucht ist das Modul eine gute Wahl und macht für kleines Geld IoT möglich. Die ersten Versuche mit diesem Modul habe ich in Verbindung mit einem Arduino MEGA gemacht. Der MEGA hat mehrere in Hardware implementierte serielle Schnittstellen, so kann man sowohl die Verbindung zum Computer als auch die Verbindung zum ESP8266 mit 115200 Baud laufen lassen. In den neueren Firmwares des ESP ist die Baudrate aber auch einstellbar, so dass ein Betrieb an einer SoftSerial Schnittstelle bei z.B. 9600 Baud, damit an einem UNO, auch möglich ist.  Die Verbindung des ESP an den MEGA muss über Pegelwandler 5V->3.3V erfolgen, die Schnittstelle ist hier nicht tolerant. Ich habe die Verbindung von TX (MEGA) zu RX (ESP) über einen Spannungsteile aus 1k und 2.2k herunter geteilt. Der ESP braucht einen eigenen 3.3V Spannungswandler, der 3.3V Ausgang des Arduino liefert zu wenig Strom für den ESP (max 200mA).

Für erste Experimente, bei denen die AT Befehle „per Hand“ eingegeben werden, eignet sich das folgende kurze Programm.

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
  Serial.println("Program started");
}

void loop() {
  if(Serial1.available()) {   
    char ser = Serial1.read();
    /*if (ser==10) {         // kann genutzt werden, um ein Gefühl für die Antwortzeiten zu bekommen
      Serial.print("  ");
      Serial.print(millis());
    }*/
    Serial.print(ser);
  }
  if(Serial.available()) {   
    char ser = Serial.read();
    Serial1.print(ser);
  }
}

Die meisten Einstellungen des Chip bleiben über ein Power on Reset bestehen. Es ist also nicht notwendig, im Programm die Einstellungen jedes mal neu zu setzen. Ich habe mir zu diesem Zweck ein Programm erstellt mit den wichtigsten Einstellungen (Access Point, SSID, PASS, Client usw.). Mit diesem Programm mache ich die Grundkonfiguration des Chip.

// ESP_Minimal.ino - sketch to quickly view and change some of ESP8266 parameters
// most of the ESP parameters are stored in eeprom, so also outlive the power on reset
// special thanks to http://rayshobby.net/?p=9734
// sketch is written for ArduinoMega, ESP connected with voltage devider to Serial1
// This code is in the public domain.

#define SET // for just viewing parameters, set this as comment

#define BUFFER_SIZE 512
#define esp Serial1
#define dbg Serial //For debugging purposes

char buffer[BUFFER_SIZE];
char OKrn[] = "OK\r\n";
int mode;

boolean wait_for_esp_response(int timeout, char* term=OKrn) {
 unsigned long t=millis();
 bool found=false;
 int i=0;
 int len=strlen(term);
 // wait for at most timeout milliseconds
 // or if OK\r\n is found
 while(millis()<t+timeout) {
 if(esp.available()) {
 buffer[i++]=esp.read();
 if(i>=len) {
 if(strncmp(buffer+i-len, term, len)==0) {
 found=true;
 break;
 }
 }
 }
 }
 buffer[i]=0;
 dbg.print(buffer);
 return found;
}

void setup() {
 esp.begin(115200); //esp baud rate
 dbg.begin(115200); //debugger baud rate
 dbg.println("start of program ...");
 esp.println("AT"); // check for existence of ESP8266
 if (!wait_for_esp_response(1000)) {
 dbg.println("no ESP found");
 while(true); // hang forever
 }
 // some important checks of operation modes
 esp.println("AT+CWMODE?"); // check mode 1=Client, 2=AP, 3=both
 wait_for_esp_response(1000);
 char *result = strstr(buffer, "+CWMODE:");
 if (result!=0) {
 mode=atoi(result+8);
 if (mode!=1) {
 esp.println("AT+CWSAP?"); // actual AP configuration
 }
 if (mode!=3) {
 esp.println("AT+CWJAP?"); // actual connected WiFi
 wait_for_esp_response(1000);
 }
 }

 esp.println("AT+CIPMUX?"); // check connection mode 0=single, 1=multiple
 wait_for_esp_response(1000);
 esp.println("AT+CIPMODE?"); // check data mode 0=normal, 1=transparent
 wait_for_esp_response(1000);
 esp.println("AT+CIFSR"); // actual IP adress
 wait_for_esp_response(1000);

#ifdef SET
 esp.println("AT+CWMODE=3"); // set mode 1=Client, 2=AP, 3=both
 wait_for_esp_response(1000);
 // set AP or Client
 esp.println("AT+CWMODE?"); // check mode 1=Client, 2=AP, 3=both
 wait_for_esp_response(1000);
 result = strstr(buffer, "+CWMODE:");
 if (result!=0) {
 if (mode!=1) { // AP settings
 esp.println("AT+CWSAP=\"ESP_9F2556\",\"blablabla\",1,3"); // set AP: SSID, PASS, channel, encryption
 wait_for_esp_response(1000); // 0=open, 1=WEP, 2=WPA_PSK, 3=WPA2_PSK, 4=WPA_WPA2_PSK
 }
 if (mode!=2) { // Client settings
 esp.println("AT+CWJAP=\"yourSSID\",\"passphrase\""); // connect client to AP
 wait_for_esp_response(5000); // was really that long!
 }
 }

#endif

 esp.println("AT+RST"); // RESET, necessary for some changes of settings
 wait_for_esp_response(3000, "ready");
}

void loop() {

}

Die zu ändernden Parameter werden direkt im Code verändert. Wenn die erste Zeile #define SET auskommentiert wird, werden die wichtigsten Parameter nur angezeigt.

Arduino goes Wireless

Die Experimente zu meinem Tutorial  „Speicherung von Arduino Messdaten auf Webserver und deren Darstellung“ setzten alle auf einen Arduino mit Ethernet Shield zur Verbindung mit dem Internet auf. Nun gibt es Situationen, wo kein Ethernet Anschluss in Reichweite ist, trotzdem aber die Verbindung ins Internet benötigt gewollt ist. Oder es ist Mobilität gefordert, während Daten übertragen werden. Das Arduino Wifi Shield wäre eine Lösung, ist aber mit fast 70€ eine sehr kostspielige und zusätzlich muss das Programm daraufhin angepasst werden. Eine wesentlich kostengünstigere und ohne Anpassung des Programms einsetzbare Lösung ist ein Wireless Client. Ich habe mich für den TP-Link TL-WR702N entschieden, der schon inklusive Versand für weniger als 20€ zu bekommen ist.

IMG_20150114_181434

Der TL-WR702N ist im Auslieferungszustand ein Access Point, für unsere Anwendung muss er aber als Client oder als Bridge konfiguriert werden. Der TL-WR702N stellt als Client über WLAN die Verbindung zum Access Point her, der Arduino mit Ethernet Shield wird mit dem TL-WR702N über die Ethernet Schnittstelle verbunden und verhält sich genauso, wie bei direkter Verbindung nur über Ethernet.

Die Konfiguration als Client ist im Handbuch ausreichend beschrieben, deshalb möchte ich hier nicht näher darauf eingehen. Einen Sonderfall möchte ich an dieser Stelle näher beschreiben, nämlich, wenn ich keinen Rechner zur Verfügung habe, den TL-WR702N zu konfigurieren. Eine Konfiguration über Wireless, z.B. mit einem Smartphone oder Tablet ist im Handbuch nicht beschrieben.

Nachfolgend gehe ich davon aus, dass der TL-WR702N im Auslieferungszustand vorliegt. Dieser Zustand kann jederzeit hergestellt werden, indem der Reset Taster mit einem spitzen Gegenstand z.B. einer aufgebogenen Büroklammer, für ca. 7 Sekunden gedrückt wird, bis die Betriebs LED mehrmals kurz blinkt. Die nachfolgenden Schritte habe ich mit meinem Nexus 7 durchgespielt, mit anderen Geräten kann das leicht variieren.

Zunächst verbinde ich mich mit dem Tablet auf den Access Point des TL-WR702N. Die SSID, nach der ich suche, steht auf dem Typenschild des TL-WR702N, ebenso die zugehörige Passphrase.

Screenshot_2015-01-14-16-45-17_bea

Wenn ich die Verbindung hergestellt habe, wird mein Tablet eine IP aus dem 192.168.0.x Netz erhalten haben. Im Browser des Tablet gebe ich 192.168.0.254 ein, die IP des TL-WR702N zur Konfiguration. In der Abfragemaske wird für User: admin und Passwort: admin eingegeben. Wir kommen auf die Konfiguration des Routers und Erstellen eine Konfiguration für eine Bridge.

Screenshot_2015-01-14-16-59-39

Der Vorteil der Bridge Konfiguration ist, dass ich später noch über WLAN auf die Konfigurationsschnittstelle komme, um Änderungen zu machen. Das ist im Client Modus nur über Ethernet möglich. Wichtig ist jetzt, dass über Quick Setup gegangen wird, sonst verliert man nach Reboot die Konfigurationsseite. Also Quick Setup, Next, Bridge, Next.

Screenshot_2015-01-14-17-08-36

Unter Survey sehe ich die zur Verfügung stehenden WLANs und kann den gewünschten Access Point direkt mit connect auswählen. Nach Eingabe des Password für dieses WLAN gehe ich weiter mit Next. Wenn die Meldung erscheint „Your AP channel is not the same as the Bridged AP’s channel, do you want to change your channel to the Bridged AP’s channel?“ kann ich das mit OK bestätigen. Im nächsten Fenster wird kann die bestehende Verschlüsselung bestätigt werden oder eine neue Passphrase vergeben werden. Mit Next kommt man auf das letzte Fenster zum Reboot des Routers.

Screenshot_2015-01-14-17-14-33

Beim Reboot verliere ich die Verbindung zur Konfiguration des Routers. Mein Tablet verliert möglicherweise auch die Anbindung zu Access Point oder verbindet sich zu einem anderen bekannten Access Point. Eigentlich ist jetzt alles fein und ich kann mein Ethernet Shield mit dem Router verbinden und loslegen. Wenn ich die Konfiguration mit dem Tablet bearbeiten will, muss ich die IP des Routers herausfinden. Wenn ich nicht die Möglichkeit habe, die IP auf meinem Router nachzusehen, kann ich folgenden Trick anwenden. Die Android App Ping-Tools hilft mir dabei. Ich stelle über das Menü links oben die Funktion UPnP scanner ein und schon sehe ich meinen TP-Link mit seiner IP-Adresse.

Screenshot_2015-01-14-17-22-38

Über diese IP in der Browserzeile komme ich jetzt wieder auf die Konfigurationsschnittstelle, falls ich noch etwas ändern möchte. Sinnvoll wäre z.B. die Änderung des Standard Passworts für den Admin Zugang.

Der Stromverbrauch des TL-WR702N liegt übrigens nur bei ca, 150mA. Bei einer mobilen Anwendung kann der Router also ohne weiteres aus der 5V Schnittstelle des Arduino mit versorgt werden oder Arduino und der TL-WR702N werden über eine Powerbank mit USB Schnittstelle versorgt.

Als nächstes steht jetzt ein Test mit dem TP-Link TL-MR3020 an, der für unter 30€ mit gleichem Verfahren einen Arduino ins 3G/4G Mobilfunknetz und damit ins Internet bringt. Zusätzlich ist nur ein USB Stick mit Mobilfunkkarte notwendig.