Logo
Lisa Schneider
2 Tage vor
Ein hängendes Programm sieht aus wie ein totes Gerät. Dabei startet meist unsichtbar ein kleiner Wächter den Mikrocontroller einfach neu.

Kennt ein Sensor nach Wochen plötzlich keine Meldung mehr, zeigt sich erst im Log, ob ein Watchdog den Neustart erzwungen hat. Wer ihn nicht kennt, dreht bei jedem Hänger die Stromversorgung von Hand.

Ein Watchdog ist ein Zähler, den die laufende Firmware (das Programm auf dem Chip) regelmäßig zurücksetzen muss; bleibt das aus, löst der Chip einen Reset aus. Er ist ein eigener, von der Firmware unabhängiger Schaltungsteil und zählt wie ein Timer von einem Startwert gegen null. Nur der regelmäßige Aufruf eines Zurücksetz-Befehls lädt den Zähler wieder auf.

Am Arduino Uno aktiviert die avr/wdt.h-Bibliothek den Watchdog des ATmega328P, mit bis zu 8 Sekunden Timeout. Beim ESP32 konfiguriert man den Task-Watchdog mit esp_task_wdt_init, ein Task (Programmteil) meldet sich mit esp_task_wdt_add an und bedient ihn mit esp_task_wdt_reset. Der Befehl gehört ans Ende der Hauptschleife, denn nur dort ist bewiesen, dass der Durchlauf hängenfrei war. Nach einem Neustart liefert der ESP32 den Grund über esp_reset_reason, etwa Watchdog oder Brownout (Reset bei zu niedriger Versorgungsspannung); dieser Grund gehört ins Log.

Verwechselt wird der Watchdog gern mit einem Einschalten. Tatsächlich ist er eine Rückkehr in einen definierten Startzustand, ohne dass jemand die Stromversorgung unterbrechen muss. Vor dem Aktivieren muss die Initialisierung durchlaufen sein, sonst löst ein langsamer WLAN-Verbindungsaufbau den Timeout schon vor der Hauptschleife aus.

Der Watchdog ist keine Fehlerbehebung, sondern ein Zurückversetzen in einen definierten Zustand. Die eigentliche Fehlersuche beginnt mit dem Reset-Grund im Log.

📌 Zähler gegen null · Zurücksetzen in der Hauptschleife · Reset-Grund im Log

📚 IoT von Grund auf · Tag 4 von 30
#esp32 #Mikrocontroller #firmware
Lisa Schneider
2 Tage vor
Wer in die Interrupt-Routine Serial.println() schreibt, wundert sich später über abgebrochene Ausgaben. Der Irrtum ist verblüffend weit verbreitet.

Viele Einsteiger nehmen an, die Unterbrechungsfunktion sei der richtige Ort für alles, was zum Ereignis gehört. Schließlich heißt sie Interrupt-Service-Routine, kurz ISR – dort gehört also der Service hin.

Tatsächlich ist ein Interrupt nur ein Hardware-Signal, das den Mikrocontroller sofort aus dem laufenden Programm herausholt. Er pausiert den Code an der aktuellen Stelle, springt in eine vorher festgelegte Funktion und kehrt danach exakt zurück. In dieser ISR stehen nur kurze Aktionen: ein Flag setzen oder einen Zähler erhöhen.

Der Irrtum entsteht, weil das Ereignis und die Bearbeitung im Alltag zusammengehören. Aber während die ISR läuft, sind oft weitere Interrupts gesperrt; eine lange ISR verzögert deshalb auch andere kurzzeitige Ereignisse.

Ein Taster an einem GPIO, also einem per Software einstellbaren digitalen Pin, löst per attachInterrupt() bei einer Flanke aus, also dem Wechsel von Low nach High. Die ISR erhöht nur einen Zähler. Prellen, das kurzzeitige unkontrollierte Öffnen und Schließen des mechanischen Kontakts, zählt dabei trotzdem mehrere Flanken pro Druck. Eine Sperrzeit in der Auswertung in der Hauptschleife behebt das, nicht in der ISR selbst.

Woran man es erkennt: Die ISR enthält nur volatile deklarierte Variablen, also solche, die der Compiler nicht wegoptimieren darf, weil ISR und loop() sie gemeinsam nutzen, und minimalste Befehle; auf dem ESP32 trägt sie zusätzlich das Attribut IRAM_ATTR. Alles Langsame wie Ausgaben und Netzwerkzugriffe liegt in loop(), gesteuert über Flags.

