Vorstellung des ESP8266-Boards D1 mini

Das handlich kleine ESP8266 Board Wemos D1 mini (kleiner Arduino Nano-Format, aber dafür etwas breiter) bekommt man aus Fernost mittlerweile (Stand März 2020) für ca. 2.50 €, wobei die Blue-Pill mit STM32 um die 1.80 € kommt.

Bei diesem marginalen Preisunterschied frage ich mich, ob der liebgewonnene STM32 überflüssig geworden ist. Schließlich bietet der ESP8266 mehr Leistung und mehr Speicher und zudem WLAN. STM32 wie ESP8266 sind Vertreter der 3.3 Volt-Klasse, können über die Bords aber auch 5V liefern. Moderne Sensoren arbeiten eigentlich alle mit 3.3V, die 5V-Sensoren werden so langsam verdrängt.

Aktuell wäre ja der ESP32, aber ein ESP32 Lolin32 Board kommt immer noch auf etwa 4.50 € (aus Fernost) und ist damit doch ein Stückchen teurer, auch wenn der ESP32 natürlich noch viel mehr kann und erste Wahl ist, wenn es nicht aufs Geld ankommt.

Vergleich STM32-Blue Pill vs. ESP8266-Wemos D1 mini

Der Vorteil des STM32 waren seine vielen Leitungen und seine batteriegebufferte Echtzeituhr direkt on Board. Der Vorteil des ESP8266 Boards, der gleich ins Auge sticht, ist natürlich das WLAN.

Im Detail schlagen sich die Kontrahenten wie folgt:

Blue Pill mit STM32 D1 Mini mit ESP8266
  • 32 bit Microcontroller
  • 3.3V Architektur
  • 72 Mhz Takt
  • 64 bzw. 128 KB Flash Programmspeicher
  • 20 KB RAM Variablenspeicher
  • 8x 12 Bit (0...4096) Analog-Eingänge auf dem Board zugänglich
  • 24x Digital-Ein-/Ausgänge auf dem Board zugänglich
  • Power-LED und programmierbare LED onBoard
  • Programmierung genauer Timings möglich
  • unterstützt I2C, SPI, UART, PWM, GPIO, CAN, USB 2.0
  • Stromverbrauch: typ. 2 bis 3.4 µA im Standby, 14 bis 24 µA im Stop-Mode, 14.4 mA im Sleep Mode, 36 mA im Run-Mode; max. 3 bis 30 mA im Sleep Mode, max. 6.8 bis 50 mA im Run-Mode
  • Debug mode: Serial wire debug (SWD) & JTAG interfaces
  • Echtzeituhr (kalibrierbar) on Board
  • VBatt-Batteriepufferung von RTC und Registern
  • 32 bit Microcontroller
  • 3.3V Architektur
  • 80-160 Mhz Takt
  • 4 MB Flash Programmspeicher
  • 81 KB RAM Variablenspeicher
  • 1x 10 Bit (0...1024) eher ungenauer (bis ±20%) Analog-Eingang
  • 11x Digital-Ein-/Ausgänge auf dem Board zugänglich
  • programmierbare LED (GPIO 2) onBoard
  • Programmierung genauer Timings ggf. schwierig, da etwa WLAN-Unterroutinen vom µC zwischenverarbeitet werden
  • unterstützt I2C, SPI, UART, SDIO, IRDA, PWM, GPIO, TCP/IP
  • Stromverbrauch: 0.01/0.9/15 mA im Deep/Light/Modem Sleep Power-Mode, < 1 mW im Standy-Mode, WLAN: 56/140 mA (RX/TX) bei 802.11g
  • WLAN 802.11 b/g/n 2.4 GHz WPA/WPA2 mit SmartLink Android/IOS, FCC zertifiziert

Schaue ich mir die Liste so an, dann ist der STM32 immer noch nicht überflüssig. Er hat viel mehr und genauere Analog-Eingänge und er hat eine batteriegepufferte Echtzeituhr an Bord. Er wird also meine Wahl sein, wenn es auf eine internetunabhängige Uhr oder mehr als einen Analog-Port ankommt oder wenn WLAN / Internet unwichtig ist.

