Gliederung


ESP-01 Modul


ESP-07 Modul


ESP-12 Modul


NodeMCU Board


Mein ESP-12 "Starter-Kit"


WiFi Monitor mit RGB-LED und ESP-01 (Quelltext)

Startseite

ESP8266 Module - Starter Anleitung

Der ESP8266 von Espressif ist ein 32bit Mikrocontroller mit integrierter WLAN Schnittstelle. Die Firmware basiert auf dem Lightweight TCP/IP stack (lwIp) von Adam Dunkels. Es werden zahlreiche handliche Module mit diesem Mikrochip verkauft. Am rechten Rand habe ich eine kleine Auswahl davon abgebildet. Mit diesen Produkten kannst Du eigene WLAN-fähige Geräte bauen.

Normalerweise werden die ESP-Module mit der sogenannten "AT-Firmware" verkauft, die es ermöglicht, sie so ähnlich wie analoge Modems zu benutzen. Der seriell angeschlossene Computer oder Mikrocontroller sendet Befehle an das Modul, um Verbindungen aufzubauen, Daten zu senden und zu empfangen. In meinem Buch Einstieg in die Elektronik mit Mikrocontrollern habe ich gezeigt, wie man auf diese Weise einen kleinen Webserver zum Fernsteuern einer Lampe baut.

Man kann aber auch anstelle der AT-Firmware eigene Programme an die Kern-Firmware anhängen und direkt durch den ESP Chip ausführen lassen. Die Kern-Firmware ist ein Stück Binärcode, der zusammen mit den nötigen Header Dateien kostenlos bereitgestellt wird.

Mit Preisen um 5 Euro sind die ESP Module mit großem Abstand die preisgünstigste Lösung für den Bau netzwerkfähiger Geräte. Allerdings muss man Abstriche bei Zuverlässigkeit in Kauf nehmen.

Technische Daten

Die wichtigsten technischen Daten des Chips sind: *) Durchschnittliche Werte, bei mir zu Hause mit Ping gemessen. Hängt sehr stark von der Auslastung des WLAN Netzes ab.

Ich kann bestätigen, dass der ESP8266 Chip an drei aufladbaren NiMh Zellen funktioniert, obwohl sie mit bis zu 4,4 Volt eigentlich zu viel Spannung abgeben. Ratsam ist das allerdings nicht.

Deep-Sleep / Power-Down

Per Software kann man den Deep-Sleep Modus aktivieren. Die Programmausführung stoppt und alle I/O-Pins außer GPIO16 sind inaktiv. Man kann GPIO16 mit dem /RESET-Eingang verbinden und dann einen Timer aktivieren, so dass sich der Chip selbst resetted um diesen Zustand wieder zu verlassen.

Außerdem kann man den Chip durch Low Pegel am ENABLE Eingang (auch CH_PD genannt) in den Power-Down Modus versetzen, aber erst nachdem die Firmware gestartet ist. Die Firmware startet neu, sobald der Enable Pin zurück auf High geht.

In beiden Fällen ist der Neustart mit einem Verlust des RAM Inhaltes verbunden. Im Deep-Sleep und Power-Down Modus nimmt der ESP Chip zusammen mit seinem Flash Speicher ca. 25µA bei 3,3V auf.

Wenn der /RESET Eingang auf Low gezogen wird nimmt der Chip ca. 25mA auf. Wenn der Enable zu früh (bevor die Firmware gestartet ist) auf Low gezogen wird, nimmt der Chip ebenfalls ca. 25mA auf und die Firmware startet nicht. Die Firmware startet danach erst, wenn sowohl /RESET als auch ENABLE auf High gehen.

Module

ESP-01 Modul

Das ESP-01 Modul wurde früher mit 512k Byte, heute jedoch mit 1M Byte Flash Speicher ausgestattet. Die Besonderheit bei diesem Modul ist die kleine 8-Polige Stiftleiste. Die Minimal-Beschaltung zur Nutzung der AT-Firmware sieht so aus:


Modul PinNummer in ArduinoNummer in NodeMCUNameBeschreibung
139RxD (GPIO3)serieller Eingang oder normaler I/O Pin
2  VCCSpannungsversorgung 3,3V 500mA
303GPIO0Muss zum normalen Start offen sein oder auf High liegen, Low beim Start aktiviert Firmware-Upload
4  /RESETLow=Reset, hat schwachen Pull-Up Widerstand auf High
524GPIO2Muss beim Start offen sein oder durch einen Widerstand auf High gezogen werden, flackert beim Start
6  ENABLEMuss auf High gezogen werden, damit der Chip arbeitet. Low=Power Down
7  GNDMasse
8110TxD (GPIO1)serieller Ausgang oder normaler I/O Pin, ist mit der blauen LED verbunden, flackert beim Start
Auf dem ESP-01 Modul befindet sich eine rote Power-LED, die zusätzlich zu den oben genannten 25µA etwa 1mA Strom aufnimmt. Die blaue LED ist mit TxD verbunden, sie leuchtet bei Low Pegel.

GPIO0 und GPIO2 haben beim Starten eine besondere Funktion, die ich im Kapitel Firmware Hochladen beschreibe.

Die Reichweite der primitiven Antenne (Leiterschleife) ist mit Smartphones vergleichbar.

ESP-07 und ESP-12 Modul

Das ESP-07 Modul ist normalerweise mit 1M Byte Flash, einer Keramikantenne und einer Steckbuchse für externe Antennen ausgestattet. Es hat alle sinnvoll nutzbaren Pins herausgeführt. Es gibt außerdem die komplett abgeschirmte Variante ESP-07S, die man nur mit externer Antenne betreiben kann.

Das ESP-12 Modul hat mehr Pins (die allerdings nichts nutzen) und ist meistens mit 4M Byte Flash ausgestattet. Als Antenne dient eine aufgedruckte Leiterschleife.

Die Minimal-Beschaltung zur Nutzung der AT-Firmware sieht für beide Module so aus:


Modul PinNummer in ArduinoNummer in NodeMCUNameBeschreibung
1  /RESETLow=Reset, hat schwachen Pull-Up WIderstand auf High
2  ADCAnaloger Eingang 0...1V
3  ENABLEMuss auf High gezogen werden, damit der Chip arbeitet. Low=Power Down
4160GPIO16Wenn mit /RESET verbunden, kann ein Timer den µC aus dem Deep-Sleep aufwecken.
5145GPIO14 (SCK)Normaler I/O Pin oder SPI Takt
6126GPIO12 (MISO)Normaler I/O Pin oder SPI Daten
7137GPIO13 (MOSI)Normaler I/O Pin oder SPI Daten
8  VCCSpannungsversorgung 3,3V 500mA
9-14Durch den Flash Speicher belegt, nicht verwendbar, nur beim ESP-12 vorhanden
15  GNDMasse
16158GPIO15muss beim Start auf Low gezogen werden, flackert beim Start
1724GPIO2Muss beim Start offen sein oder durch einen Widerstand auf High gezogen werden, flackert beim Start, ist mit der blauen LED verbunden.
1803GPIO0Muss zum normalen Start offen sein oder auf High liegen, Low beim Start aktiviert Firmware-Upload
1942GPIO4Normaler I/O Pin
2051GPIO5Normaler I/O Pin
2139RxD (GPIO3)serieller Eingang oder normaler I/O Pin
22110TxD (GPIO1)serieller Ausgang oder normaler I/O Pin, flackert beim Start
Auf dem ESP-07 Modul befindet sich eine rote Power-LED, die zusätzlich zu den oben genannten 25µA etwa 1mA Strom aufnimmt. Die blaue LED ist mit GPIO2 verbunden und leuchtet bei Low Pegel.