Interrupt heißt nicht „hier wird alles erledigt“, sondern „hier wird nur vermerkt, dass etwas passiert ist“. Merken: kurz unterbrechen, schnell zurückkehren.

📌 Interrupt · ISR · volatile

📚 IoT von Grund auf · Tag 4 von 30
#Mikrocontroller #esp32 #Arduino
Lisa Schneider
2 Tage vor
delay() und millis() sehen auf den ersten Blick ähnlich aus: Beide drehen sich um Millisekunden. Doch der eine hält das Programm an, der andere nie.

Die Verwechslung ist verständlich, weil beide Zeit in Millisekunden behandeln. Wer „warte eine Sekunde“ denkt, greift schnell zu delay(1000) – und wundert sich später über tote Tasten.

delay() ist ein Befehl, der das Programm an dieser Stelle pausiert. Die gesamte Hauptschleife, also die loop()-Funktion, steht dabei still. Ein delay(1000) bei einer blinkenden LED blockiert eine Taste für eine volle Sekunde; ein kurzer Druck bleibt meist unbemerkt. Auch Sensorwerte und Netzwerkereignisse werden während der Pause nicht bearbeitet.

millis() ist eine Funktion, die beim Aufruf die Millisekunden seit dem Programmstart als Zahl zurückgibt. Sie hält nichts an, sie liest nur die Uhr und kehrt sofort zurück. Ein typisches Beispiel: eine LED im Sekundentakt blinken lassen, die Taste aber in jedem Schleifendurchlauf lesen. Dazu notiert man die Startzeit in einer Variablen, prüft später, ob das Intervall verstrichen ist, und führt die Aktion aus. Die Startzeit speichert man im Typ unsigned long, einem vorzeichenlosen 32-Bit-Wert.

delay() verwaltet die Zeit, indem sie das Programm opfert. millis() verwaltet die Zeit, während das Programm weiterläuft. Bei mehreren Aufgaben mit unterschiedlichen Intervallen bekommt jede ihre eigene Zeitvariable.

Faustregel: Für kurze Pausen ohne Nebenläufigkeit genügt delay(). Sobald während der Wartezeit etwas anderes passieren soll, immer millis() mit Zeitvergleich nehmen.

Ein Zeitvergleich heißt jetzt minus Startzeit größer gleich Intervall, nicht jetzt größer gleich Zielzeit. Die Differenz bleibt auch beim Überlauf korrekt, den der Zähler nach rund 49,7 Tagen macht.

📌 millis() statt delay() · Differenz bilden · unsigned long

📚 IoT von Grund auf · Tag 4 von 30
#Arduino #Mikrocontroller #esp32 #iot
Lisa Schneider
2 Tage vor
Eine Ampel an einer Einbahnstraße arbeitet wie delay() im Mikrocontroller. Alles hält an, bis die Wartezeit vorbei ist.

Stehende Autos wollen abbiegen, Fußgänger wollen queren, ein Krankenwagen will durch. Die Ampel interessiert das nicht. Sie zählt rot herunter und lässt nichts vorbei. Erst wenn die Zeit um ist, fließt der Verkehr wieder.

So arbeitet delay() auf einem Arduino oder ESP32: Die Funktion pausiert das Programm für die angegebenen Millisekunden. Die Arduino-Firmware besteht aus der Endlosschleife loop(), in der alle Aufgaben drankommen müssen. Während delay() läuft, zählt der Controller nur Zeit ab. Tasten, Sensorabfragen und Netzwerkereignisse warten, bis die Schleife wieder frei ist.

Eine Taste soll eine LED im Sekundentakt blinken lassen. Mit delay(1000) blockiert die Schleife für eine volle Sekunde, ein kurzer Tastendruck bleibt meist unbemerkt. Stattdessen notiert man die Startzeit mit millis(), dem Millisekundenzähler seit dem Start, und prüft in jedem Durchlauf, ob das Intervall verstrichen ist. Die Taste bleibt dadurch ständig lesbar. Beim Entprellen, dem Unterdrücken des mechanischen Nachschwingens eines Tasters, bremst eine millis()-Sperrzeit nur diese eine Taste aus statt der ganzen Schleife.

