Heute ist wieder ein Mikrocontroller hinter dem Türchen, mit dem ihr nicht nur verschiedene Sensoren auslesen und Aktoren steuern, sondern auch mit einem WLAN-Verbindung aufnehmen könnt. Es ist ein anderes Breakout Board mit dem ESP8266.
Dieses Breakout Board hat, neben dem Prozessor mit 4MByte Flash Speicher, einen CP2102 USB zu seriell Converter, damit ihr das Modul einfach programmieren könnt. Die meisten der I/O-Pins sind herausgeführt. Ebenso ist ein Spannungsregler vorhanden, der aus der USB-Versorgungsspannung oder der Spannung am Vin Anschluss die 3.3 V Versorgungsspannung für den ESP8266 liefert. Hier gleich ein wichtiger Hinweis. Da der ESP8266 mit 3.3 V arbeitet, dürfen an seine Eingänge keine höheren Spannungen als 3.3 V angelegt werden! Ein weiterer Vorteil dieses Boards, es ist um ein Rastermaß schmaler und passt daher auf ein einfaches Breadboard.
![]() |
Wie das Titelbild zeigt, wollen wir mit einem der Controller zusammen mit einem LCD-Display, wie es im Adventkalender am 4. 12. vorgestellt wurde, einen RSS-Feed Reader, der auch Datum und Uhrzeit anzeigt, bauen. Mit dem Reader ist es möglich, aktuelle Nachrichten aus einem Newsfeed als Laufschrift anzuzeigen. Datum und Uhrzeit werden von einem NTP Zeitserver bezogen.
Ein RSS-Feed ist ein Nachrichtenüberblick im XML-Format, den verschiedene Informationsserver im Internet anbieten. Im Beispielprogramm wird der Server der ARD verwendet. Da die Nachrichten im XML-Format empfangen werden, ist es einfach, nur bestimmte Teile der gesamten Information, anzuzeigen. Mit 16 Zeichen pro Zeile ist der Platz sehr gering, weshalb wir nur den Titel jeder Nachricht anzeigen.
Hier zum Beispiel der Anfang eines solchen Feeds:
<?xml-stylesheet href="/resources/xsl/rdf_xsl.jsp" type="text/xsl"?>
<rss version="2.0">
<!--
* XML-format for teasering tagesschau.de-headlines. Version: 2.0
* Release-Date:2002/02/04, last updated 2006/06/28
*
* Die Nutzung dieser Inhalte ist ausschliesslich nic⸮ht-kommerziellen Internet-
* Angeboten erlaubt, die Nutzung kann jederzeit von tagesschau.de untersagt
* werden. tagesschau.de übernimmt keinen Support, zudem wird keine Verfügbarkeit
* dieser XML-Datei gewährleistet. Die Inhalte dürfen nicht archiviert werden.
//-->
<channel>
<title>tagesschau.de - Die Nachrichten der ARD</title>
<link>https://www.tagesschau.de</link>
<description>tagesschau.de</description>
<language>de</language>
<copyright>tagesschau.de, Norddeutscher Rundfunk</copyright>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<ttl>30</ttl>
<item>
<title>Corona-Katastrophenfall: Bayern will Maßnahmen verschärfen</title>
<link>https://www.tagesschau.de/inland/corona-bayern-119.html</link>
<description>Die Neuinfektionen mit dem Corona-Virus bleiben............</description>
<guid>https://www.tagesschau.de/inland/corona-bayern-119.html</guid>
<category>Inland</category>
</item>
<item>
<title>……………………………..
Der Root Tag (sprich "tegg" =Etikett, Anhängeschild, Kennzeichnung) <rss> innerhalb dieses Tags ist der Tag <channel>, in dem die einzelnen Nachrichten mit dem Tag <item> enthalten sind. Uns interessiert der Titel-Tag der Items, daher muss der XML-Pfad /rss/channel/item/title lauten.
Zuerst ist ein wenig Lötarbeit erforderlich. Erstens muss das Mikrocontroller Board mit Stiftleisten versehen werden. Dann soll an das Display der I2C Adapter gelötet werden. Ich empfehle den I2C Adapter an der Unterseite anzubringen, da er bei einem geplanten Einbau in ein Gehäuse dann nicht im Weg ist.Die Verdrahtung ist ganz einfach GND und Vcc des Displays verbinden wir mit GND und Vin des Controllers. Die Taktleitung SCL kommt an D1 und die Datenleitung SDA an D2.
![]() |
Nun geht’s ans Programmieren mit der Arduino IDE. Wenn die Unterstützung der Boards mit ESP8266 MCU noch nicht installiert ist, müssen wir das jetzt nachholen. In der Arduino IDE gehen wir über das Menü Datei auf Voreinstellungen oder einfach mit „Strg+;“.
Im Formular klicken wir beim Punkt „Zusätzliche Boardverwalter-URLs“ auf das Symbol rechts neben dem Eingabefeld. Hier können wir nun die URL für den ESP8266 Boardverwalter eingeben:
http://arduino.esp8266.com/stable/package_esp8266com_index.json
![]() |
Nachdem Voreinstellungen gespeichert wurden, rufen wir über das Menü Werkzeuge->Board:->Boardverwalter den Boardverwalter auf. Als Suchbegriff geben wir „esp8266“ ein. Wir erhalten folgenden Eintrag, den wir installieren.
![]() |
Nun können wir im Menü Werkzeuge->Board:->ESP8266 Boards ein Board auswählen. Wir verwenden NodeMCU 1.0….
![]() |
Jetzt ist alles bereit, um den Sketch für den News-Reader zu installieren.
Fast alles, was wir benötigen ist im ESP8266-Paket enthalten. Nur die Bibliotheken für das LCD-Display und zum Auswerten der XML-Daten fehlen. Sie können über die Bibliotheksverwaltung in der Arduino-IDE installiert werden.#include <ESP8266WiFi.h> //WLAN Unterstützung
#include <TZ.h> //Zeitzonen Konstanten #include <LiquidCrystal_I2C.h> //Bibliothek für das LCD Display #include <TinyXML.h> //XML-Interpreter zum Lesen des RSS-Feed //SSID und PSK vom lokalen WLAN #define STASSID "*********************" #define STAPSK "*********************" //Zeitzone mit Sommer/Winterzeit Information #define MYTZ TZ_Europe_Berlin // Timeout zum Lesen des RSS-Feed in Sekunden #define READ_TIMEOUT 10 //Verarbeitungsschritte #define ST_CLEAR 0 //neue Daten vom Server holen #define ST_START 1 //Meldung anzeigen #define ST_MOVE 2 //Meldung durchschieben #define ST_END 3 //Meldungsende anzeigen #define MAXNEWS 10 //Maximale Anzahl der Meldungen #define RSS_SERVER "www.tagesschau.de" //Nachrichtenserver #define RSS_FEED "newsticker.rdf" //Name des Feeds // LCD Adresse = 0x27, Anzahl Zeichen 16 Anzahl Zeilen 2 LiquidCrystal_I2C lcd(0x27,16,2); //WLAN Client Instanz WiFiClient client; //XML Interpreter Instanz TinyXML xml; //Deutsche Sonderzeichen uint8_t font [8][9] { {0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00}, // 0 ° {0x11,0x04,0x0a,0x11,0x1f,0x11,0x11,0x00}, // 1 Ä {0x11,0x0e,0x11,0x11,0x11,0x11,0x0e,0x00}, // 2 Ö {0x11,0x00,0x11,0x11,0x11,0x11,0x0e,0x00}, // 3 Ü {0x0a,0x00,0x1e,0x01,0x0f,0x13,0x0d,0x00}, // 4 ä {0x0a,0x00,0x0e,0x11,0x11,0x11,0x0e,0x00}, // 5 ö {0x0a,0x00,0x12,0x12,0x12,0x12,0x0f,0x00}, // 6 ü {0x0c,0x12,0x12,0x14,0x12,0x12,0x14,0x00} // 7 ß }; uint8_t buffer[4000]; //Buffer für XML-Interpreter uint16_t msglen = 0; //Länge der aktuellen Nachricht String msg; //aktuelle Nachricht String news[MAXNEWS]; //Speicher für Nachrichten uint8_t newsCnt = 0; //Anzahl der aktuellen Nachrichten im Speicher uint8_t curNews = 0; //Index der gerade angezeigten Nachricht uint8_t step = 0; //Aktueller Verarbeitungsschritt uint16_t pos = 0; //Startposition zum Durchschieben //Deutsche Umlaute (UTF8) fürs Display codieren String extraChar(String text){ String res = ""; uint8_t i = 0; char c; while (i<text.length()) { c=text[i]; if (c==195) { //UTF8 Deutsche Umlaute i++; switch (text[i]) { case 164: c=4; break; //ä case 182: c=5; break; //ö case 188: c=6; break; //ü case 159: c=7; break; //ß case 132: c=1; break; //Ä case 150: c=2; break; //Ö case 156: c=3; break; //Ü default: c=0; } } else if (c == 194) { //UTF8 Sonderzeichen i++; if (text[i] == 176) c=0xdf; else c=0; } else if (c > 128) { //normal characters unchanged c=255; } if (c>0) res.concat(c); i++; } return res; } //Diese Funktion wird vom XML-Interpreter aufgerufen, wenn ein XML-Tag gelesen wurde //tagName enthält den vollständigen XML-Pfad des Tags, data den Inhalt des Tags void XML_callback(uint8_t statusflags, char* tagName, uint16_t tagNameLen, char* data, uint16_t dataLen) { if (statusflags & STATUS_TAG_TEXT) { //Serial.println(tagName); //wenn wir einen Titel-Tag finden, und die maximale Anzahl der Meldungen noch //nicht erreicht ist, wird die Meldung gespeichert und der Zähler erhöht if (strcasecmp(tagName,"/rss/channel/item/title")==0) { data[dataLen] = '\0'; Serial.printf("%i %s\n",newsCnt,data); if (newsCnt < MAXNEWS) { news[newsCnt] = data; newsCnt++; } } } } //Neue Nachrichten vom RSS-Feed lesen boolean getNews() { boolean res = false; boolean timedOut = false; char c; newsCnt = 0; //nur wenn wir eine Internetverbindung haben if(WiFi.status()== WL_CONNECTED){ //zuerst mit dem HTTP-Server verbinden Serial.println("Mit Server verbinden"); if(client.connect(RSS_SERVER, 80)) { Serial.println("OK\r\nRequesting data..."); //Nun können wir die XML-Seite mit dem Feed holen client.print("GET /"); client.print(RSS_FEED); client.print(" HTTP/1.1\r\nHost: "); client.print(RSS_SERVER); client.print("\r\nConnection: Close\r\n\r\n"); client.flush(); //den XML-Interpreter vorbereiten xml.reset(); newsCnt = 0; uint32_t t = millis(); // Startzeit while(client.connected()) { if((c = client.read()) >= 0) { //Solange wir Zeichen vom Webserver erhalten, werden diese //zur Interpretation an den XML Interpreter weitergegeben xml.processChar(c); delay(1); //Verzögerung 1ms sonst kommt der XML Interpreter nicht nach t = millis(); // Reset timeout clock } else if((millis() - t) >= (READ_TIMEOUT * 1000)) { //Im Falle eines Timeouts wird die Interpretation abgebrochen Serial.println("---Timeout---"); timedOut = true; break; } } if (timedOut) Serial.println("Timeout"); if(!timedOut && (newsCnt > 0)) { //Falls Nachrichten empfangen wurden, wird die erste Nachricht angezeigt curNews = 0; } } client.stop(); } else { //war keine Internet Verbindung vorhanden //wird ein neuer Verbindungsversuch gestartet //und eine Fehlermeldung angezeigt news[0] = "Keine Internetverbindung!"; newsCnt = 1; curNews = 0; } } //Anzeige aktualisieren void updateDisplay() { //erste Zeile Zeit und Datum time_t now; //aktuelle Zeit struct tm * s_time; //Zeitstruktur aufgesplittet in Jahr, Monat, Tag, Stunden, Minuten und Sekunden char line_buffer[20]; //Buffer für Anzeigenzeile now = time(nullptr); //aktuelle Zeit lesen s_time = localtime(&now); //für die lokale Zeit in die Zeitstruktur umwandeln //Zeilenbuffer mit Uhrzeit und Datum füllen strftime(line_buffer,17,"%d.%m.%Y %H:%M",s_time); //Uhrzeit auf die serielle Schnittstelle ausgeben //Serial.println(line_buffer); //Uhrzeit am Display in Zeile 1 anzeigen lcd.setCursor(0,0); lcd.print(line_buffer); //zweite Zeile Nachrichten lcd.setCursor(0,1); switch (step) { case ST_CLEAR: step = ST_START; //Nächster Schritt if (curNews >= newsCnt) { lcd.print("Aktualisierung.."); getNews(); //neue Nachrichten holen curNews = 0; } else { curNews++; //nächste Nachricht starten lcd.print(" "); if (curNews >= newsCnt) step = ST_END; } msg = extraChar(news[curNews]); msglen = msg.length(); break; case ST_START:lcd.print(msg.substring(0,16)); pos = 0; //Startposition einnehmen step = ST_MOVE; break; case ST_MOVE: pos++; lcd.print(msg.substring(pos,pos+16)); //wenn die Nachricht fertig ist, nächste Nachricht if (pos > (msglen-17)) step=ST_END; break; case ST_END: step = ST_CLEAR; break; } } //Setup Funktion void setup() { Serial.begin(115200); //Serielle Schnittstelle initialisieren //XML-Interpreter initialisieren xml.init((uint8_t *)buffer, sizeof(buffer), &XML_callback); //Display initialisieren und Beleuchtung ein lcd.init(); //bei älteren Versionen der Bibliothek muss der Aufruf lcd.begin(); heißen
lcd.backlight(); //Deutsche Umlaute erzeugen for (uint8_t i = 0; i<8; i++) lcd.createChar(i, font[i]); //Display löschen und Startmeldung anzeigen lcd.clear(); lcd.setCursor(0,0); lcd.print("AZ-Delivery"); lcd.setCursor(0,1); lcd.print("Einen Moment...."); //Interne Uhr konfigurieren configTime(MYTZ, "pool.ntp.org"); //WLAN initialisieren und mit dem WLAN verbinden WiFi.persistent(false); WiFi.mode(WIFI_STA); WiFi.begin(STASSID, STAPSK); uint8_t cnt = 0; //warten bis Verbindung hergestellt wurde while ((WiFi.status() != WL_CONNECTED) && (cnt<10)) { Serial.println(WiFi.status()); cnt++; delay(500); } newsCnt = 0; step = ST_CLEAR; } //Hauptschleife void loop() { //Zeit anzeigen updateDisplay(); //Verzögerung fürs Durchschieben delay(500); }
Wir geben als Suchbegriff „I2C LCD“ ein und finden, etwas weiter unten in der Liste, die gewünschte Bibliothek.
![]() |
Dann geben wir als Suchbegriff „Tiny XML“ ein und erhalten die gewünschte Bibliothek.
![]() |
Ehe wir den Sketch kompilieren, müssen wir die Zugangsdaten für das WLAN an Stelle der Sternchen eintragen.
Eventuell wollt ihr auch einen anderen News-Server, einen anderen Feed auf diesem Server und/oder eine andere Anzahl von Nachrichten auswählen. Dann müsst ihr die entsprechenden #define Einträge ändern. Die Anzahl der Nachrichten sollte nicht größer als 10 gewählt werden.
Wundert euch nicht, wenn beim Kompilieren folgende Warnung angezeigt wird.
WARNUNG: Bibliothek LiquidCrystal_I2C behauptet auf avr Architektur(en) ausgeführt werden zu können und ist möglicherweise inkompatibel mit Ihrem derzeitigen Board, welches auf esp8266 Architektur(en) ausgeführt wird.
Diese Warnung kommt daher, dass in den Spezifikationen zur Bibliothek ein falscher Eintrag vorgenommen wurde. Die Bibliothek funktioniert einwandfrei mit ESP8266 MCUs.
Nachdem alle Nachrichten vom News-Server angezeigt wurden, werden erneut Nachrichten vom Server geholt. Die Uhrzeit wird laufend aktualisiert. Zwischen Sommerzeit und Winterzeit wird automatisch umgeschaltet.
Viel Spaß beim Nachbau.
2 Kommentare
Bernd-Steffen Großmann
Hi Anthony, I have this problem (the first two letters are not readable) too, but only with iOS (Safari). It works properly with Chrome, Firefox, and other browsers on Windows or Android. Sincerely Bernd-Steffen
Anthony Goodhew
Formatting of this blog not working properly.