GPIO0, GPIO2 und GPIO15 haben beim Starten eine besondere Funktion, die ich im Kapitel Firmware Hochladen beschreibe.

Die Reichweite der primitiven Antenne (Leiterschleife) ist mit Smartphones vergleichbar. Mit einer guten externen Antenne soll das ESP-07 sogar weiter kommen.

NodeMCU Board

Das NodeMCU Board besteht im Grunde genommen aus einem ESP-12 mit USB-UART Interface und Spannungsregler. Alle Anschlusspins sind heraugeführt und beschriftet, daher spare ich mir hier die Tabellarische Auflistung. Das Board hat einen Reset Taster, und einen Taster an GPIO0, damit man Firmware hochladen kann (siehe unten). Für die erstem Programmierversuche (egal ob mit oder ohne NodeMCU Software) ist das die ideale Ausstattung, und zudem sehr preisgünstig.

USB-UART Kabel

Während das NodeMCU Board schon einen USB-UART Adapter enthält, brauchst du für andere Module ein USB-UART Kabel. Es soll mit 3,3V Signalpegeln arbeiten. Zum Schutz vor Vertauschung der Leitungen habe ich an die Enden meines USB-UART Kabels Widerstände angelötet und mit Schrumpfschlauch umhüllt. So ausgestattet taugt das Kabel auch für andere Anwendungsfälle, zum Beispiel für AVR Mikrocontroller die mit 3V bis 5V versorgt sind.

Für USB-UART Kabel mit gefälschtem PL2303 Chip habe ich hier einen passenden alten Windows Treiber, denn der aktuelle Treiber mag diese Chips nicht. Nach der Installation sucht man das Gerät im Gerätemanager und klickt auf "Treiber aktualisieren". Dann soll Windows den PC nach verfügbaren Treibern durchsuchen (Aus einer Liste von Gerätetreibern auf dem Computer wählen). Dort wählst du dann nicht den aktuellen Treiber aus, sondern den alten v3.3.2.105 aus dem Jahr 2008.

Maßnahmen gegen Fehlfunktionen

Sporadische Fehlfunktionen werden meistens durch mangelhafte Stromversorgung verursacht.

Da die Stromaufnahme sehr starke Spitzen hat, empfehle ich dringend, einen 100µF Kondensator direkt an die VCC und GND Anschlüsse zu löten. Außerdem sollte man den Spannungsregler sorgfältig auswählen. Einige Low-Drop Regler und manche Schaltnetzteile sind ungeeignet, weil sie die extremen Stromschwankungen zu träge ausregeln. Ich habe gute Erfahrungen mit dem LF33CV gemacht, der eignet sich auch für den Betrieb an Batterien bis knapp unter 3 Volt.

Die Masse Leitungen sollen möglichst kurz sein und sternförmig zusammen laufen. Achte darauf, dass alle steckbaren Verbindungen zur Stromversorgung gut fest sitzen. Steckbretter sind daher nicht so gut geeignet.

Damit der Chip sich nicht ungewollt zurück setzt, sollte man sowohl den RESET Pin als auch den ENABLE Pin (=CH_PD) entweder direkt oder durch einen 2,2k Ohm Widerstand mit VCC verbinden. Zu große Widerstände machen die Pins für elektromagnetische Wellen von der Antenne empfänglich. Das gilt übrigens auch für sämtliche weitere Elektronik in der Nähe des Funkmoduls.

Im Kapitel Fallstricke weiter unten findest Du weitere Hinweise, die bei der Programmierung eigener Firmware zu beachten sind.

Firmware Hochladen

Die Anschlüsse GPIO0, GPIO2 und GPIO15 haben beim Starten eine besondere Bedeutung. Nach dem Start können sie jedoch als programmierbare I/O Pins verwendet werden.
GPIO0GPIO2GPIO15Modus
High oder offenHigh durch Widerstand oder offenLowNormaler Bootvorgang vom Flash Speicher
LowFirmware Upload über seriellen Port
Alle anderen Kombinationen sind ungültig und bewirken, dass der Chip nicht startet. Daraus ergibt sich die folgende sinnvolle Grundschaltung:

Die Widerstände vor GPIO0 und GPIO15 schützen vor Kurzschluss, falls man den Pin als Ausgang programmiert. Wenn der Wakeup-Jumper verbunden ist, kann ein Timer den ESP Chip aus dem Deep-Sleep Modus aufwecken.

Falls man GPIO2 beschaltet, ist zu beachten, dass er beim Starten durch einen Widerstand auf High gezogen werden muss und dass er kurzzeitig als Ausgang mit flackerndem Signal agiert. Beim ESP-12 Modul ist er außerdem mit der blauen LED verbunden, die bei Low Pegel leuchtet.

Um den ESP-Chip in den Firmware-Upload Modus zu versetzen, musst du beide Taster gleichzeitig drücken und dann den Reset Taster zuerst loslassen. Der ESP Chip erwartet dann Kommandos und Daten vom PC.

Es gibt zahlreiche grafische Programme zum hochladen der Firmware, aber die scheinen alle etwas zickig zu sein. Daher empfehle das Script esptool.py, welches meine beiden weiter unten bereitgestellten Firmware-Pakete enthalten. Zum Ausführen musst Du vorher Python instalieren. Achte darauf dass es zur PATH Variable hinzugefügt wird. Anschließend installiere die Library für serielle Ports, indem du im CMD Fenster (Eingabeaufforderung) pip install pyserial eingibst.

Original AT-Firmware

Die AT-Firmware ermöglicht es, das Modul wie ein Modem zu benutzen. Durch das Absetzen von Befehlen auf der seriellen Schnittstelle konfiguriert man das Modul, baut Verbindungen auf überträgt Daten. Das Modul dient also als Netzwerk-Schnitttselle für einen angeschlossenen Mikrocontroller.

Die AT-Firmware arbeitet auffällig langsam, was bitte nicht als Abwertung zu verstehen ist. Wenn ich per WLAN ein Kommando an den seriell angeschlossenen Mikrocontroller sende und auf dessen Antwort warte, dauert das unabhängig von der Paketgröße und Baudrate meistens 100 - 200ms. Allerdings muss man im WLAN Netz ohnehin mit Verzögerungen in dieser Größenordnung rechnen.