Das Bild hat eine Grenze: Die Ampel regelt bewusst, wer fährt und wer wartet. delay() trifft keine solche Entscheidung, es lähmt ausnahmslos alle Aufgaben. Eine kurze Pause am Programmende ist harmlos, solange dort keine Eingaben anfallen.

delay() heißt nicht „Programm pausieren lassen“, sondern „alle Aufgaben gleichzeitig anhalten“. Wer mehrere Aufgaben bedient, vergleicht Zeitdifferenzen mit millis() statt zu warten.

📌 blockierendes Warten · millis()-Vergleich · reaktionsfähige Schleife

📚 IoT von Grund auf · Tag 4 von 30
#Arduino #Mikrocontroller #firmware
Lisa Schneider
3 Tage vor
Die meisten Anfänger raten, wo ihre Firmware hängt. Dabei sagt es das Programm selbst – über die Verbindung, die es beim Flashen ohnehin nutzt.

Wer ein erstes IoT-Programm auf einen Mikrocontroller lädt, trifft schnell auf Serial.println(). Wer nicht weiß, was dahinterläuft, sieht nur wirre Zeichen im Monitor und hält die Platine für kaputt.

Der serielle Monitor der Arduino-IDE zeigt Textausgaben der Firmware über die USB-Verbindung an, etwa mit Serial.println(). Dahinter steckt dieselbe UART-Verbindung, also die serielle Schnittstelle mit einer TX- und einer RX-Leitung, über die auch die Firmware in den Flash-Speicher geschrieben wird. UART überträgt Daten ohne gemeinsamen Takt, deshalb müssen Firmware und Monitor dieselbe Baudrate verwenden, also dieselbe Übertragungsgeschwindigkeit in Bits pro Sekunde.

In der Praxis sieht das so aus: In setup(), dem Vorbereitungsteil, der genau einmal läuft, startet Serial.begin() die Schnittstelle und legt die Baudrate fest. Danach gibt die Firmware mit Serial.print() Text aus dem laufenden loop(), der Endlosschleife nach dem Start, an den PC. Serial.println() fügt am Ende einen Zeilenumbruch an, sodass jede Ausgabe eine eigene Zeile erhält. Vor dem WLAN-Verbinden etwa eine Zeile „WLAN verbinde…“, danach die Antwort der Firmware.

Verwechselt wird der Monitor gern mit einem Messgerät. Er ist keins: Er zeigt nur, was die Firmware selbst ausgibt, etwa den gelesenen Pin-Zustand, nicht was ein Multimeter messen würde. Auch Serial.begin() gehört in setup(), nicht in loop(), sonst wiederholt die Firmware die Startarbeit bei jedem Durchlauf und kann Abläufe stören, die nur beim Start gehören.

Der serielle Monitor ist kein separates Werkzeug, sondern dasselbe UART-Kabel, nur in Gegenrichtung. Er ersetzt kein Messgerät – aber er ersetzt das Raten.

📌 Serieller Monitor · Serial.println() · Baudrate

📚 IoT von Grund auf · Tag 3 von 30
#Arduino #esp32 #Mikrocontroller
Lisa Schneider
3 Tage vor
Viele halten UART für ein Kabel mit einem Draht. Dabei braucht die einfachste serielle Verbindung zwei Pins und eine Masseleitung.

Viele Einsteiger denken, eine Datenleitung reiche: Ein Gerät sendet, das andere hört zu, wie bei einem Lautsprecher. Plausibel klingt das, weil USB und viele Kabel im Alltag ja auch nur „ein Kabel“ sind. Man verbindet TX mit TX und wundert sich, dass nichts ankommt.

Tatsächlich arbeitet UART, kurz für Universal Asynchronous Receiver Transmitter, mit zwei Leitungen: TX (Sende-Pin) und RX (Empfangs-Pin). Die werden über Kreuz verbunden, also TX des einen Geräts an RX des anderen. Dazu gehört GND, die gemeinsame Masse als Bezugspunkt aller Spannungen. Der UART-Baustein zerlegt Bytes in eine Kette von High- und Low-Pegeln und setzt sie auf der anderen Seite wieder zusammen.

Der Irrtum entsteht, weil I2C wirklich mit zwei Leitungen für alle Geräte auskommt und SPI sogar eine Taktleitung nutzt. UART hat keinen gemeinsamen Takt, dafür aber zwei Richtungen.

