ESP32 programmieren - DC-Motor mit PWM und Drehpotentiometer steuern
In einem frĂŒheren Video mit dem Titel ESP32 programmieren â steuern von LEDs mit einem Drehpotentiometer habe ich bereits gezeigt, wie sich ein ESP32 ganz einfach nutzen lĂ€sst, um LEDs stufenlos per Drehregler zu steuern. Das Video stammt zwar bereits aus dem Jahr 2023, die grundlegenden Konzepte - ADC, PWM und das Zusammenspiel von Hardware und Software - sind aber nach wie vor aktuell.
https://youtu.be/_YnbPYVUwUQ
In den Kommentaren zu diesem Video kam eine spannende Frage auf: Kann man mit dem ESP32 auf Àhnliche Weise auch einen DC-Motor steuern?
Genau das schauen wir uns in diesem Beitrag an.
Ich zeige dir Schritt fĂŒr Schritt, wie du einen DC-Motor am ESP32 D1 R32 anschlieĂt und programmierst. Statt einer LED regeln wir diesmal die Drehzahl eines Motors per PWM, ebenfalls ĂŒber ein Drehpotentiometer. Das Grundprinzip bleibt also vertraut, der praktische Nutzen steigt jedoch deutlich.
FĂŒr die Ansteuerung des Motors setze ich auf das IRF520-Modul, das ich bereits in einem frĂŒheren Projekt verwendet habe - unter anderem in meinem Beitrag zur LĂŒftersteuerung: https://draeger-it.blog/lueftersteuerung-mit-irf520-ir-abstandssensor/
Der groĂe Vorteil dieses Moduls liegt in der einfachen Handhabung: Der ESP32 ĂŒbernimmt ausschlieĂlich die Steuerlogik, wĂ€hrend das IRF520-Modul die nötige Leistung fĂŒr den Motor schaltet. Dadurch bleibt die Schaltung ĂŒbersichtlich, sicher und auch fĂŒr Einsteiger gut geeignet.
Am Ende dieses Beitrags weiĂt du:
- warum ein DC-Motor nicht direkt an den ESP32 angeschlossen werden sollte, - wie der Anschluss mit dem IRF520-Modul erfolgt, - und wie sich die Drehzahl per PWM sauber und reproduzierbar regeln lÀsst.
PWM - so steuert der ESP32 einen DC-Motor
Um einen DC-Motor mit dem ESP32 zu steuern, benötigen wir kein spezielles Motor-Protokoll. Die Grundlage ist ein PWM-Signal (Pulsweitenmodulation), das der ESP32 direkt erzeugen kann.
Angeschlossenes mini Osziloskop vom Typ DOS-138
Der ESP32 selbst kann an seinen AusgĂ€ngen nur zwei ZustĂ€nde ausgeben: Ein oder Aus. FĂŒr einen Motor ist das jedoch völlig ausreichend - denn er reagiert nicht auf einzelne Schaltimpulse, sondern auf die zugefĂŒhrte Energie ĂŒber die Zeit.
Genau hier kommt PWM ins Spiel: Der ESP32 schaltet den Ausgang sehr schnell ein und aus. Entscheidend ist dabei nicht, wie hoch die Spannung ist, sondern wie lange der Ausgang innerhalb eines festen Zeitfensters eingeschaltet ist.
- Kurze Einschaltzeit â wenig Energie â Motor dreht langsam - Lange Einschaltzeit â mehr Energie â Motor dreht schneller
Der Motor wirkt dabei wie ein mechanischer âFilterâ: Durch seine MassentrĂ€gheit werden die einzelnen Impulse nicht als Stop-and-Go wahrgenommen, sondern als gleichmĂ€Ăige Drehbewegung mit unterschiedlicher Geschwindigkeit.
Wichtig ist: đ Der ESP32 steuert den Motor nicht direkt.
Das PWM-Signal wird an das IRF520-MOSFET-Modul weitergegeben. Der ESP32 liefert dabei ausschlieĂlich das Steuersignal, wĂ€hrend das IRF520-Modul den eigentlichen Motorstrom aus der externen Stromversorgung schaltet.
Das IRF520-Modul ĂŒbernimmt damit drei zentrale Aufgaben:
- Es macht die Motorsteuerung elektrisch sicher und zuverlĂ€ssig - Es schaltet den Motorstrom passend zum PWM-Signal ein und aus - Es entlastet und schĂŒtzt den ESP32 vor hohen Strömen
IRF520 MOS Driver
Benötigte Materialien
FĂŒr den Aufbau brauchst du nur wenige, gut erhĂ€ltliche Komponenten:
- ESP32* (z. B. ESP32 D1 R32*) - Breadboardkabel* - Kleiner DC-Motor* - Externe Stromversorgung Am besten ein regelbares Netzteil* (z. B. Labornetzteil*) - IRF520-Modul* zur Motoransteuerung - Ein paar LEDs* inkl. VorwiderstÀnde* zur einfachen Visualisierung der eingestellten Geschwindigkeit
Bauteile - DC-Motor mit Drehpoti am ESP32 steuern
Mehr ist fĂŒr dieses Projekt nicht nötig. Im nĂ€chsten Schritt verbinden wir die Komponenten und bauen die Schaltung Schritt fĂŒr Schritt auf.
Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du ĂŒber diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beitrĂ€gt, diesen Blog zu unterstĂŒtzen. Der Preis fĂŒr dich bleibt dabei unverĂ€ndert. Vielen Dank fĂŒr deine UnterstĂŒtzung!
In der Schaltung verwende ich einen groĂen Drehpotentiometer mit 50 kOhm, diesen gibt es noch in weiteren ausfĂŒhrungen welche kleiner sind und wie ich finde dadurch weniger gut zu bedienen, aber die Schaltung funktioniert mit diesen genauso gut.
verschiedene Drehpotentiometer
Werkzeuge
ZusÀtzlich benötigst du noch einpaar Werkzeuge:
- einen kleinen Seitenschneider, - eine Biegehilfe fĂŒr die WiderstĂ€nde, - einen kleinen Kreuzschraubendreher (PH0)
Schaltung: ESP32 mit Drehpotentiometer, IRF520-MOSFET-Modul und DC-Motor
Die Schaltung ist bewusst einfach gehalten. Der ESP32 erzeugt das PWM-Steuersignal, das IRF520-MOSFET-Modul schaltet damit den Motorstrom aus einer externen Stromversorgung. Der Motor selbst ist zu keinem Zeitpunkt direkt mit dem ESP32 verbunden.
Schaltung - ESP32 mit IRF520 und DC-Motor ESP32 PinBauteilAnschluss / FunktionGPIO 4IRF520-MOSFET-ModulSIG (PWM-Steuersignal fĂŒr den Motor)GNDIRF520-MOSFET-ModulGND (gemeinsame Masse)GNDExterne StromversorgungMinus (-)V+IRF520-MOSFET-ModulMotor +V-IRF520-MOSFET-ModulMotor -3,3 VDrehpotentiometerAuĂenpinGNDDrehpotentiometerAuĂenpinGPIO 2DrehpotentiometerSchleifer (mittlerer Pin, ADC)GPIO 18LED 1AnodeGPIO 23LED 2AnodeGPIO 12LED 3AnodeGPIO 17LED 4AnodeGPIO 26LED 5AnodeGNDLEDsKathode (ĂŒber Vorwiderstand)
Um den DC-Motor sinnvoll auf dem Schreibtisch zu platzieren, habe ich mir auf MakerWorld einen Linearantrieb heruntergeladen und 3D-gedruckt. Das sorgt nicht nur fĂŒr einen stabilen Aufbau, sondern sieht nebenbei auch deutlich besser aus als ein lose herumliegender Motor.
ESP32 D1 R32 mit DC-Motor im Linearantrieb
Wichtiger Sicherheits- und Praxis-Hinweis zur Versorgung
Der ESP32 stellt an seinen Pins 3,3 V (teilweise auch 5 V) zur VerfĂŒgung. Rein theoretisch könnte man auf die Idee kommen, einen kleinen DC-Motor direkt an einen GPIO-Pin anzuschlieĂen - das sollte man jedoch niemals tun.
Der Grund dafĂŒr ist der sogenannte Anlaufstrom eines Motors. Beim Start zieht ein DC-Motor fĂŒr einen sehr kurzen Moment deutlich mehr Strom als im normalen Betrieb. Dieser Strom liegt weit ĂŒber dem, was ein GPIO-Pin des ESP32 liefern kann. Im schlimmsten Fall wird dadurch der Pin oder sogar der gesamte Mikrocontroller dauerhaft beschĂ€digt.
Selbst wenn der ESP32 diesen Moment ĂŒberstehen sollte, entsteht das nĂ€chste Problem, sobald der Motor mechanisch belastet wird - zum Beispiel durch Reibung, eine Achse oder einen Linearantrieb. Auch hier steigt der Strombedarf sprunghaft an und kann erneut zu SchĂ€den oder instabilem Verhalten fĂŒhren.
Aus diesem Grund wird der Motor in diesem Projekt niemals direkt vom ESP32 versorgt. Der ESP32 erzeugt ausschlieĂlich das PWM-Steuersignal, wĂ€hrend die eigentliche Motorleistung ĂŒber eine externe Stromversorgung und das IRF520-MOSFET-Modul geschaltet wird. So bleibt der ESP32 geschĂŒtzt und die Schaltung arbeitet zuverlĂ€ssig und sicher.
Programmieren in der Schaltung in der Arduino IDE
Das Gute an diesem Projekt ist, dass der Code ohne zusÀtzliche Bibliotheken auskommt. Das IRF520-Modul wird lediglich mit einem PWM-Signal angesteuert, welches sich mit den Bordmitteln des ESP32 sehr einfach erzeugen lÀsst.
Programm - steuern eines DC-Motors am ESP32 mit DrehpotentiometerHerunterladen Schritt 1 - definieren der Pins
Im ersten Schritt legen wir die Konstanten fĂŒr unsere Pins fest. Dabei verwende ich das SchlĂŒsselwort #define. Dieses sorgt dafĂŒr, dass der Compiler vor dem eigentlichen Kompilieren jedes Vorkommen des definierten Namens durch den zugewiesenen Wert ersetzt.
Das hat zwei Vorteile:
- Der Code wird ĂŒbersichtlicher und besser lesbar, da wir mit sprechenden Namen arbeiten. - Ăndert sich spĂ€ter ein Pin, muss dieser nur an einer Stelle angepasst werden.
Statt im Code mit festen Zahlen zu arbeiten, greifen wir so ĂŒberall auf klar benannte Bezeichner wie motor oder led1 zurĂŒck - das macht den Sketch gerade fĂŒr Einsteiger deutlich nachvollziehbarer.
// ============================== // LED-Pins (Geschwindigkeitsanzeige) // ============================== #define led1 18 #define led2 23 #define led3 12 #define led4 17 #define led5 26 // ============================== // Drehpotentiometer (ADC-Eingang) // ============================== #define drehPoti 2 // ============================== // Motor-Pin (PWM-Ausgang â IRF520 SIG) // ============================== #define motor 4
Alternativ kannst du die Pins auch so definieren, wie es in vielen anderen Tutorials im Internet ĂŒblich ist - zum Beispiel ĂŒber ganz normale Variablen anstelle von #define.
const int LED1 = 18; Schritt 2 - anlegen der Konstanten und Liste mit Pindefinitionen
Wenn wir mehrere LEDs gemeinsam behandeln wollen - zum Beispiel um sie alle auf einmal ein- oder auszuschalten - bietet sich eine for-Schleife an. Damit das funktioniert, mĂŒssen die verwendeten Pins jedoch in einer Liste (Array) abgelegt werden.
Statt jede LED einzeln anzusprechen, können wir so alle LEDs nacheinander durchlaufen und mit derselben Anweisung steuern. Das spart Code, vermeidet Wiederholungen und macht den Sketch deutlich ĂŒbersichtlicher.
Gerade bei mehreren LEDs ist diese Vorgehensweise sehr praktisch und lÀsst sich spÀter leicht erweitern, falls weitere LEDs hinzukommen.
// Anzahl der verwendeten LEDs const int MAX_LEDS = 5; // Array fĂŒr die LEDs, damit sie bequem per Schleife angesteuert werden können int leds = { led1, led2, led3, led4, led5 }; // Speichert den letzten Poti-Wert, um unnötige Updates zu vermeiden int lastValue = -1; Schritt 3 - Funktion setup
In der Funktion setup(), die einmalig beim Start des Mikrocontrollers oder nach dem DrĂŒcken des RESET-Tasters ausgefĂŒhrt wird, legen wir fest, wie die einzelnen Pins verwendet werden. In unserem Fall definieren wir die LED-Pins als AusgĂ€nge.
Hier kommt auch die zuvor erwĂ€hnte for-Schleife zum Einsatz. Mit ihr durchlaufen wir alle LED-Pins aus unserem Array und setzen sie als Ausgang. AnschlieĂend werden die LEDs einmal nacheinander eingeschaltet. Dieser kurze Test zeigt sofort, ob alle LEDs korrekt angeschlossen sind und funktioniert gleichzeitig als einfache FunktionsprĂŒfung beim Start des Programms.
void setup() { // Alle LEDs als Ausgang konfigurieren for (int index = 0; index < MAX_LEDS; index++) { pinMode(leds, OUTPUT); } // LED-Test beim Start: // Die LEDs werden nacheinander eingeschaltet, // um zu prĂŒfen, ob alle korrekt angeschlossen sind. for (int index = 0; index < MAX_LEDS; index++) { digitalWrite(leds, HIGH); delay(250); } // Kurze Pause, damit der Test sichtbar bleibt delay(2000); } Schritt 4 - Hilfsfunktionen
FĂŒr das Ausschalten aller LEDs sowie fĂŒr das Visualisieren und Setzen der Geschwindigkeit habe ich jeweils separate Funktionen angelegt. Dadurch bleibt der Code ĂŒbersichtlich und man sieht immer nur den Teil, der gerade relevant ist.
Diese Aufteilung erleichtert nicht nur das VerstĂ€ndnis, sondern macht den Sketch auch leicht erweiterbar. Möchte man spĂ€ter zum Beispiel die LED-Anzeige Ă€ndern oder die Motorsteuerung anpassen, kann das gezielt an einer Stelle erfolgen, ohne den restlichen Code anfassen zu mĂŒssen.
Schritt 4.1 - deaktivieren der LEDs
Die LEDs werden in einer Schleife deaktiviert.
// ============================== // Alle LEDs ausschalten // ============================== void resetLEDs() { for (int ledIndex = 0; ledIndex < MAX_LEDS; ledIndex++) { digitalWrite(leds, LOW); } } Schritt 4.2 - aktivieren der LEDs
Wie die LEDs deaktiviert werden kann man diese eben auch aktivieren, hier muss lediglich der Pin auf HIGH statt auf LOW gesetzt werden.
// ============================== // Geschwindigkeit ĂŒber LEDs anzeigen // ============================== // Der ADC-Wert (0â4095) wird auf einen LED-Index (0â4) umgerechnet. // Es leuchtet genau eine LED als aktuelle Geschwindigkeitsstufe. void displaySpeed(int value) { int ledIndex = map(value, 0, 4095, 0, MAX_LEDS - 1); digitalWrite(leds, HIGH); } Schritt 4.3 - setzen der Motor Geschwindigkeit
Die Funktion zum setzen der Motor Geschwindigkeit erhÀlt den ausgelesenen Wert des Drehpotentiometers und mappt diesen (0..4095) auf ein PWM Wert (0..255).
// ============================== // Motorgeschwindigkeit setzen // ============================== // Der ADC-Wert wird auf einen PWM-Wert (0â255) gemappt. // Dieser PWM-Wert steuert das IRF520-MOSFET-Modul. void setMotorSpeed(int value) { int speed = map(value, 0, 4095, 0, 255); analogWrite(motor, speed); } Schritt 5 - Funktion loop
In der Funktion loop wird zunÀchst der Wert vom Drehpotentiometer ausgelesen und wenn dieser sich vom letzten Wert unterscheidet dann werden alle LEDs deaktiviert eine passende LED aktiviert sowie die Motorgeschwindigkeit gesetzt.
void loop() { // Aktuellen Wert des Drehpotentiometers einlesen int resistorValue = analogRead(drehPoti); // Nur reagieren, wenn sich der Wert geĂ€ndert hat if (lastValue != resistorValue) { resetLEDs(); // LEDs zurĂŒcksetzen displaySpeed(resistorValue); // neue LED-Stufe anzeigen setMotorSpeed(resistorValue); // Motor-PWM setzen lastValue = resistorValue; // Wert merken } // Kleine Pause zur Beruhigung der Ausgabe delay(50); }
Am Ende wird noch eine kleine Pause eingelegt diese wird benötigt um den Mikrocontroller etwas zu entlasten.
Kompletter Quellcode /* Titel: ESP32 DC-Motor steuern: PWM + Drehpotentiometer (mit LED-Speedanzeige) Beschreibung: In diesem Sketch wird gezeigt, wie sich ein DC-Motor mit einem ESP32 per PWM-Signal steuern lĂ€sst. Die Drehzahl wird ĂŒber ein Drehpotentiometer vorgegeben und zusĂ€tzlich ĂŒber 5 LEDs visualisiert. Der Motor wird nicht direkt vom ESP32 angesteuert, sondern ĂŒber ein externes MOSFET-Modul (z. B. IRF520). Der ESP32 erzeugt lediglich das PWM-Steuersignal. AusfĂŒhrliche Anleitung inkl. Schaltung: https://draeger-it.blog/esp32-programmieren-dc-motor-mit-pwm-und-drehpotentiometer-steuern/ Autor: Stefan Draeger */ // ============================== // LED-Pins (Geschwindigkeitsanzeige) // ============================== #define led1 18 #define led2 23 #define led3 12 #define led4 17 #define led5 26 // ============================== // Drehpotentiometer (ADC-Eingang) // ============================== #define drehPoti 2 // ============================== // Motor-Pin (PWM-Ausgang â IRF520 SIG) // ============================== #define motor 4 // Anzahl der verwendeten LEDs const int MAX_LEDS = 5; // Array fĂŒr die LEDs, damit sie bequem per Schleife angesteuert werden können int leds = { led1, led2, led3, led4, led5 }; // Speichert den letzten Poti-Wert, um unnötige Updates zu vermeiden int lastValue = -1; void setup() { // Alle LEDs als Ausgang konfigurieren for (int index = 0; index < MAX_LEDS; index++) { pinMode(leds, OUTPUT); } // LED-Test beim Start: // Die LEDs werden nacheinander eingeschaltet, // um zu prĂŒfen, ob alle korrekt angeschlossen sind. for (int index = 0; index < MAX_LEDS; index++) { digitalWrite(leds, HIGH); delay(250); } // Kurze Pause, damit der Test sichtbar bleibt delay(2000); } // ============================== // Alle LEDs ausschalten // ============================== void resetLEDs() { for (int ledIndex = 0; ledIndex < MAX_LEDS; ledIndex++) { digitalWrite(leds, LOW); } } // ============================== // Geschwindigkeit ĂŒber LEDs anzeigen // ============================== // Der ADC-Wert (0â4095) wird auf einen LED-Index (0â4) umgerechnet. // Es leuchtet genau eine LED als aktuelle Geschwindigkeitsstufe.