Falls deine AT-Firmware älter als 0.40.0.0 ist, rate ich zu einem Upgrade, da frühere Versionen noch ziemlich instabil liefen. Die Firma Espressif stellt ihre AT Firmware im bin Verzeichnis des SDK zur Verfügung. Dort befindet sich auch die Textdatei README.md, in der drin steht, welche Dateien abhängig von der Größe des Flash Speichers an welche Position geladen werden müssen.

Die Größe des Flash Speichers erkennt man anhand der letzten Ziffern seiner ID-Nummer. 04=512k Byte, 08=1M Byte, 16=2M Byte, 32=4M Byte. Das esptool kann diese ID-Nummer auslesen:

python esptool.py --port COM6 flash_id

Für Module mit nur 4M bit (=512k Byte) Flash Speicher muss man die AT-Firmware 0.50.0.0 vom SDK 1.4.0 verwenden. Das ist die letzte Version, die noch dort hinein passt. Für alle größeren Module kannst du die Firmware aus dem aktuellen SDK verwenden. Ich habe mir die AT-Firmware 1.1.0.0 vom SDK 1.5.4 gesichert, weil sie gut funktioniert, was noch lange nicht für jede Version gilt.

Für die Firmware aus dem SDK 1.4.0 und 1.5.4 sind die folgenden Befehle zum Hochladen der Firmware richtig:

4M bit (=512k Byte)python esptool.py --port COM6 write_flash 0x000000 noboot/eagle.flash.bin 0x040000 noboot/eagle.irom0text.bin 0x03e000 blank.bin 0x07e000 blank.bin 0x07c000 esp_init_data_default.bin
8M bit (=1M Byte)python esptool.py --port COM6 write_flash 0x000000 boot_v1.5.bin 0x001000 512+512\user1.1024.new.2.bin 0x0fc000 esp_init_data_default.bin 0x07e000 blank.bin 0x0fe000 blank.bin
16M bit (=2M Byte)python esptool.py --port COM6 write_flash 0x000000 boot_v1.5.bin 0x001000 512+512\user1.1024.new.2.bin 0x01fc000 esp_init_data_default.bin 0x07e000 blank.bin 0x1fe000 blank.bin
32M bit (=4M Byte)python esptool.py --port COM6 write_flash 0x000000 boot_v1.5.bin 0x001000 512+512\user1.1024.new.2.bin 0x03fc000 esp_init_data_default.bin 0x07e000 blank.bin 0x3fe000 blank.bin
Auf diese Weise kannst du auch andere nicht originale Firmware hochladen. Wobei diese meistens nur aus einer bin Datei bestehen, die an Adresse 0x00000 geladen wird. Im Zweifelsfall schaue in die dazugehörige Dokumentation. Keine Angst: Wenn das Hochladen der Firmware (warum auch immer) fehlschlägt, kann man es einfach nochmal versuchen. Also Taster drücken und nochmal das esptool starten.

AT Befehle

In diesem Absatz beschreibe ich nicht alle AT Befehle, was auch schwierig wäre, weil sie sich von Version zu Version unterscheiden. Die hier genannten Befehle funktionieren auf allen mir bekannten Firmware Versionen von 0.21.0.0 bis 1.1.0.0 Die vollständige Dokumentation findest Du als PDF Dokument auf der Webseite von Espressif, sowie in den obigen Firmware downloads. Beachte beim Programmieren, dass das exakte Format der Antworten je nach Firmware Version etwas variiert.

Zum Testen von Netzwerkverbindungen empfehle ich das Kommandozeilen-Programm Netcat. Außerdem solltest Du Dir unbedingt das Programm Wireshark anschauen, falls du es noch nicht kennst.

Als Terminalprogramm zur manuellen Eingabe der AT Befehle empfehle ich das Hammer Terminal. Stelle oben "Newline at CR+LF" ein und unten "Send on Enter CR-LF". Die Baudrate ist normalerweise 115200, ansonsten versuche es mit 57600 und 9600 Baud. Nach dem Hardware-Reset zeigt das Terminal Programm einige unlesbare Zeilen an (das ist normal), und dann "ready". Danach kannst du Befehle eintippen.

AT
wird einfach mit "OK" beantwortet. Der Befehl hat keine weitere Funktion, er eignet sich prima, um die serielle Verbindung zu testen.

ATE0
schaltet das Echo der Befehle aus. Dieser Befehl kann die Programmierung vereinfachen und die Geschwindigkeit geringfügig verbessern. Mit der Zahl 1 schaltet man das Echo wieder an. Für manuelles Testen lässt man das Echo am besten eigeschaltet.

AT+GMR
Zeigt die Version der Firmware an, zum Beispiel:

AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:1.5.4(baaeaebb)
compile time:May 20 2016 15:06:44
OK

AT+CWMODE=1
stellt ein, dass das Modul sich in ein bestehendes WLAN Netz einbuchen soll.

AT+RST
löst einen Software-Neustart aus. Dies ist nach dem Wechsel von CWMODE notwendig.

AT+CWLAP
listet alle erreichbaren Access Points auf. Zum Beispiel:

+CWLAP:(4,"EasyBox-4D2D18",-72,"18:83:bf:4d:2d:b2",2,-46)
+CWLAP:(4,"UPC2827302",-63,"88:f7:c7:52:40:9d",6,-22)
+CWLAP:(0,"Unitymedia WifiSpot",-64,"8a:f7:c7:52:40:9f",6,-22)
+CWLAP:(3,"Muschikatze",-45,"5c:49:79:2d:5b:cd",7,-4)
OK

AT+CWJAP="Muschikatze","supergeheim"
das Modul verbindet sich mit dem WLAN Netz "Muschikatze" und dem angegebenen WPA/WPA2 Passwort. Diese Einstellung wird automatisch dauerhaft gespeichert und beim nächsten Neustart aktiv.

AT+CWJAP?
zeigt an, mit welchem Access Point das Modul gerade verbunden ist. Zum Beispiel:

+CWJAP:"Muschikatze","5c:49:79:2d:5b:cd",7,-60
OK

AT+CIFSR
zeigt die IP-Adresse und MAC Adresse des Moduls an zum Beispiel:

+CIFSR:STAIP,"192.168.0.111"
+CIFSR:STAMAC,"5c:cf:7f:8b:a9:f1"
OK

AT+CIPMUX=1
Stellt ein, dass das Modul mehrere Verbindungen erlauben soll. In diesem Modus sind bis zu 5 gleichzeitige Verbindungen möglich. Die folgenden Beispiele setzen alle voraus, dass dieser Modus aktiviert wurde.
Das Gegenteil wäre der AT+CIPMUX=0, wo das Modul nur als Client und mit nur einer Verbindung genutzt werden kann. In diesem Fall entfällt bei den drauf folgenden Befehlen die Kanalnummer.