Wichtigste Regel: beide Seiten müssen dieselbe Baudrate, also Bits pro Sekunde, verwenden – etwa 115200. Der Empfänger erkennt den Anfang eines Zeichens am Startbit und tastet die Pegel dann im Takt dieser Rate ab. Bei Serial.println() in der Arduino-Firmware muss der serielle Monitor auf denselben Wert eingestellt sein.

Woran man es erkennt: Im seriellen Monitor erscheint statt lesbarem Text wirrer Datenschrott mit seltsamen Zeichen. Dann Baudrate in der Firmware und im Monitor abgleichen.

UART heißt nicht „ein Draht für alles“, sondern zwei gekreuzte Leitungen plus Masse bei gleicher Baudrate.

📌 TX an RX · Baudrate 115200 · gemeinsame Masse

📚 IoT von Grund auf · Tag 3 von 30
#embedded #Mikrocontroller #iot
Lisa Schneider
3 Tage vor
Ein Druck, und der Zähler springt um drei. Dabei wurde die Taste genau einmal gedrückt.

Schuld ist nicht das Programm, sondern der Taster selbst. Der Vorgang heißt Prellen (englisch bouncing): Der mechanische Kontakt öffnet und schließt kurzzeitig mehrfach, bevor er endgültig anliegt.

Zuerst trifft beim Drücken eine federnde Kontaktfeder mit Schwung auf die Gegenfläche. Die Kontaktfedern im Taster sind federnd, dadurch schließt der Kontakt sicher. Der Schwung lässt die Flächen aber nicht sofort ruhig liegenbleiben.

Dann schwingen die Kontaktflächen für einige Millisekunden. In dieser Phase berühren sie sich, trennen sich kurz und berühren sich wieder. Elektrisch sieht das wie ein schneller Wechsel zwischen gedrückt und losgelassen aus.

Danach liest der Mikrocontroller seinen Eingang und sieht jedes dieser kurzen Kontakte. Er prüft den Pin so schnell, dass er jedes der kurzen Kontakte als eigenen Tastendruck erkennt. Ein Interrupt-gesteuerter Zähler ohne Entprellung zählt deshalb pro Druck mehrere Flanken.

Zuletzt fängt das Programm das Prellen ab. Die Sperrzeit ignoriert den Eingang nach einer erkannten Flanke, also einem Pegelwechsel, für wenige Millisekunden. Für die Zeitmessung eignet sich millis() (liefert die Millisekunden seit dem Start) besser als delay(), weil delay() die gesamte Hauptschleife anhält. Beim Nachfrage-Verfahren wird der Pegel erst gewertet, wenn er über mehrere Abtastungen stabil bleibt. In einer Interrupt-Service-Routine gehört nur eine kurze Aktion hinein, etwa ein Flag setzen.

Ein Tastendruck ist elektrisch erst fertig, wenn er still ist. Entprellen heißt nicht warten um jeden Preis, sondern gezielt die ersten Millisekunden ignorieren.

📌 Prellen · Sperrzeit · millis()

📚 IoT von Grund auf · Tag 3 von 30
#embedded #Mikrocontroller #Arduino
Lisa Schneider
3 Tage vor
Der Sensorwert zeigt plötzlich 4096 statt 4095. Wer dann nur Schleifen und Indizes prüft, übersieht den wahrscheinlichen Grund: einen Vergleich auf einen Wert, den der ADC nie liefert.

Der Rohwert des Analogeingangs erreicht nie 4096, sondern endet bei 4095. Ein Zahlenvergleich auf 4096 löst deshalb nie aus, weil er auf Off-by-one (einen um eins verschobenen Zahlenvergleich) beruht. Umgekehrt entspricht ein Wert wie 2048 fast, aber nicht ganz der halben Referenzspannung.

Der Analog-Digital-Wandler (ADC), also die Schaltung, die eine Spannung in eine Zahl umsetzt, liefert beim ESP32 12 Bit Auflösung. 12 Bit bedeuten 2 hoch 12, also 4096 mögliche Stufen. Da die Zählung bei 0 beginnt, ist der größte Rohwert 4095, nicht 4096. Die Auflösung teilt den Messbereich in diese Stufen, sagt aber nichts über die Genauigkeit: 4096 Stufen garantieren nicht, dass der Wert der wahren Spannung entspricht.