Der ESP8266 wird meine Wahl sein, wenn es eine Internetverbindung gibt und ein analoger Eingang reicht. Die Zeit kann man hier auch über das Internet per NTP beziehen.

Die Hardware


Das Board ist mit seinen Abmessungen von 26 x 34.5 x 8 mm sehr handlich. Dieser D1 mini Formfaktor hat sich mittlerweile etabliert und es gibt eine ganze Reihe von aufsteckbaren Shields für das Board, sei es für Li-Ion-Akkubetrieb, Relais zum Schalten bis 250V, mit DHT22 oder DS18B20 Temperaturfühler, OLED, 8x8-LED-Matrix, SD-Kartenleser, Echtzeituhr und SD, Taster, Temperatur/Luftdruck-Sensor BMP180, RGB-LED (WS2812B), Prototyping Board und dergleichen.

Es hat einen USB-Micro-Anschluss und einen CH340-Seriellen-Chip on board, so dass am Windows-PC erkannt wird und direkt über den USB-Port programmiert werden kann. Der Reset-Taster befindet sich an der Seite, was bei der Entwicklung vielleicht ein wenig fummelig ist, aber Vorteile beim Einbau in ein Gehäuse hat, weil man ihn da besser zugänglich machen kann.

Die WLAN-Antenne ist auf eine kleine Seitenplatine aufgedruckt. Dort befindet sind auch eine (bei mir blaue) LED.

Download des PinOut als PDF


Der Anschluss A0 kann nur als Input, nicht aber als Output benutzt werden. Beim D1 Mini ist die max. zulässige angelegte Spannung 3.2 Volt. Intern im ESP8266 Chip sind dies 1.0 Volt. Ein Widerstand auf dem D1 mini Board sorgt für eine entsprechende Anpassung.

In der Arduino-IDE ist "LOLIN(WEMOS) Dl R2 & mini" und der entsprechenden COM-Port einzustellen, damit die Programmierung klappt.
Bei der Kompilierung zeigt die Arduino IDE an, wieviel Speicher das Board im Vergleich zu einem STM32 oder Arduino Uno bietet:
Der Sketch verwendet 268652 Bytes (25%) des Programmspeicherplatzes. Das Maximum sind 1044464 Bytes. Globale Variablen verwenden 27904 Bytes (34%) des dynamischen Speichers, 54016 Bytes für lokale Variablen verbleiben. Das Maximum sind 81920 Bytes. Uploading 272800 bytes from C:\Users\admin\AppData\Local\Temp\arduino_build_876731/esp8266-oled-ntp.ino.bin to flash at 0x00000000 ................................................................................ [ 29% ] ................................................................................ [ 59% ] ................................................................................ [ 89% ] ........................... [ 100% ] Um das Board zu testen und die Frage, ob und wie eine Echtzeituhr auf dem ESP8266 zu realisieren ist, zu klären, habe ich mir dieses als Aufgabe gesetzt.

Der ESP8266 soll sich mit meinem WLAN verbinden, die Zeit von einem Zeitserver holen und diese dann auf einem I2C-OLED anzeigen. Im Sekundentakt soll dazu die auf dem Board verbaute LED blinken.

Die Schaltung



Hier gibt es nicht viel zu erklären. Das OLED hängt an der Spannungsversorgung und am I2C-Bus, so wie es oben im Pinout beschrieben ist: SDA an D2 (oranges Kabel) und SCL an D1 (braunes Kabel).

Programm Echtzeituhr

Für das OLED nehme ich wieder die ThingPulse-Library (Funktionsbeschreibung ist in diesem Projekt erklärt) her. Diese gefällt mir mit den Fonts besser als die von adafruit und diese werde ich in Zukunft benutzen. Diesmal habe ich mir auch einen user defined font erstellt und eingebunden.


Für die NTP-Abfrage habe ich auf die Library NTPClient von Fabrice Weinberg zurückgegriffen, die gut funktioniert. Ihr findet sie im Bibliotheksmanager.