AT Firmware als TCP Server benutzen

AT+CIPSERVER=1,5000
dieser Befehl schaltet den Server ein, so dass er Verbindungen auf Port 5000 annimmt. Er kann danach maximal 5 Verbindungen gleichzeitig annehmen. Danach könntest du zum Beispiel mit Netcat eine Netzwerkverbindung zu diesem Mini-Server aufbauen:

nc 192.168.0.111 5000
Hallo
Welten!

Beim Verbindungsaufbau liefert das Modul folgende Meldungen:

0,CONNECT
+IPD,0,7:Hallo
+IPD,0,9:Welten!
"0,CONNECT" bedeutet, dass der TCP Server eine Verbindung auf Kanal 0 angenommen hat. "+IPD,0,7:" bedeutet, dass der Server auf Kanal 0 genau 7 Bytes empfangen hat. Nach dem Doppelpunkt folgen genau diese 7 Bytes.

AT+CIPSEND=0,18
> Ebenfalls Hallo!
Mit diesem Befehl sendest du eine Antwort an den Computer. Die 0 ist wieder die Kanalnummer und die 18 sind die Anzahl der zu sendenden Bytes (maximal 2048). Nachdem das Modul mit ">" Antwortet, gibst du die zu sendenden Zeichen (oder Bytes) ein. Das Modul bestätigt den Sendevorgang nach kurzer Zeit mit

SEND OK

AT+CIPCLOSE=0
mit diesem Befehl schließt du die Verbindung auf Kanal 0. Das Modul antwortet mit

0,CLOSED
OK

AT Firmware als TCP Client benutzen

AT+CIPSTART=0,"TCP","mail.stefanfrings.de",25
Kanal 0 baut eine TCP Verbindung zu dem angegebenen Server auf Port 25 auf. Anstelle des Hostnamens kannst du auch eine IP Adresse verwenden. Die Antwort lautet zum Beispiel:
0,CONNECT
OK
+IPD,0,96:220 wp039.webpack.hosteurope.de 
   ESMTP Host Europe Mail Service 
   Sat, 08 Apr 2017 23:37:19 +0200

Da dieser Mail-Server sofort antwortet, siehst du auch direkt eine +IPD Zeile. Der Text hinter dem Doppelpunkt ist die Antwort des Servers. Danach kann man mit AT+CIPSEND wie bereits oben beschrieben Daten an den Server senden. Mit AT+CIPCLOSE schließt man die Verbindung.

AT Firmware für UDP benutzen

Beim UDP Protokoll entfällt der Verbindungsaufbau, und damit auch die Begrenzung auf 5 gleichzeitige Verbindungen. Man sendet einzelne Nachrichten an die gewünschten Empfänger und hofft, dass sie zügig dort ankommen. Im Gegensatz zu TCP verzichtet das UDP Protokoll auf die Wiederholung von verlorenen Paketen. Es garantiert nicht einmal, dass alle Pakete in der richtigen Reihenfolge beim Empfänger ankommen. UDP ist einfacher zu programmieren und nutzt die Übertragungsstrecke effizienter als TCP. Es eignet sich besonders gut zur regelmäßigen Übertragung von Messwerten, wenn einzelne Aussetzer tolerierbar sind (z.B. Temperaturfühler).

AT+CIPSTART=0,"UDP","0",0,3002,0
Nach diesem Befehl kann das Modul UDP Nachrichten auf Port 3002 von beliebigen Absendern empfangen. Es kann aber keine Nachrichten senden. Zum Test kannst du das Programm Netcat benutzen:

nc -u 192.168.0.111 3002
Jetzt geht's los!

Wobei du die IP-Adresse deines WLAN Moduls angeben musst. Wenn Du dann in Netcat etwas zum senden eintippst, wird das Modul den Empfang der Nachricht mit +IPD signalisieren.

AT+CIPSTART=0,"UDP","0",0,3002,2
Das Modul empfängt UDP Nachrichten auf Port 3002 von beliebigen Absendern, und es kann Antworten mit AT+CIPSEND zurück schicken. Die Antworten werden immer an den Computer gesendet, von dem zuletzt eine Nachricht empfangen wurde.

AT+CIPSTART=0,"UDP","192.168.0.5",3001,3002,0
Das Modul kann UDP Nachrichten auf Port 3002 von beliebigen Absendern empfangen. Mit dem AT+CIPSEND Befehl wird es Nachrichten an den Computer 192.168.0.5 Port 3001 senden.

Access-Point Modus

Wo kein WLAN Netz existiert, kann das ESP-Modul selbst ein kleines provisorisches Netz aufspannen. Bis zu 4 andere Geräte können sich dann mit dem Modul verbinden, aber sie können sich nicht gegenseitig sehen. Leider funktioniert das nicht mit allen Geräten zuverlässig. Im Access-Point Modus erreichst du das WLAN Modul unter der IP-Adresse 192.168.4.1.

AT+CWMODE=2
AT+CWSAP="ESP-Modul","supergeheim",5,3
AT+RST
Diese Befehlsfolge aktiviert den Access-Point Modus, und stellt den Namen des Netzes und das Passwort ein. Die 5 gibt den WLAN Kanal an (0-13), und die 3 legt fest, dass WPA2 Verschlüsselung verwendet wird. Diese Einstellung wird automatisch dauerhaft gespeichert und beim nächsten Neustart aktiv.

Es gibt auch einen Kombinierten Modus (AT+CWMODE=3), in welchem sich das Modul mit einem bestehenden WLAN Netz verbindet und außerdem ein eigenes zweites Netz aufspannt.

Möglichkeiten der Programmierung

Der chinesische Hersteller Espressif stellt ein SDK bereit, mit dem man eigene Programme in C schreiben kann, die direkt von dem Prozessor des WLAN Moduls ausgeführt werden. Dazu muss man sich allerdings mit Linux auskennen und darf nicht vor gruseliger Dokumentation zurück schrecken.

Das NodeMCU Projekt bemüht sich darum, die Programmierung stark zu vereinfachen, indem man auf LUA Scripte setzt. Allerdings leidet dieser Lösungsansatz an notorischem Speichermangel. Das Script und die Daten müssen in ca 40k Byte RAM gequetscht werden. Immerhin kann man ganz viele Scripte in den Flash Speicher laden, die sich gegenseitig aufrufen. Scrolle auf der Projektseite nach unten, dort gibt es einen Link zu dem "custom firmware build service", wo man sich eine individuell zusammengestellte Firmware erzeugen lässt.

Die meiner Meinung nach Bastel-freundlichste Lösung ist hingegen die ESP8266 Erweiterung für die Arduino IDE. Man programmiert dort in C++. Die Installation der IDE ist kinderleicht. Das Arduino Framework ist verständlich gestaltet und ausreichend dokumentiert, ebenso ist die ESP8266 Erweiterung ausreichend dokumentiert.