Bei einer Referenzspannung, also der Vergleichsspannung für die Messung, von 3,3 V ergibt sich der kleinste Schritt aus 3,3 V geteilt durch 4095, etwa 0,8 mV je Stufe. Zurückrechnen ist ein Dreisatz: Spannung gleich Rohwert geteilt durch 4095, multipliziert mit der Referenzspannung. Wichtig: Die Referenzspannung des ESP32 streut von Chip zu Chip; Espressif speichert deshalb einen Kalibrierwert im eFuse, den die Kalibrierfunktionen von ESP-IDF nutzen.

„So prüft man es:“ Einen Spannungsteiler (zwei Widerstände, die eine Spannung herabsetzen) oder ein als Referenz geeignetes Multimeter an den Pin legen und Rohwert sowie gerechnete Spannung vergleichen. Weicht der Wert stark ab, die Kalibrierfunktionen nutzen und mehrere Messungen mitteln.

12 Bit heißt nicht 4095 Stufen, sondern 4096 Stufen mit letztem Wert 4095. Auflösung ist nicht Genauigkeit: Sie zählt Stufen, nicht Messfehler.

📌 ADC-Auflösung · Dreisatz · Referenzspannung

📚 IoT von Grund auf · Tag 3 von 30
#esp32 #Arduino #sensorik
Lisa Schneider
4 Tage vor
3,3 Volt oder 5 Volt – viele glauben, das entscheidet der Chip. Dabei entscheidet allein die Richtung, in die das Signal fließt.

Viele Einsteiger denken, ein 3,3-V-Chip und ein 5-V-Chip passen nie zusammen. Sie suchen dann vorsorglich für jede Verbindung einen Pegelwandler. Das klingt plausibel, weil die Spannungen tatsächlich unterschiedlich sind.

Tatsächlich gibt es zwei Richtungen mit zwei verschiedenen Antworten. Ein Logikpegel ist die Spannung, mit der ein Pin High (logisch eins) oder Low (logisch null) anzeigt. Umgekehrt ist es gefährlich: Ein 5-V-Ausgang auf einen 3,3-V-Eingang übersteigt dessen Grenze.

Der Irrtum entsteht, weil Chips nach Spannung kategorisiert werden, Signale aber nach Richtung. Genaues Hinsehen ins Datenblatt ersetzt jede Faustregel.

Ein Beispiel: Der ESP32 arbeitet mit 3,3 V, seine Eingänge vertragen laut Datenblatt maximal 3,6 V – er ist nicht 5-V-tolerant. Der ATmega328P im Arduino Uno arbeitet mit 5 V und erkennt ein High ab etwa 3 V. Ein ESP32-Pin darf also einen Uno-Eingang treiben. Vom Uno-Ausgang zum ESP32 gehört ein Spannungsteiler (zwei Widerstände, nur für langsame Signale) oder ein aktiver Pegelwandler dazwischen. Für schnelle und bidirektionale Leitungen wie I2C gehört ein aktiver Pegelwandler dazwischen, klassisch je Leitung ein BSS138 mit Pull-ups auf beiden Seiten.

Woran man es erkennt: Im Datenblatt des Empfängers stehen die Grenzen für High und für die maximale Eingangsspannung. Übersteigt die Ausgangsspannung des Senders die Eingangsgrenze, gehört ein Wandler dazwischen.

Pegelwandlung heißt nicht, Chips mit gleicher Spannung zu verbinden, sondern die Signalgrenzen beider Datenblätter in der richtigen Richtung zu prüfen. Und vorher immer die gemeinsame Masse verbinden.

📌 Logikpegel · Signalrichtung · Datenblatt-Grenzen

📚 IoT von Grund auf · Tag 2 von 30
#esp32 #Arduino #Mikrocontroller
Lisa Schneider
4 Tage vor
Ein Taster an Pin 4 liest mal 0, mal 1, ohne dass ihn jemand berührt. Schuld ist der offene Eingang, der keinen festen Pegel kennt.

GPIO ist die allgemeine Bezeichnung für einen anpassbaren Pin am Mikrocontroller, also dem kleinen Computer-Chip auf dem Board. GPIO-Pins können als Ausgang eine LED schalten oder als Eingang einen Taster abfragen. GPIO-Eingänge sind hochohmig: Sie lesen den Pegel nur ab, steuern ihn aber nicht selbst. Ohne feste Verbindung bleibt die Spannung am Pin zufällig, etwa durch Störungen aus der Umgebung.

