ESP32 REST-API abfragen: JSON mit ArduinoJson parsen & Live-Daten aufs OLED bringen
Dein ESP32 hängt im WLAN, hat eine IP – und redet trotzdem nur mit sich selbst. Der nächste logische Schritt: Daten aus dem Internet holen. Wetterbericht, Strompreis, Sonnenaufgang, Abfahrtszeiten, Bitcoin-Kurs, der Füllstand deines eigenen Servers. Fast alles davon liegt hinter einer REST-API und kommt als JSON zurück. Dieses Tutorial zeigt den kompletten Weg: HTTP-GET absetzen, HTTPS ohne Zertifikatschaos, JSON zerlegen mit ArduinoJson, Anzeige auf dem OLED – und am Ende eine Abfrageschleife, die auch dann noch läuft, wenn das WLAN mal kurz weg ist.
Was bei einer API-Abfrage eigentlich passiert
Eine REST-API ist im Kern nichts anderes als eine Webseite, die statt HTML strukturierte Daten zurückgibt. Du schickst eine ganz normale HTTP-Anfrage an eine URL, der Server antwortet mit einem Statuscode und einem Textkörper. Bei einer API ist dieser Textkörper JSON – ein Format aus geschweiften Klammern, Schlüsseln und Werten.
GET /data/2.5/weather?q=Berlin&units=metric HTTP/1.1
Host: api.example.com
--- Antwort ---
HTTP/1.1 200 OK
Content-Type: application/json
{
"main": { "temp": 18.4, "humidity": 71, "pressure": 1014 },
"weather": [ { "main": "Clouds", "description": "bedeckt" } ],
"name": "Berlin"
}
Für den ESP32 zerfällt die Aufgabe damit in drei Teile, die du getrennt voneinander lösen und testen kannst:
| Schritt | Zuständig | Typischer Fehler |
|---|---|---|
| 1. Verbindung | WiFi.h |
falsches Passwort, 5-GHz-Netz, zu schwaches Signal |
| 2. Anfrage |
HTTPClient / WiFiClientSecure
|
HTTP-Code 401, 403 oder -1, TLS-Handshake schlägt fehl |
| 3. Auswertung | ArduinoJson |
Speicher zu klein, falscher Pfad, NoMemory
|
ℹ️ Wichtig für die Fehlersuche: Der HTTP-Statuscode und das JSON-Parsing sind zwei völlig getrennte Baustellen. Ein 200 OK heißt nur, dass der Server geantwortet hat – ob die Antwort das enthält, was du erwartest, steht auf einem anderen Blatt. Gib deshalb bei jedem Problem zuerst den rohen Antworttext auf dem Serial Monitor aus, bevor du am Parser schraubst.
Das brauchst du
Software: Arduino IDE mit ESP32-Boardpaket und die Bibliothek ArduinoJson (Bibliotheksverwalter, Autor Benoit Blanchon) in Version 7 oder neuer.
1Verkabelung
| Modul | Pin | ESP32 | Hinweis |
|---|---|---|---|
| OLED SSD1306 | VCC | 3V3 | keine 5 V nötig |
| OLED SSD1306 | GND | GND | gemeinsame Masse |
| OLED SSD1306 | SDA | GPIO21 | Standard-I2C beim WROOM32 |
| OLED SSD1306 | SCL | GPIO22 | Adresse meist 0x3C |
| Rotary Encoder | CLK / DT / SW | GPIO32 / 33 / 25 | optional, zum Blättern |
⚠️ Beim ESP32-C3 liegen die I2C-Pins woanders. Dort startest du den Bus explizit mit Wire.begin(8, 9); vor display.begin(...). Wenn dein OLED schwarz bleibt, ist das in neun von zehn Fällen die Ursache – nicht ein defektes Display. Ein I2C-Scanner bringt in dreißig Sekunden Klarheit.
2Die erste Abfrage: rohe Antwort auf dem Serial Monitor
Bevor irgendetwas geparst wird, willst du sehen, was überhaupt ankommt. Dieser Sketch verbindet sich mit dem WLAN, holt eine Testantwort und gibt sie unverändert aus:
#include <WiFi.h>
#include <HTTPClient.h>
const char* WLAN_SSID = "DeinNetz";
const char* WLAN_PASS = "DeinPasswort";
// Testendpunkt ohne Schluessel: liefert die aktuelle Zeit als JSON
const char* API_URL = "http://worldtimeapi.org/api/timezone/Europe/Berlin";
void wlanVerbinden() {
WiFi.mode(WIFI_STA);
WiFi.begin(WLAN_SSID, WLAN_PASS);
Serial.print(F("Verbinde"));
uint8_t versuche = 0;
while (WiFi.status() != WL_CONNECTED && versuche < 40) {
delay(250);
Serial.print('.');
versuche++;
}
Serial.println();
if (WiFi.status() == WL_CONNECTED) {
Serial.print(F("IP: "));
Serial.println(WiFi.localIP());
Serial.print(F("RSSI: "));
Serial.println(WiFi.RSSI());
} else {
Serial.println(F("WLAN fehlgeschlagen"));
}
}
void setup() {
Serial.begin(115200);
delay(300);
wlanVerbinden();
if (WiFi.status() != WL_CONNECTED) return;
HTTPClient http;
http.begin(API_URL);
http.setTimeout(8000); // nicht ewig warten
http.addHeader("User-Agent", "ESP32-MAKEROO");
int code = http.GET();
Serial.print(F("HTTP-Code: "));
Serial.println(code);
if (code > 0) {
String antwort = http.getString();
Serial.print(F("Laenge: "));
Serial.println(antwort.length());
Serial.println(F("--- Rohantwort ---"));
Serial.println(antwort);
} else {
// Negative Codes sind Client-Fehler, keine Serverantworten
Serial.print(F("Fehler: "));
Serial.println(http.errorToString(code));
}
http.end(); // Verbindung sauber schliessen
}
void loop() {
}
ℹ️ Positive und negative Codes bedeuten Verschiedenes. Alles ab 100 kommt vom Server: 200 heißt „alles gut“, 401 „Schlüssel fehlt oder falsch“, 429 „zu viele Anfragen“, 500 „Server hat ein Problem“. Negative Werte wie -1 oder -11 erzeugt der ESP32 selbst und bedeuten: gar keine Antwort erhalten – DNS, Timeout, TLS oder schlicht kein Netz. http.errorToString(code) übersetzt sie in Klartext.
⚠️ http.end() nicht vergessen. Jede offene Verbindung belegt einen Socket und einige Kilobyte Heap. Wer in der loop() alle paar Sekunden abfragt und nie schließt, hat nach einer halben Stunde einen Reboot mit Guru Meditation Error. Das ist der häufigste Grund dafür, dass ein API-Projekt „erst funktioniert und dann irgendwann nicht mehr“.
3JSON zerlegen mit ArduinoJson
Jetzt der eigentliche Trick. Man könnte mit indexOf() und substring() im Antworttext herumsuchen – das funktioniert genau so lange, bis der Server ein Feld umsortiert. ArduinoJson baut stattdessen einen echten Objektbaum auf, aus dem du Werte über ihren Pfad holst:
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
struct Wetter {
float temperatur = NAN;
float gefuehlt = NAN;
uint8_t feuchte = 0;
uint16_t druck = 0;
String beschreibung = "";
bool gueltig = false;
};
Wetter aktuell;
bool wetterHolen(const String& url) {
if (WiFi.status() != WL_CONNECTED) return false;
HTTPClient http;
http.begin(url);
http.setTimeout(8000);
int code = http.GET();
if (code != HTTP_CODE_OK) {
Serial.print(F("HTTP-Fehler: "));
Serial.println(code);
http.end();
return false;
}
// Ab ArduinoJson 7: JsonDocument waechst dynamisch mit
JsonDocument doc;
// Direkt aus dem Stream parsen spart den kompletten String im RAM
DeserializationError fehler = deserializeJson(doc, http.getStream());
http.end();
if (fehler) {
Serial.print(F("JSON-Fehler: "));
Serial.println(fehler.c_str());
return false;
}
// Pfade wie im JSON-Baum. Fehlt ein Feld, kommt der Default zurueck.
aktuell.temperatur = doc["main"]["temp"] | NAN;
aktuell.gefuehlt = doc["main"]["feels_like"]| NAN;
aktuell.feuchte = doc["main"]["humidity"] | 0;
aktuell.druck = doc["main"]["pressure"] | 0;
aktuell.beschreibung = doc["weather"][0]["description"] | "unbekannt";
aktuell.gueltig = !isnan(aktuell.temperatur);
return aktuell.gueltig;
}
void wetterAusgeben() {
if (!aktuell.gueltig) {
Serial.println(F("Keine gueltigen Daten"));
return;
}
Serial.print(aktuell.temperatur, 1);
Serial.print(F(" C, "));
Serial.print(aktuell.feuchte);
Serial.print(F(" %, "));
Serial.print(aktuell.druck);
Serial.print(F(" hPa, "));
Serial.println(aktuell.beschreibung);
}
Der Pipe-Operator ist dein Sicherheitsnetz
Das | NAN hinter jedem Zugriff ist kein Zufall. Es liefert einen Ersatzwert, falls das Feld fehlt oder den falschen Typ hat. Ohne diesen Default bekommst du bei einer unerwarteten Antwort eine stille Null – und wunderst dich, warum dein Thermostat plötzlich bei 0 °C heizt.
💡 Große Antworten filtern statt vergrößern. Manche APIs schicken 40 KB JSON, von denen du drei Werte brauchst. Mit einem Filter parst du nur, was dich interessiert – der Rest wird beim Lesen verworfen und belegt nie Speicher:
// Nur die Felder behalten, die wirklich gebraucht werden
JsonDocument filter;
filter["main"]["temp"] = true;
filter["main"]["humidity"] = true;
filter["weather"][0]["description"] = true;
JsonDocument doc;
DeserializationError fehler = deserializeJson(
doc, http.getStream(), DeserializationOption::Filter(filter));
// Arrays durchlaufen, wenn die API eine Liste liefert
JsonArray liste = doc["list"].as<JsonArray>();
for (JsonObject eintrag : liste) {
const char* zeit = eintrag["dt_txt"] | "";
float t = eintrag["main"]["temp"] | NAN;
Serial.print(zeit);
Serial.print(F(" -> "));
Serial.println(t, 1);
}
// Verbrauchten Speicher pruefen - wichtig beim Dimensionieren
Serial.print(F("JSON belegt: "));
Serial.print(doc.memoryUsage());
Serial.println(F(" Byte"));
ℹ️ ArduinoJson 6 oder 7? In Version 6 musstest du die Größe vorab festlegen: StaticJsonDocument<1024> doc;. Seit Version 7 gibt es nur noch JsonDocument doc;, das im Heap dynamisch wächst. Viele Tutorials im Netz zeigen noch die alte Schreibweise – wenn dein Sketch mit StaticJsonDocument was not declared abbricht, ist genau das der Grund. Beide Varianten funktionieren, aber mische sie nicht.
4HTTPS: die Hürde, an der die meisten hängenbleiben
Fast jede ernstzunehmende API läuft heute über https://. Der ESP32 kann das – aber er will wissen, wem er vertrauen soll. Es gibt drei Wege, und du solltest wissen, welchen du gerade gehst:
| Verfahren | Code | Sicherheit | Wann sinnvoll |
|---|---|---|---|
| Ohne Prüfung | client.setInsecure() |
verschlüsselt, aber nicht authentifiziert | Bastelprojekt im Heimnetz, schneller Test |
| Root-Zertifikat | client.setCACert(cert) |
voll geprüft | alles, was länger als eine Woche laufen soll |
| Fingerprint | client.setFingerprint(...) |
geprüft, aber bricht bei jedem Zertifikatswechsel | eher historisch, heute nicht mehr empfohlen |
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// Root-Zertifikat der Zertifizierungsstelle, PEM-Format.
// Im Browser: Schloss-Symbol -> Zertifikat -> oberste Ebene exportieren.
static const char ROOT_CA[] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
... hier das Root-Zertifikat einfuegen ...
-----END CERTIFICATE-----
)CERT";
bool apiAbfragenSicher(const String& url, JsonDocument& ziel) {
WiFiClientSecure client;
// Variante A - schnell und unsicher, nur zum Testen:
// client.setInsecure();
// Variante B - so gehoert es sich:
client.setCACert(ROOT_CA);
client.setTimeout(10); // Sekunden bei WiFiClientSecure
HTTPClient http;
if (!http.begin(client, url)) {
Serial.println(F("begin() fehlgeschlagen"));
return false;
}
http.addHeader("Accept", "application/json");
// Viele APIs erwarten den Schluessel im Header statt in der URL:
// http.addHeader("Authorization", "Bearer DEIN_TOKEN");
int code = http.GET();
if (code == 429) {
Serial.println(F("Rate Limit - Abfrageintervall erhoehen"));
http.end();
return false;
}
if (code != HTTP_CODE_OK) {
Serial.print(F("HTTP "));
Serial.println(code);
http.end();
return false;
}
DeserializationError fehler = deserializeJson(ziel, http.getStream());
http.end();
if (fehler) {
Serial.print(F("JSON: "));
Serial.println(fehler.c_str());
return false;
}
return true;
}
⚠️ TLS braucht Zeit und eine korrekte Uhr. Ein Handshake kostet auf dem ESP32 rund 1 bis 3 Sekunden und etwa 40 KB Heap – plane das ein. Und: Zertifikate haben ein Gültigkeitsdatum. Startet dein Board mit der Systemzeit 1. Januar 1970, hält es jedes gültige Zertifikat für „noch nicht gültig“ und bricht ab. Hol dir deshalb vor der ersten HTTPS-Anfrage die Uhrzeit per NTP – wie das geht, steht im Artikel ESP32 Uhrzeit per NTP holen.
💡 Kein passendes Root-Zertifikat zur Hand? Setze für den ersten Test client.setInsecure() und prüfe, ob die Abfrage grundsätzlich klappt. Wenn ja, weißt du: Das Problem liegt nur am Zertifikat, nicht an URL, Schlüssel oder Parser. Danach tauschst du es gegen setCACert(). Für ein Gerät, das dauerhaft läuft, sollte setInsecure() nicht im finalen Sketch stehen.
5Live-Anzeige auf dem OLED
Zahlen im Serial Monitor sind schön zum Debuggen, aber niemand stellt einen Laptop neben den Kaffeevollautomaten. Auf das SSD1306 passen Temperatur groß, Details klein und eine Statuszeile:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void displayStarten() {
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("OLED nicht gefunden"));
while (true) { delay(1000); }
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.display();
}
void zeigeStatus(const char* text) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 28);
display.print(text);
display.display();
}
void zeigeWetter(const Wetter& w, uint32_t alterSekunden) {
display.clearDisplay();
// Kopfzeile mit Ort
display.setTextSize(1);
display.setCursor(0, 0);
display.print(F("Berlin"));
// WLAN-Balken rechts oben aus dem RSSI
int8_t rssi = WiFi.RSSI();
uint8_t balken = 0;
if (rssi > -60) balken = 4;
else if (rssi > -70) balken = 3;
else if (rssi > -80) balken = 2;
else if (rssi <= -80) balken = 1;
for (uint8_t i = 0; i < balken; i++) {
display.fillRect(110 + i * 4, 8 - (i + 1) * 2, 3, (i + 1) * 2, SSD1306_WHITE);
}
// Grosse Temperatur
display.setTextSize(3);
display.setCursor(0, 14);
if (w.gueltig) {
display.print(w.temperatur, 1);
} else {
display.print(F("--.-"));
}
display.setTextSize(1);
display.print(F(" C"));
// Detailzeile
display.setTextSize(1);
display.setCursor(0, 42);
display.print(w.feuchte);
display.print(F("% "));
display.print(w.druck);
display.print(F(" hPa"));
// Beschreibung, auf Displaybreite gekuerzt
display.setCursor(0, 52);
String kurz = w.beschreibung;
if (kurz.length() > 14) kurz = kurz.substring(0, 14);
display.print(kurz);
// Alter der Daten rechts unten - verraet stille Ausfaelle
display.setCursor(92, 52);
display.print(alterSekunden / 60);
display.print(F("m"));
display.display();
}
ℹ️ Das Alter der Daten mit anzuzeigen ist der wichtigste Kniff im ganzen Sketch. Ein Display, das seit sechs Stunden dieselbe Temperatur zeigt, sieht exakt aus wie eines, das gerade aktualisiert hat. Ein kleines „3m“ in der Ecke sagt dir sofort, ob die Verbindung noch steht – ohne dass du den Serial Monitor öffnen musst.
6Robust abfragen: nicht blockieren, sauber wiederholen
Ein delay(600000) in der loop() ist bequem und falsch: Zehn Minuten lang reagiert dein Gerät auf nichts mehr. Diese Schleife fragt regelmäßig ab, wiederholt bei Fehlern mit wachsendem Abstand und bleibt zwischendurch bedienbar:
const uint32_t INTERVALL_MS = 10UL * 60UL * 1000UL; // 10 Minuten
const uint32_t RETRY_BASIS_MS = 15UL * 1000UL; // 15 s
const uint8_t RETRY_MAX = 5;
uint32_t letzteAbfrage = 0;
uint32_t naechsteAbfrage = 0;
uint8_t fehlversuche = 0;
Wetter aktuell;
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
displayStarten();
zeigeStatus("Verbinde WLAN...");
WiFi.mode(WIFI_STA);
WiFi.setAutoReconnect(true); // ESP32 haelt die Verbindung selbst
WiFi.begin(WLAN_SSID, WLAN_PASS);
naechsteAbfrage = 0; // sofort beim Start abfragen
}
void loop() {
uint32_t jetzt = millis();
// WLAN weg? Nur melden, der Autoreconnect erledigt den Rest
if (WiFi.status() != WL_CONNECTED) {
static uint32_t letzteMeldung = 0;
if (jetzt - letzteMeldung > 5000) {
letzteMeldung = jetzt;
Serial.println(F("warte auf WLAN"));
}
}
if ((int32_t)(jetzt - naechsteAbfrage) >= 0 &&
WiFi.status() == WL_CONNECTED) {
bool ok = wetterHolen(API_URL);
if (ok) {
letzteAbfrage = jetzt;
fehlversuche = 0;
naechsteAbfrage = jetzt + INTERVALL_MS;
Serial.println(F("Update ok"));
} else {
fehlversuche++;
// Exponentiell zurueckziehen: 15s, 30s, 60s, 120s, 240s
uint32_t wartezeit = RETRY_BASIS_MS * (1UL << min(fehlversuche, RETRY_MAX));
naechsteAbfrage = jetzt + wartezeit;
Serial.print(F("Fehlversuch "));
Serial.print(fehlversuche);
Serial.print(F(", naechster Versuch in "));
Serial.print(wartezeit / 1000);
Serial.println(F(" s"));
}
}
// Anzeige unabhaengig von der Abfrage aktualisieren
static uint32_t letztesBild = 0;
if (jetzt - letztesBild >= 1000) {
letztesBild = jetzt;
uint32_t alter = (letzteAbfrage == 0) ? 0 : (jetzt - letzteAbfrage) / 1000;
zeigeWetter(aktuell, alter);
}
// Heap im Blick behalten - Leck zeigt sich hier zuerst
static uint32_t letzterHeapCheck = 0;
if (jetzt - letzterHeapCheck >= 60000) {
letzterHeapCheck = jetzt;
Serial.print(F("Freier Heap: "));
Serial.println(ESP.getFreeHeap());
}
}
💡 Exponentielles Zurückziehen ist keine Spielerei. Wenn eine API kurz ausfällt und tausend Geräte im Sekundentakt weiterhämmern, wird aus der kurzen Störung eine lange. Wachsende Wartezeiten entlasten den Server und dich: Dein Board fragt bei einem Dauerausfall nur noch alle paar Minuten und verheizt keine Batterie. Falls dein Projekt am Akku hängt, kombiniere das mit Deep Sleep.
ℹ️ Die Zeile (int32_t)(jetzt - naechsteAbfrage) >= 0 sieht umständlich aus, ist aber überlaufsicher. millis() läuft nach 49,7 Tagen über. Die Differenz zweier vorzeichenloser Werte, in int32_t gecastet, liefert auch über diesen Punkt hinweg das richtige Ergebnis. Ein simples jetzt >= naechsteAbfrage würde dein Gerät nach knapp sieben Wochen für 49 Tage einschlafen lassen.
Troubleshooting
⚠️ HTTP-Code -1 bei jeder Anfrage: Meist DNS. Prüfe mit WiFi.hostByName("api.example.com", ip), ob der Name überhaupt aufgelöst wird. Hilft das nicht, setze testweise einen festen DNS-Server in WiFi.config(). Zweithäufigste Ursache: Du nutzt eine https://-URL mit dem einfachen http.begin(url) statt mit WiFiClientSecure.
⚠️ DeserializationError::NoMemory: Die Antwort ist größer als der freie Heap. Setze einen Filter (siehe Schritt 3), parse direkt aus dem Stream statt über einen String, und schau mit ESP.getFreeHeap() nach, wie viel überhaupt noch frei ist. Auf dem ESP8266 ist das schnell erreicht – dort sind 40 KB freier Heap schon üppig.
⚠️ DeserializationError::InvalidInput: Was ankommt, ist kein JSON. Sehr oft ist es eine HTML-Fehlerseite („403 Forbidden“) oder eine Weiterleitung. Gib die Rohantwort aus – der Grund steht meist im Klartext darin. Bei Weiterleitungen hilft http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);.
⚠️ Funktioniert 20 Mal, dann Reboot: Speicherleck. Fehlt irgendwo ein http.end(), oder du legst WiFiClientSecure global statt lokal an. Lass ESP.getFreeHeap() jede Minute mitlaufen – wenn der Wert stetig sinkt, hast du die Ursache eingekreist.
⚠️ HTTP 429 „Too Many Requests“: Du fragst zu oft. Viele kostenlose APIs erlauben 60 Anfragen pro Stunde oder 1000 pro Tag. Für Wetterdaten reicht ein Intervall von 10 bis 15 Minuten völlig – das Wetter ändert sich nicht sekündlich.
⚠️ Umlaute erscheinen als kryptische Zeichen: JSON kommt als UTF-8, das OLED erwartet je nach Schriftart Latin-1. Entweder du ersetzt die Umlaute vor der Ausgabe, oder du nutzt display.cp437(true) und eine passende Zeichentabelle. Am unkompliziertesten: Frag die API in einer Sprache ohne Umlaute ab.
⚠️ TLS bricht mit connection refused ab: Zu wenig Heap für den Handshake. Schließe alles andere, bevor du die Anfrage startest, und lege große Puffer nicht global an. Ein ESP32-S3 mit PSRAM löst das Problem, falls dein Projekt ohnehin größer wird.
Praxistipps
- Erst im Browser testen. Ruf die API-URL im Browser auf und schau dir die Antwort an. Was dort nicht funktioniert, wird auf dem ESP32 nicht besser.
-
API-Schlüssel nicht in den Sketch tippen. Leg ihn in eine separate
secrets.h, die du beim Teilen des Codes weglässt. Wer seinen Schlüssel einmal auf GitHub hatte, macht das nie wieder. - Kleines JSON zuerst. Bau den Parser gegen eine kurze, feste Beispielantwort im Code auf, bevor du ihn ans Netz hängst. So trennst du Parser-Fehler sauber von Netzwerkfehlern.
- Nur das nehmen, was du brauchst. Filter statt großer Dokumente – das spart Heap und macht den Sketch schneller.
- Werte mitschreiben. Mit einem Micro-SD-Modul hast du nach einer Woche eine Datei, aus der du echte Verläufe zeichnen kannst – siehe Arduino Datenlogger mit Micro-SD-Karte.
- Zugangsdaten nicht fest verdrahten. Ein Captive Portal macht dein Gerät auch in fremden Netzen einsatzbereit, ohne neu zu flashen.
- Daten weiterverteilen statt nur anzeigen. Wer die geholten Werte per MQTT ins Smart Home schiebt, macht aus dem Display eine Datenquelle für alle Geräte im Haus.
- Ein Kondensator an der Versorgung. Der ESP32 zieht beim Senden kurzzeitig über 300 mA. Ein 470 µF Elko direkt am Board verhindert Brownouts genau in dem Moment, in dem die Anfrage rausgeht.
🚀 Bauteile für dein API-Display
- ESP32 DEV KIT WROOM32 (USB-C) – WLAN und TLS in einem Board
- 0,96 Zoll OLED SSD1306 128x64 oder 1,3 Zoll OLED
- 1,8 Zoll TFT ST7735 – für Wettersymbole in Farbe
- ESP32-C3 Mini – die kompakte Variante fürs Regal
- Rotary Encoder KY-040 – zwischen mehreren Datenquellen blättern
- Micro-SD-Kartenmodul – Langzeitprotokoll der abgerufenen Werte
- LM2596S Step-Down-Wandler – stabile Dauerversorgung
- ESP32 Acryl-Gehäuse – aus dem Breadboard-Aufbau wird ein Gerät
- Breadboard 400 Kontakte und Dupont-Jumperkabel
Fazit
Eine API abzufragen ist der Moment, in dem dein ESP32 vom Bastelaufbau zum vernetzten Gerät wird. Technisch sind es drei Bausteine – HTTP-Anfrage, JSON-Parser, Anzeige – und jeder davon lässt sich einzeln testen. Genau darin liegt der Schlüssel: Wer bei einem Fehler zuerst die Rohantwort ansieht, spart sich Stunden Suche im Parser.
Drei Dinge machen den Unterschied zwischen einem Sketch, der einmal läuft, und einem Gerät, das monatelang durchhält: immer http.end(), Filter statt riesiger JSON-Dokumente und eine nicht-blockierende Schleife mit wachsender Wartezeit. Hast du das einmal sauber aufgebaut, tauschst du für das nächste Projekt nur noch die URL und zwei Feldnamen aus – und holst dir statt Wetterdaten eben Strompreise, Abfahrtszeiten oder die Werte deiner eigenen Sensoren aus dem Keller.