Alle drei Varianten haben eines gemeinsam: Es gibt keinen Debugger. Man kann nur durch Ausgeben von Log-Meldungen (auf dem seriellen Port) nachzuvollziehen, was das Programm gerade macht.

Bei Anwendungen, die mit Batterien mehrere Monate laufen sollen kann es hilfreich sein, neben dem ESP8266 zusätzlich einen kleineren Mikrocontroller (z.B. ATmega328) zu benutzen, welcher die Stromversorgung des ESP samt Spannungsregler unterbricht. Denn so ein ATmega kann direkt an der Batterie hängen und verbraucht im Standby viel weniger Strom. Außerdem hat er mehr nützliche I/O Pins, ist besser dokumentiert und kann professionell debuggt werden.

Erste Schritte mit Arduino

Das Arduino Plugin kombiniert das SDK des Herstellers mit C++ Klassen, um die Programmierung zu erleichtern. Das damit erzeugte Compilat enthält daher immer die originale Firmware des Herstellers plus das eigene Programm.
  1. Installiere die Arduino IDE
  2. Starte dann die IDE und gehe ins Menü Datei/Voreinstellungen. Gebe ins Feld "Zusätzliche Boardverwalter-URLs" die Adresse http://arduino.esp8266.com/stable/package_esp8266com_index.json ein.
  3. Gehe ins Menü Werkzeuge/Board/Boardverwalter. Suche dort nach "esp8266". Installiere die Erweiterung "esp8266 by ESP8266 Community".
  4. Die IDE lädt dann eine große Menge Dateien herunter und installiert sie ins Verzeichnis C:\Users\DeinName\AppData\Local\Arduino15.
  5. Stelle im Werkzeuge Menü das "Generic ESP8266 Module" ein, bzw. was auch immer du für ein Modul vorliegen hast.
  6. Stelle dann darunter im Werkzeuge Menü die Details zum Modul ein. Beim ESP-12 Modul sollte es sein:
    • Flash Mode: QIO (benutzt mehr Leitungen zum Flash Chip, als das langsamere DIO).
    • Flash Frequency: 40Mhz
    • CPU Frequency: 80Mhz
    • Flash Size: 4M (3M SPIFFS), das bedeutet: Von 4M Byte Flash werden 3M Byte für ein Dateisystem benutzt, das Dir frei zur Verfügung steht.
    • Debug Port: disabled
    • Debug Level: keine
    • Reset Method: NodeMCU, du musst die Taster zum Resetten benutzen.
    • Upload Speed: 115200 (mehr solltest du nicht versuchen, wenn du Widerstände zwecks 5V/3,3V Anpassung an dein UAB-UART Kabel angeschlossen hast).
    • Port: Der Port, den Windows deinem USB-UART Kabel zugewiesen hat (siehe Gerätemanager).
  7. Schreibe dein Programm (Arduino nennt es "Sketch").
  8. Compiliere das Programm, mit dem Menüpunkt Sketch/Überprüfen&Compilieren.
  9. Lade dein Programm hoch, mit dem Menüpunkt Sketch/Hochladen.

Lies die Dokumentation von Arduino und der ESP8266 Erweiterung.

Beispiel Sketches

Beispielprogramme für die ESP8266WiFi Library findest du im Verzeichnis C:\Users\DeinName\AppData\Local\Arduino15\packages\esp8266\libraries\ESP8266WiFi\examples oder in C:\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\examples. Dort findest du auch noch andere nützliche Beispiele für weitere Libraries, die Du Dir anschauen solltest.

Darüber hinaus zeige ich Dir hier Sketches, die Du für erste Versuche 1:1 in deine Arduino IDE kopieren kannst.

LED Blinker

Der erste Sketch lässt die blaue LED auf dem ESP-12 Modul blinken und gibt auf dem Seriellen Port immer abwechselnd "Tick" und "Tack" aus.
// Beim ESP-12 ist an GPIO2 eine blaue LED
#define LED 2

/** Wird beim Start einmal ausgeführt */
void setup() 
{
    pinMode(LED, OUTPUT);
    Serial.begin(115200);
}

/** Hauptschleife, wird wiederholt ausgeführt. */
void loop() 
{
    digitalWrite(LED, LOW);
    Serial.println("Tick");
    delay(500);

    digitalWrite(LED, HIGH);
    Serial.println("Tack");
    delay(500);
}
Dieser Sketch lässt noch 48k Bytes RAM und 3,7M Byte Flash übrig. Das ist eine Menge Platz für viele großartige Ideen.

UDP Server

Der zweite Sketch empfängt UDP Nachrichten und sendet sie als Echo zurück:
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

// Beim ESP-12 ist an GPIO2 eine blaue LED
#define LED 2

// Name und Passwort des Access Points
#define SSID "Muschikatze"
#define PASSWORD "supergeheim"

// Der Server nimmt Verbindungen auf diesem Port an
#define PORT 5444
WiFiUDP udpServer;

// Puffer für hereinkommende UDP Nachrichten
char udp_buffer[WIFICLIENT_MAX_PACKET_SIZE+1];


/** Wird beim Start einmal ausgeführt */
void setup()
{
    // LED aus
    pinMode(LED, OUTPUT);
    digitalWrite(LED, HIGH);

    // Seriellen Port initialisieren
    Serial.begin(115200);
    
    // Gib dem seriellen Port Monitor von der Arduino
    // IDE ein bisschen Zeit.
    delay(500);

    // Benutze einen externen AP
    WiFi.mode(WIFI_STA);
    WiFi.begin(SSID, PASSWORD);

    // UDP Server starten
    udpServer.begin(PORT);
}


/** Hauptschleife, wird wiederholt ausgeführt. */
void loop()
{
    process_incoming_udp();
    check_ap_connection();
}


/** Empfange UDP Nachrichten und sende Echo zurück */
void process_incoming_udp()
{   
    if (udpServer.parsePacket()) 
    {
        // Nachricht abholen
        int len=udpServer.read(udp_buffer,sizeof(udp_buffer)-1);
        udp_buffer[len] = 0;
                
        // Nachricht anzeigen
        Serial.print("Empfangen von ");
        Serial.print(udpServer.remoteIP());
        Serial.print(":");
        Serial.print(udpServer.remotePort());
        Serial.print(": ");
        Serial.println(udp_buffer);
        
        // Nachricht als Echo zurück senden
        udpServer.beginPacket(udpServer.remoteIP(), udpServer.remotePort());
        udpServer.print("Echo: ");
        udpServer.print(udp_buffer); 
        udpServer.endPacket();
        
        // Auf bestimmte Befehle reagieren
        if (strstr(udp_buffer, "an"))
        {
            digitalWrite(LED, LOW);
            udpServer.println("LED ist an");
        }
        else if (strstr(udp_buffer, "aus"))
        {
            digitalWrite(LED, HIGH);
            udpServer.println("LED ist aus");
        }
    }    
}