Zuerst fehlt dem offenen Pin jede Referenz. High und Low sind keine festen Spannungspunkte, sondern Bereiche: Der Eingang wertet alles oberhalb einer Schwelle als High, alles darunter als Low. Ein unbeschalteter, sogenannter floating Eingang pendelt willkürlich dazwischen.

Dann entscheidet der gemeinsame Bezugspunkt. Die Masse (GND) ist der Punkt, gegen den alle Spannungen gemessen werden. Erst über die gemeinsame Masse weiß der Eingang, was High und Low überhaupt bedeuten.

Danach zieht ein Widerstand den Eingang auf den Ruhepegel. Ein Pull-up liegt zwischen Versorgungsspannung und Eingang und hält ihn auf High; ein Pull-down liegt zwischen Eingang und Masse und hält ihn auf Low. Spannungen nahe der Schwelle wären unsauber, weil sie mal so, mal so gelesen werden.

Zuletzt kommt der Taster ins Spiel: pinMode(4, INPUT_PULLUP) aktiviert den internen Pull-up, digitalRead(4) liest den Pin. Der Taster drückt den Eingang gegen Masse; gedrückt bedeutet also LOW, ungedrückt HIGH – invertiert zur Intuition. Der Widerstandswert ist ein Kompromiss: Kleinere Widerstände geben steife Pegel, größere sparen Strom.

Ein offener Eingang lügt nicht böswillig, er weiß es einfach nicht besser. Wer den Ruhepegel definiert, bekommt eine eindeutige Antwort.

📌 Floating-Eingang · Pull-up · Ruhepegel

📚 IoT von Grund auf · Tag 2 von 30
#Mikrocontroller #Arduino #iot #embedded
Lisa Schneider
4 Tage vor
Zwei Schaltungen, zwei Netzteile, ein Kabel – und trotzdem kommt keine Botschaft an. Schuld ist meist nicht das Signal, sondern die fehlende Masse.

Die Verwechslung ist verständlich: Signalleitungen sind sichtbar und auffällig, die Masse wirkt wie selbstverständlich. Einsteiger nehmen an, GND sei bei allen Geräten von selbst derselbe Punkt, weil alles an Strom hängt.

Ein Signal ist die Information selbst. Es kennt digital nur zwei Zustände: Low und High. Welche Spannung als High gilt, hängt von der Logikfamilie ab, also der Chip-Gattung mit ihren Pegelvorgaben. Der ESP32 arbeitet mit 3,3 V, sein Eingang verträgt laut Datenblatt höchstens 3,6 V. Ein Arduino Uno mit ATmega328P arbeitet mit 5 V und erkennt High ab etwa 3 V.

Die Masse (GND) ist der Bezugspunkt aller Spannungen. Eine Spannung ist nie eine Eigenschaft eines einzelnen Punktes, sondern immer eine Differenz zwischen zwei Punkten. Gemessen wird sie gegen GND. Fehlt eine gemeinsame Masse, bezieht jedes Gerät High und Low auf seinen eigenen Bezugspunkt.

Das Signal ist die Botschaft, die Masse ist die gemeinsame Sprache, in der sie gelesen wird. Ohne gemeinsamen Bezugspunkt ist selbst eine korrekte Signalleitung bedeutungslos – zufällige Messwerte oder gar keine Kommunikation folgen.

Faustregel: Beim Aufbau einer Schaltung zuerst die Masse aller Beteiligten verbinden, erst danach die Signalleitungen anschließen. Bei getrennten Netzteilen verbindet man ebenfalls deren Massepunkte.

Eine Spannung ist keine Zahl auf einem Pin, sondern immer eine Differenz. GND heißt nicht „irgendwo Masse“, sondern „elektrisch verbunden“.

📌 GND · Bezugspunkt · Spannungsdifferenz

📚 IoT von Grund auf · Tag 2 von 30
#esp32 #Mikrocontroller #embedded
Lisa Schneider
4 Tage vor
Die rote LED leuchtet hell, dann dunkel, und der ESP32 startet neu. Was wie ein Softwarefehler aussieht, ist oft reine Elektrik.

Zu sehen ist: Der Mikrocontroller hängt sporadisch oder der GPIO-Pin gibt danach dauerhaft nichts mehr aus. GPIO-Pins (General Purpose Input/Output) sind Anschlüsse, die per Software als Eingang oder Ausgang dienen. Wer die LED direkt an so einen Pin anschließt, überfordert ihn.