NTP (Network Time Protocol) ist das Internet-Protokoll zum Holen der genauen Zeit über das Internet. Es setzt seinerseits auf UDP (User Datagram Protocol) auf.

Was ihr natürlich noch machen müsst, ist eure Zugangsdaten für euren Router in den Source eintragen, denn ohne WLAN kein Internet und keine Zeit.

Source-Code

oled.ino (klicken, um diesen Abschnitt aufzuklappen)
//////////////////////////////////////////////////////// // (C) 2020 by Oliver Kuhlemann // // Bei Verwendung freue ich mich über Namensnennung, // // Quellenangabe und Verlinkung // // Quelle: http://cool-web.de/esp8266-esp32/ // //////////////////////////////////////////////////////// #define PinSCL 5 // I2C-Bus für OLED #define PinSDA 4 #include <Wire.h> #include "SSD1306Wire.h" // für OLED (legacy: #include "SSD1306.h") #include <NTPClient.h> // für Internet-Zeit, Library by Fabrice Weinberg #include <ESP8266WiFi.h> // für WLAN #include <WiFiUdp.h> // für UDP-Protokoll #include "fontArimo30.h" // größerer Font zur Anzeige der Uhrzeit const char *ssid = "???"; // Anmeldedaten für deinen Router const char *password = "???"; WiFiUDP ntpUDP; // You can specify the time server pool and the offset, (in seconds) // additionaly you can specify the update interval (in milliseconds). // NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000); // By default 'pool.ntp.org' is used with 60 seconds update interval and no offset NTPClient timeClient(ntpUDP, "pool.ntp.org", 3600*1, 600000); // GMT+1 Winterzeit / GMT+2 Sommerzeit, Update alle 10 Minuten // Initialize the OLED display using Arduino Wire: SSD1306Wire oled(0x3c, PinSDA, PinSCL); // ADDRESS, SDA, SCL void setup(void) { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); Serial.print(F("Verbinde WLAN...")); oled.init(); oled.flipScreenVertically(); // falls anders herum eingebaut oled.clear(); oled.setTextAlignment(TEXT_ALIGN_CENTER); oled.setFont(ArialMT_Plain_24); oled.drawString(64, 15, F("WLAN...")); oled.display(); WiFi.begin(ssid, password); while ( WiFi.status() != WL_CONNECTED ) { delay ( 500 ); Serial.print ( "." ); } Serial.println(F(" Erfolg!")); Serial.println(F("Hole Zeit...")); oled.clear(); oled.drawString(64, 15, F("Hole Zeit...")); oled.display(); timeClient.begin(); delay (1000); } void loop(void) { char buf[20]; int32_t mStart=millis(); int32_t za=0; timeClient.update(); while (1) { if (za % 2 == 0) { Serial.println(timeClient.getFormattedTime()); oled.clear(); // oled.setTextAlignment(TEXT_ALIGN_CENTER); oled.setFont(Arimo_Regular_30); //snprintf (buf,20, "%d %d", za/2, (millis()-mStart)/1000); oled.drawString(64, 15, timeClient.getFormattedTime()); oled.display(); } delay (500); digitalWrite(LED_BUILTIN, !(digitalRead(LED_BUILTIN))); // LED blinken lassen za++; } }

Die fontArimo30.h-Datei ist sehr lang und sehr langweilig, denn sie enthält nur die Definition für einen größeren Zeichensatz. Hier könnt ihr im Prinzip jeden Zeichensatz auf http://oleddisplay.squix.ch/#/home aussuchen und in das Header-File kopieren. Allerdings müsst ihr noch ein const unsigned char aus dem const char am Anfang machen, damit ein keine Fehler beim Kompilieren gibt.
Oder ihr setzt einfach das mitgelieferte ArialMT_Plain_24 ein und lasst den Include-Befehl oben weg. Dann ist die Schrift geringfügig kleiner.

Ansonsten ist alles wieder gut im Source kommentiert und sollte keine Fragen offen lassen.

Zum Schluss noch ein kurzes Demonstrationsvideo:



Wenn man also im Bereich des heimischen WLANs bleibt, kann man auf eine batteriegestützte Echtzeituhr verzichten.