/** Optional: Zeige an, wenn die Verbindung zum AP geändert wurde. */
void check_ap_connection()
{
    static wl_status_t preStatus = WL_DISCONNECTED;
    
    wl_status_t newStatus = WiFi.status();
    if (newStatus != preStatus)
    {
        if (newStatus == WL_CONNECTED)
        {
            digitalWrite(LED, LOW);
            
            // Die eigene IP-Adresse anzeigen
            Serial.print("AP Verbindung aufgebaut, lausche auf ");
            Serial.print(WiFi.localIP());
            Serial.print(":");
            Serial.println(PORT);
        }
        else
        {
            digitalWrite(LED, HIGH);
            Serial.println("AP Verbindung verloren");
        }
        preStatus = newStatus;
    }
}
Wenn die Verbindung zum AP aufgebaut wurde, geht die blaue LED an. Auf dem seriellen Port gibt das Programm hilfreiche Statusmeldungen aus. So kannst du den Server mit Netcat testen:
nc -u 192.168.0.111 5444
Affen machen alles nach
Echo: Affen machen alles nach
aus
LED ist aus
an
LED ist an
Der UDP Service ist sehr einfach zu programmieren, weil man sich darauf verlassen kann, dass Nachrichten 1:1 wie gesendet eintreffen, also weder zerstückelt noch zusammengefügt. Außerdem braucht man sich nicht um den Verbindungs-Aufbau kümmern. Der größte Nachteil ist, dass UDP Nachrichten manchmal unbemerkt verloren gehen - besonders in drahtlosen Netzen.

TCP Server

Der dritte Sketch zeigt einen TCP Server, der mehrere Verbindungen gleichzeitig bedient:
#include <ESP8266WiFi.h>

// Beim ESP-12 ist an GPIO2 eine blaue LED
#define LED 2

// Name und Passwort des Access Points
#define SSID "Muschikatze"
#define PASSWORD "supergeheim"

// Der Server nimmt Verbindungen auf diesem Port an
#define PORT 5333
WiFiServer tcpServer(PORT);

// Objekte für Verbindungen
#define MAX_TCP_CONNECTIONS 5
WiFiClient clients[MAX_TCP_CONNECTIONS];

// Puffer für hereinkommende Textzeilen
char tcp_buffer[MAX_TCP_CONNECTIONS][30];


/** Wird beim Start einmal ausgeführt */
void setup()
{
    // LED aus
    pinMode(LED, OUTPUT);
    digitalWrite(LED, HIGH);

    // Seriellen Port initialisieren
    Serial.begin(115200);
    
    // Gib dem seriellen Port Monitor von der Arduino
    // IDE ein bisschen Zeit.
    delay(500);

    // Benutze einen externen AP
    WiFi.mode(WIFI_STA);
    WiFi.begin(SSID, PASSWORD);

    // TCP Server starten
    tcpServer.begin();
}


/** Hauptschleife, wird wiederholt ausgeführt. */
void loop()
{
    handle_new_connections();
    process_incoming_tcp();
    check_ap_connection();
}


/** 
 * Lege neue Verbindungen im Array ab und 
 * sende eine Willkommens-Nachricht.
 */
void handle_new_connections()
{
    WiFiClient client = tcpServer.available();
    if (client)
    {
        Serial.print("Neue Verbindung von ");
        Serial.println(client.remoteIP().toString());
        
        // Finde einen freien Platz im Array        
        for (int i = 0; i < MAX_TCP_CONNECTIONS; i++)
        {
            if (!clients[i].connected())
            {
                // Freien Platz gefunden
                clients[i] = client;
                tcp_buffer[i][0]=0;
                Serial.print("Kanal=");
                Serial.println(i);
                
                // Mit einer Willkommes-Meldung begrüßen
                client.println("Hallo Welt!");
                return;
            }
        }
        Serial.println("Zu viele Verbindungen");
        client.stop();
    }
}


/** Empfange TCP Nachrichten und sende Echo zurück */
void process_incoming_tcp()
{   
    static int i=0;
    
    // Bei jedem Aufruf wird nur ein TCP client abgefragt
    if (clients[i].available())
    {
        // Eine Zeile einlesen
        if (append_until(clients[i],tcp_buffer[i],sizeof(tcp_buffer[i]),'\n'))
        {        
            // Nachricht anzeigen
            Serial.print("Empfangen von ");
            Serial.print(i);
            Serial.print(": ");
            Serial.print(tcp_buffer[i]);

            // Nachricht als Echo zurück senden
            clients[i].print("Echo: ");
            clients[i].print(tcp_buffer[i]);
            
            // Auf bestimmte Befehle reagieren
            if (strstr(tcp_buffer[i], "an"))
            {
                digitalWrite(LED, LOW);
                clients[i].println("LED ist an");
            }
            else if (strstr(tcp_buffer[i], "aus"))
            {
                digitalWrite(LED, HIGH);
                clients[i].println("LED ist aus");
            }    
            
            // Bereit machen für das Empfangen der nächsten Zeile
            tcp_buffer[i][0]=0;
        }
    }
    
    // Zum nächsten TCP client weiter schalten
    if (++i >= MAX_TCP_CONNECTIONS)
    {
        i=0;
    }
}


/**
 * Hänge Zeichen von einem Stream an einen Puffer an, bis das terminierende Zeichen
 * erreicht wurde. Wenn der Puffer überläuft, lies trotzdem weiter aber verwerfe
 * die überschüssigen Zeichen.
 *
 * @param source Der Quell-Stream.
 * @param buffer Der Ziel-Puffer, muss mit '\0' zerminiert sein.
 * @param bufSize Größe des Ziel-Puffers
 * @param terminator Das letzte Zeichen, das gelesen werden soll, zum Beispiel '\n'.
 * @return True wennn das terminierende Zeichen erreicht wurde.
 */
bool append_until(Stream& source, char* buffer, int bufSize, char terminator)
{
    int data=source.read();
    if (data>=0)
    {
        int len=strlen(buffer);
        do
        {
            if (len<bufSize-1)
            {
                buffer[len++]=data;
            }
            if (data==terminator)
            {
                buffer[len]=0;
                return true;
            }
            data=source.read();
        }
        while (data>=0);
        buffer[len]=0;  
    }
    return false;
}