Dahinter steckt das ohmsche Gesetz: Spannung U in Volt ist Widerstand R in Ohm mal Strom I in Ampere (U = R · I). Spannung ist die treibende Kraft, die elektrische Ladung bewegt; der Strom ist die Ladungsmenge pro Sekunde; der Widerstand setzt dem Strom seinen Gegenwert entgegen. Eine LED (Leuchtdiode) ist kein solcher Widerstand: Sie braucht eine bestimmte Flussspannung, um zu leuchten, und lässt danach den Strom fast unbegrenzt steigen. digitalWrite(PIN, HIGH) legt beim ESP32 3,3 V an den Ausgang, bezogen auf die Masse (GND), den gemeinsamen Bezugspunkt. Ohne Vorwiderstand fließt dann so viel Strom, dass der Pin beschädigt wird.

Die Rechnung: Von den 3,3 V Pinspannung fallen etwa 2 V Flussspannung an der roten LED ab; nur die verbleibende Differenz liegt am Vorwiderstand. Gewünschter Strom 10 mA, also I = U / R umgestellt nach R = U / I: rund 130 Ohm. In der Praxis wählt man den nächstliegenden verfügbaren Widerstandswert.

So prüft man es: Zuerst LED, Vorwiderstand und Pin gegen GND nach dem Schaltplan verkabeln, den Pin per digitalWrite(PIN, HIGH) auf HIGH setzen. Danach den fließenden Strom nachmessen oder nachrechnen.

Der Widerstandswert ergibt sich aus der Spannungsdifferenz, nicht aus den vollen 3,3 V. Die LED zeigt den Weg, der Vorwiderstand setzt das Limit.

📌 Spannung · Vorwiderstand · U=R·I

📚 IoT von Grund auf · Tag 2 von 30
#esp32 #Arduino #Mikrocontroller #iot
Lisa Schneider
4 Tage vor
Die meisten denken, ein digitaler Pin misst Spannungen wie ein Messgerät. Dabei wertet er nur zwei Bereiche aus und kennt nichts dazwischen.

Ein digitaler Eingang muss sich entscheiden: High oder Low. Sie entscheidet darüber, ob ein Tastendruck erkannt wird oder verloren geht.

🔋 High und Low sind Spannungsbereiche, keine festen Punkte. Der Eingang eines Mikrocontrollers hält alles oberhalb einer Schwelle für High und alles darunter für Low. Beim ESP32 mit seiner 3,3-V-Logik gibt ein High am Ausgang etwa 3,3 V gegen Masse aus, ein Low annähernd 0 V. Ältere 5-V-Systeme wie klassische Arduino-Boards verwenden dafür 5 V.

📡 Alle Spannungen werden gegen die Masse (GND) gemessen, den gemeinsamen Bezugspunkt der Schaltung. Erst über eine gemeinsame Masse weiß der Eingang, gegen welchen Punkt High und Low gemessen werden. Deshalb gehört GND immer mit angeschlossen. digitalWrite(PIN, HIGH) schaltet auf die Versorgungsspannung der Logik, digitalWrite(PIN, LOW) auf Masse.

🔧 Spannungen dicht an der Umschaltschwelle bleiben unsauber und liefern mal High, mal Low. Ein offener, unbeschalteter Eingang (floating) springt deshalb willkürlich; ein Pull-up-Widerstand hält ihn fest. Bewährt hat sich: pinMode(4, INPUT_PULLUP) und digitalRead(4) für einen Taster, der den Pin gegen Masse zieht. Achtung: 5-V-Signale können einen 3,3-V-Eingang zerstören.

Digital heißt nicht, dass es nur genau 3,3 V und 0 V gibt, sondern dass der Eingang zwei Spannungsbereiche als zwei Werte auswertet. Alles dazwischen ist kein dritter Zustand, sondern ein Fall, der sauber vermieden wird.

📌 High und Low · Spannungsbereiche · Masse als Bezugspunkt

📚 IoT von Grund auf · Tag 2 von 30
#Mikrocontroller #esp32 #iot
Lisa Schneider
4 Tage vor
Ein Arduino-Programm wirkt auf den ersten Blick wie eine Datei voller Regeln. Viele Einsteiger schreiben deshalb alles in eine Funktion – und wundern sich über stockende Abläufe.