/** Optional: Zeige an, wenn die Verbindung zum AP geändert wurde. */
void check_ap_connection()
{
    static wl_status_t preStatus = WL_DISCONNECTED;
    
    wl_status_t newStatus = WiFi.status();
    if (newStatus != preStatus)
    {
        if (newStatus == WL_CONNECTED)
        {
            digitalWrite(LED, LOW);
            
            // Die eigene IP-Adresse anzeigen
            Serial.print("AP Verbindung aufgebaut, lausche auf ");
            Serial.print(WiFi.localIP());
            Serial.print(":");
            Serial.println(PORT);
        }
        else
        {
            digitalWrite(LED, HIGH);
            Serial.println("AP Verbindung verloren");
        }
        preStatus = newStatus;
    }
}
Wenn die Verbindung zum AP aufgebaut wurde, geht die blaue LED an. Auf dem seriellen Port gibt das Programm hilfreiche Statusmeldungen aus. So kannst du die Anwendung mit Netcat testen:
nc 192.168.0.111 5333
Hallo Welt!
Ich bin Groot
Echo: Ich bin Groot
aus
LED ist aus
an
LED ist an
Bei TCP kann man sich im Gegensatz zu UDP einigermaßen sicher sein, dass innerhalb einer Verbindung keine Nachrichten verloren gehen und dass die Reihenfolge nicht durcheinander gerät. Aber eine Textzeile kommt unter Umständen zerteilt in mehreren Segmenten an, selbst wenn sie kurz ist. Oder ein Segment liefert zwei Textzeilen, die ursprünglich einzeln gesendet wurden.

Deswegen habe ich die Funktion append_until() entwickelt, die Eingaben Zeilenweise unabhängig von der Segmentierung einsammelt. Im Gegensatz zu Arduinos readStringUntil() hat sie folgende Vorteile:

WiFi Config Service

Bei den obigen Beispielen wurden die Zugangsparameter für den WLAN Access Point einfach fest in den Quelltext geschrieben. Für Nicht-Entwickler ist diese Vorgehensweise jedoch ungeeignet. Eigentlich wurde für diesen Zweck WPS erfunden, doch das hat bei mir so oft nicht funktioniert, dass ich es gar nicht mehr verwende.

Eine naheliegende Alternative wäre, ein provisorisches WLAN Netz zu erzeugen und darüber eine Webseite zur Konfiguration bereit zu stellen. Ein entsprechender Beispiel-Sketch befindet sich in der Datei WiFiConfigService.zip. An dem folgenden verkürzten Quelltext siehst du, wie einfach der WiFi Config Service anzuwenden ist:

#include "ConfigService.h"

ConfigService configService(80);

void setup()
{
    configService.begin(5,"ESP Thing","");
    ...
}

void loop()
{
    configService.run();
    ...
}
Nach dem Einschalten der Stromversorgung aktiviert das Programm für 5 Minuten ein provisorisches Netz mit dem Namen "ESP Thing" ohne Passwort. Du kannst deinen Computer oder Smartphone mit diesem Netz verbinden und dann die Seite http://192.168.4.1 aufrufen:

Dort kannst du nun die Zugangsdaten deiner Fritz Box (oder was auch immer du für einen WLAN Router hast) eingeben und absenden. Wenn sie richtig sind, baut das Modul sofort eine Verbindung zum Access Point auf. Das Programm gibt hilfreiche Meldungen auf dem seriellen Port aus und es nutzt eine LED zur Status-Anzeige.

Dieses Projekt ist außerdem ein schönes Beispiel, wie man einen minimalen HTTP Server schreibt, mit dem man Dinge fernsteuern könnte.

Fallstricke

Wenn dein Programm unzuverlässig läuft, kontrolliere zuerst meine Ratschläge aus dem Kapitel Maßnahmen gegen Fehlfunktionen. Wenn das alles Ok ist, dann kontrolliere die folgenden Aspekte in deinem eigenen Programm:

Es ist wichtig, das die Firmware genügend Rechenzeit ab bekommt, sonst fällt das Modul aus. Alle eigenen Programmteile müssen spätestens nach 50ms (empfohlen werden 20ms) die Kontrolle an die Firmware abgeben, indem entweder die loop() Funktion verlassen wird, oder delay(ms) oder yield() aufgerufen wird.

Für eigene Programme stehen nur ungefähr 4k Byte Stack zur Verfügung. Wenn lokale Variablen in Prozeduren mehr Platz belegen, stürzt das Programm ab. Größere Datenmengen (z.B. Puffer für Daten) sollen daher vorzugsweise global deklariert werden, damit sie außerhalb des Stack liegen.

Dynamische Speicherverwaltung auf dem Heap verlangt besondere Sorgfalt, damit der Heap nicht fragmentiert wird. Mein Tipp: Schreibe Dein Programm so, dass es gar keinen Heap belegt. Verzichte möglichst auf malloc(), calloc(), den new Operator und die Verwendung der String Klasse.

Wenn man Daten sendet, wird aus jedem Client::print() und Client::write() Aufruf ein einzelnes Ethernet Paket. Viele kleine Pakete reduzieren die Performance, da sie genau so lange dauern, wie große Pakete. Die maximale Paketgröße steht in WIFICLIENT_MAX_PACKET_SIZE und ist 1460 Bytes. Wenn man in einem Aufruf mehr Daten sendet, teilt die Firmware sie automatisch auf mehrere Pakete auf und wartet ggf. auch darauf, dass Platz im Sendepuffer frei wird.

Da der Empfangspuffer mehrere Pakete aufnehmen kann, muss man bei der Programmierung davon ausgehen, dass Client::available() und Client::readBytes() einige Kilobytes zurück liefern können, vor allem wenn die Daten schnell aufeinander folgend eintreffen. Passe beim Auslesen der Daten auf, weder deine Puffer noch den Stack zu überladen.

Benutze die Methoden readString() und readStringUntil() am besten gar nicht, weil sie beliebig lange Strings ansammeln, die leicht einen Speicher-Überlauf auslösen.

Verlasse Dich nicht darauf, dass gesendete TCP Nachrichten den Empfänger in der gleichen Segmentierung erreichen, wie sie gesendet wurden. Die Netzwerk-Komponenten dürfen die Segmente des TCP Datenstromes zerlegen und neu zusammenfügen. In dieser Diskussion wurden die Efekkte der Segmentierung sehr schön erklärt.

Beim UDP Protokoll kann man nur einzelne Nachrichten mit maximal 1460 Bytes senden oder empfangen. Unter Umständen schränken Netzwerk-Komponenten die maximale Paketgröße weiter ein. Im heimischen WLAN Netz kannst du dich jedoch auf die 1460 Bytes verlassen.

SSID und Passwort von AP und softAP werden automatisch dauerhaft gespeichert, aber nur wenn sie gültig sind. Das Passwort muss entweder ein Leerstring ("") sein oder mindestens 8 Zeichen lang sein.

NetBeans als besseren Text-Editor für Sketches verwenden

Der Text-Editor von Arduino ist gelinde gesagt knapp ausgestattet. NetBeans hat einen viel besseren Editor, deswegen nutze ich diesen gerne. NetBeans erkennt viele Fehler schon direkt während der Eingabe und hilft Dir beim Tippen. Wenn Du zum Beispiel "Serial." eintippst, listet NetBeans alle Felder und Methoden der Serial Klasse auf. Wenn Du die Strg-Taste gedrückt hälst und dann auf eine #include Datei, einen Klassen-Namen oder einen Methoden-Namen klickst, dann öffnet NetBeans die zugehörige Datei und springt zu der entsprechenden Zeile. Im Navigator Fenster zeigt NetBeans die Struktur der aktuellen Datei an, mit deren Hilfe du blitzschnell zu anderen Codeabschnitten springen kannst.

Einmalige Einrichtung

Installiere dazu Java JDK 8 und NetBeans in der Variante für C/C++. Wenn du NetBeans bereits für andere Programmiersprachen installiert hast, dann genügt es, das C/C++ Plugin hinzuzufügen.

Starte NetBeans und gehe dann ins Menü Tools/Options/Miscellaneous/Files.

Finde heraus, in welches Verzeichnis die ESP8266 Erweiterung für Arduino installiert wurde. Wahrscheinlich befindet sie sich entweder in C:\Users\DeinName\AppData\Local\Arduino15\packages\esp8266 oder in C:\Arduino\hardware\esp8266com\esp8266. Bei der folgenden Konfiguration sollst du anstelle von <esp8266> den vollständigen Pfad eingeben.

Gehe dann ins Menü Tools/Options/C/C++/Build Tools.

Wechsele dann zu dem Reiter "Code Assistance". Wähle bei "Tool Collection" die "Arduino_ESP8266" aus und füge dann darunter beim C++ Compiler folgende "Include Directories" hinzu:

Das genügt erstmal für die obigen Beispiel Sketches. In Zukunft wirst du eventuell noch weitere Verzeichnisse unter <esp8266>\libraries hinzufügen müssen, damit NetBeans deine #include Anweisungen auswerten kann.

In der Arduino IDE sollst du nun in das Menü Datei/Voreinstellungen gehen und die Option "Externen Editor verwenden" einschalten.

Arduino Sketch in Netbeans öffnen

Erstelle in deinem Arduino Projektverzeichnis (wo sich die *.ino Datei befindet) eine leere Datei mit dem Namen "Makefile" (achte dabei auf die groß/klein-Schreibung). Gehe danach in NetBeans auf den Menüpunkt File/New Project.

Wenn du vorher alles richtig konfiguriert hast, kannst du nun in NetBeans deinen Sketch (die *.ino Datei) öffnen und bearbeiten. Die obigen Beispiel-Sketche sind fehlerfrei, sie eignen sich daher sehr gut, die Konfiguration von NetBeans zu überprüfen. Es sollten keine gelben oder gar rote Markierungen erscheinen.

Um den Sketch zu überprüfen (compilieren) und hochzuladen musst du weiterhin die Arduino IDE verwenden.

Manchmal funktionieren die ganzen erweiterten Editor-Funktionen bei einzelnen Dateien nicht. Klicke dann in der Projekt-Ansicht mit der rechten Maustaste auf den Dateinamen und dann auf Properties. In dem folgenden Dialog musst die Option "Add To Parse" einschalten, dann funktioniert es.

Kritik

Der Hersteller hat seinen Chip zu früh agressiv vermarktet, als die Firmware noch extrem instabil war. In den ersten zwei Jahren war eine kommerzielle Nutzung noch undenkbar. Erst seit Herbst 2016 hat die unvermeidbare Firmware einen Zustand erreicht, wo man sagen kann, dass sie funktioniert.

Espressif gibt in seinem Datenblatt mit einigen Superlativen an, die in der Realität kaum erreicht werden. Ich muss allerdings positiv bemerken, dass das Marketing Gewäsch immer weniger wird, und wichtige technische Daten zunehmend ergänzt werden. Noch sind die verfügbaren Dokumentationen sehr unvollständig.

Vor einem Jahr fand ich noch die Angabe "Ultra Low Power Technology" und "Deep-Sleep 10µA". Heute ist der selbe Chip nur noch "energy-efficient" und braucht plötzlich angeblich 20µA im Deep-Sleep. Ich habe 25µA bei 3,3V mit Flash Speicher gemessen.

Dann gibt es im Datenblatt noch die Angabe "Power Off 0,5µA", es fehlt allerdings jegliche Erklärung, wie man diesen Modus erreicht und was er bedeutet.

Beim Aufwachen aus den Deep-Sleep bleiben nur wenige Bytes vom RAM erhalten und die ganze Firmware muss neu booten. Das sollte man mal klar und deutlich ins Datenblatt schreiben, denn es beschränkt den Nutzen dieser Betriebsart doch sehr.

In diesem Zusammenhang finde ich ziemlich irritierend, dass der Chip vor einem Jahr noch für 3,0 bis 3,6V spezifiziert war, aber laut aktuellem Datenblatt schon ab 2,5V funktionieren soll. Immerhin haben meine Experimente ergeben, dass die 2,5V stimmen - sogar ohne Verlust von Reichweite. Mein ESP-12F startet ab 2,3V und läuft danach weiter, bis die Spannung unter 2,0V fällt.

Als maximale Stromaufnahme gibt der Hersteller 170mA an, aber mehrere Leute (auch ich) haben unabhängig voneinander Werte im Bereich 300 bis 500mA gemessen. Könnte das an der Antenne liegen?

Bei den Netzwerkprotokollen nennt der Hersteller "HTTP" und "FTP", doch ich habe im SDK dazu keinerlei Funktionen gefunden. In der Programmieranleitung zeigen sie lediglich ein Demo, wie man "zu Fuß" einen HTTP Request sendet und die ganze Response als Plain Text anzeigt.

Im aktuellen Datenblatt steht immer noch, dass minimum 512k Byte Flash erforderlich seien, doch für die aktuelle AT Firmware braucht man mindestens 1M Byte. Da dies die Referenzanwendung ist, finde ich die Angabe von 512k Byte unpassend.

Wenn ein Händler von mehr als 11 GPIO Pins schreibt, dann lügt er glatt, denn 6 der sogenannten GPIO Pins sind mit dem Flash Speicher verbunden und dürfen nicht zusätzlich beschaltet werden. Wirklich frei verwendbar sind nur 5 I/O Pins, und weitere 6 sind eingeschränkt verwendbar.

Der ADC Eingang misst 0 bis 1 Volt mit 10 Bit, aber wegen der Einstreuung des eigenen HF Signals muss man mit 0,2V Abweichung rechnen! Eigentlich kann man den Eingang nur gebrauchen, wenn der HF Teil deaktiviert ist. Immerhin wird das inzwischen im Datenblatt gut versteckt erwähnt.

Der Watchdog erfüllt seinen Zweck nicht gut. Bei Programmfehlern (z.B. Stack Überlauf) kommt es sehr häufig vor, dass das Modul nach einem Watchdog-Reset nicht mehr richtig startet. Ein externer Hardware Reset funktioniert aber zuverässig.

Schließlich möchte ich noch darauf hinweisen, dass der Chip unabhängig von der eigenen Anwendung immer noch nicht 100% stabil arbeitet. Manchmal hängt er sich auf, und manchmal resetted er sich selbst erfolgreich. Ich glaube, dass die Kern-Firmware auf Übertragungsstörungen in der Funk-Schnittstelle falsch reagiert.