Ein Programm sei eine Anweisung nach der anderen, also gehöre alles einfach untereinander in den Code. Das klingt plausibel, weil man beim Skripten am Rechner genau so arbeitet.

Tatsächlich besteht jedes Arduino-Programm aus zwei Bausteinen: setup() läuft genau einmal nach dem Start, loop() danach endlos. Der Mikrocontroller startet die Firmware, also das fest im Flash gespeicherte Programm, direkt ohne Betriebssystem – deshalb ist der Startvorgang kurz und vorhersagbar. In setup() steht alles, was einmalig hergestellt wird: pinMode() legt fest, ob ein GPIO-Pin (ein per Software einstellbarer Ein- oder Ausgang) Eingang oder Ausgang ist. In loop() steht die Arbeit, die sich wiederholt, etwa Sensoren lesen und Werte senden.

Der Irrtum entsteht, weil Einsteiger pinMode() oder Serial.begin() – das Starten der Seriellen Schnittstelle – in loop() schreiben. Das funktioniert oft, ist aber unnötige Arbeit bei jedem Durchlauf und stört Abläufe, die nur zum Start gehören.

Ein Beispiel ist ein Temperatur-Sensorknoten: In setup() wird der Sensor initialisiert und das Funkmodul verbunden. In loop() wird die Temperatur gelesen und gesendet; anschließend schläft der Knoten bis zur nächsten Messung.

Woran man es erkennt: Fragen Sie, ob der Schritt einen einmaligen Zustand festlegt oder wiederholt geschehen soll. Verbindung aufbauen gehört in setup(), Sensor lesen in loop().

setup() heißt nicht „Hauptprogramm mit Extras“, sondern einmalige Vorbereitung. loop() heißt nicht „einzige Funktion“, sondern endlos wiederholte Arbeit.

📌 setup() · loop() · Endlosschleife

📚 IoT von Grund auf · Tag 1 von 30
#Arduino #Mikrocontroller #firmware #iot
Lisa Schneider
5 Tage vor
Ein Rechner bootet erst ein Betriebssystem, bevor irgendetwas läuft. Ein Mikrocontroller startet direkt sein einziges Programm – und das ist ein Vorteil.

Das ist die Firmware, also das eine Programm, das fest im Flash-Speicher des Chips abgelegt ist. Sie steckt in jedem IoT-Sensor, jeder smarten Steckdose und jedem Werkzeug mit Knopf und Elektronik.

Zuerst kommt der Strom. Der Mikrocontroller, ein Chip mit Prozessor, Arbeitsspeicher, Flash und Ein- und Ausgängen, lädt die Firmware direkt aus dem Flash. Flash ist ein nichtflüchtiger Speicher, der seinen Inhalt auch ohne Strom behält. Ein Betriebssystem wird nicht zuerst geladen, deshalb bleibt der Startvorgang kurz und vorhersagbar.

Dann läuft setup(). In einem Arduino-Programm ruft die Firmware einmal am Anfang die Funktion setup() auf, die die angeschlossene Hardware initialisiert. Danach folgt loop(), eine Endlosschleife, die immer wieder durchlaufen wird.

Danach verrichtet loop() die eigentliche Arbeit. Sie liest Sensorsignale an den Eingängen, verrechnet sie und schaltet Ausgänge – ganz ohne Benutzer. Ein Temperatur-Sensorknoten misst die Temperatur, sendet sie über ein Funkmodul und schläft anschließend bis zur nächsten Messung. Das schont den Akku.

Zuletzt macht Schlankheit das Gerät zuverlässig. Ein Betriebssystem wie Windows oder Linux verwaltet viele Programme, Dateien und Geräte; ein Mikrocontroller braucht das nicht, weil genau eine Aufgabe festgelegt ist. Weniger Software heißt weniger Fehlerquellen – das Verhalten bleibt bei jedem Durchlauf gleich.

Firmware heißt also nicht „ein Programm von vielen“, sondern „das einzige Programm“ – direkt, schlank und nach jedem Einschalten sofort da.

📌 Firmware · Flash · Endlosschleife

📚 IoT von Grund auf · Tag 1 von 30
#Mikrocontroller #firmware #iot #embedded

Nichts gefunden!

Entschuldigung, aber für Ihre Suchanfrage {{search_query}} konnten wir in unserer Datenbank nichts finden. Bitte versuchen Sie es erneut, indem Sie andere Suchbegriffe eingeben.