Arduino Lektion 56: 4 Phasen Schrittmotor steuern
In diesem Tutorial möchte ich gerne den 5V , 4 Phasen Schrittmotor mit Treiberplatine ULN2003 vorstellen.

Inhaltsverzeichnis
Bezug
Den 5 V, 4 Phasen Schrittmotor vom Typ „28BYJ-48 ULN2003“ kann man über eBay.de und amazon.de günstig erwerben. Wobei man darauf achten sollte das es das „komplett Set“ ist, denn es gibt den Motor und die Platine einzeln jedoch ist das „komplett Set“ günstiger zu erwerben.
Technische Daten des 4 Phasen Schrittmotor
- Betriebsspannung des Schrittmotors 5V
- Betriebsspannung der Platine 5V / 12V (einstellbar über einen Jumper)
- Abmaße
- Durchmesser des Motors 28mm
- Platinengröße 40,5mm x 21,3mm
Der Schrittmotor hat eine Übersetzung mit einem Zahnradgetriebe von 1: 64 d.h. für eine Umdrehung von 360° benötigt dieser Schrittmotor
360° : 64 Schritte = 5,625° pro Schritt.
Bei einer Halbschritt Übersetzung bedeutet das, dass wir 64 * 64 Schritt für eine volle Umdrehung benötigen.
64 * 64 = 4096 Schritte pro voller Umdrehung
Diese Berechnung erfolgte aus den Angaben aus dem Datenblatt des Schrittmotors 28BYJ-48.
Aufbau
Für den Aufbau der Schaltung verwende ich einen Wemos D1 mini, dieser verfügt über ein Wifi Modul welches wir später in einem Beispiel verwenden wollen.

Der Schrittmotor wird mit einer Treiberplatine geliefert (Bezeichnung UNL2003) an diese kann man eine 5V oder 12V Versorgungsspannung anlegen. Die 5V liefert der Microcontroller, jedoch sollte man hier aufpassen das die Last des Motors nicht zu hoch wird denn mit der Last steigt die Stromaufnahme und der Microcontroller ist hier leider begrenzt.
UNL2003 | Wemos D1 mini |
---|---|
IN1 | D5 |
IN2 | D6 |
IN3 | D8 |
IN4 | D7 |
– | GND |
+ | 5V |
Schaltung

Ermitteln der Kraft des Schrittmotors
Der Schrittmotor hat je nach Geschwindigkeit eine stärkere bzw. geringere Kraft um ein Objekt wie zbsp. eine Welle zu bewegen. Ich möchte nun einmal einen kleinen Versuch starten eine 0,5l Wasserflasche aus einer Höhe von ca. 75cm anzuheben. Dabei werde ich die Flasche immer mehr füllen und auch die Geschwindigkeit erhöhen.

Es konnte ermittelt werden das, der Schrittmotor eine Maximale Kraft von 300g (3Nm) ab der Geschwindigkeitsstufe 2 aufbringen kann. Die Stufe 1 ist die Schnellste kann jedoch weniger Kraft aufbringen.

Quellcode
Für die nachfolgenden Beispiele wird die Bibliothek „Arduino-and-ULN2003-Stepper-Motor-Driver“ von rydepier benötigt. Diese Bibliothek kann man sich aus dem GitHub Repository herunterladen.
Wie man eine Bibliothek in der Arduino IDE installiert habe ich im Tutorial Arduino IDE, Einbinden einer Bibliothek ausführlich erläutert.
Einfaches Beispiel
Der Bibliothek „StepperMotor“ liegt bereits ein Beispiel bei welches nach einer kleinen Konfiguration sofort lauffähig ist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <StepperMotor.h> //Einbinden der Bibliothek StepperMotor.h StepperMotor motor(D5,D6,D8,D7); // IN1, IN2, IN3, IN4 //Die maximale Geschwindigkeit bei 5Volt ist 15 RPM (RoundsPerMinute) //Je größer der Wert ist desto langsamer wird der Motor. //Mit einem langsamen Motor kann man größere Kräfte erzeugen! int motorSpeed = 1; //Es benötigt 4096 Schritte für eine volle Umdrehung. int motorSteps = 4096; //Wert für die Pause zwischen den Schritten. int motorDelay = 1000; void setup(){ motor.setStepDuration(motorSpeed); } void loop(){ //Erst eine volle Umdrehung entgegen des Uhrzeigersinns durchführen. motor.step(motorSteps); delay(motorDelay); //Eine kleine Pause einlegen. //Danach eine volle Umdrehung im Uhrzeigersinn durchführen. motor.step(-motorSteps); delay(motorDelay); //Eine kleine Pause einlegen. } |
Video
Webseite zum steuern des Schrittmotors 28BYJ-48 mit Treiberplatine ULN2003
Durch einen Kommentar auf einem meiner früheren Beiträge, bin ich auf eine wohl performantere Lösung von Seitenaufrufen hingewiesen worden. Dieses möchte ich nun in diesem Beispiel anwenden.
Die Webseite soll auf einem mobilen Endgerät laufen daher wähle ich die Einstellung für einen AccessPoint.
Damit sich mein Handy (Huawei P20 lite) mit dem Netzwerk verbinden konnte, musste ich die Mobilen Daten sowie die Einstellung „WLAN+“ unter den WLAN Einstellungen deaktivieren.
Erstellen der Webseite
Die Webseite muss als String im Sketch hinterlegt werden. Ich schreibe zuerst die Seite in einem Editor wie Notepad++ oder PSPad da diese mit einem entsprechenden Highlighting beim schreiben unterstützt.

Quellcode der Webseite
Nachfolgend nun den Quellcode für die Webseite.
Dieser Code muss noch um die echte IP-Adresse des Servers ergänzt werden dieses wird dann im Quellcode des Sketches erfolgen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | <html><head><meta charset="utf-8"> <title>Online Schrittmotorsteuerung</title> <style> label{ display:inline-block; width:230px;} .lbl {width:100px;} .textfield {width:60px;} </style> </head> <body> <h2>Schrittmotorsteuerung</h2> <fieldset> <legend>Konfiguration</legend> <label>Drehrichtung</label> <input type="radio" value="1" name="direction" id="vRbtn"/> <label for="vRbtn" class="lbl">Vorwärts</label> <input type="radio" value="2" name="direction" id="rRbtn"/> <label for="rRbtn" class="lbl">Rückwärts</label> <br/><br/> <label for="spTField">Geschwindigkeit</label> <input class="textfield" type="number" value="1" id="spTField" min="1" max="15"/> <br/><br/> <label for="sVUTField">Schritte für eine volle Umdrehung</label> <input class="textfield" type="number" value="4096" id="sVUTField" min="1"/> <br/><br/> <label for="sTField">Schritte</label> <input class="textfield" type="number" value="10" id="sTField" min="1"/> <br/><br/> <input type="button" value="Speichern" id="cSBtn"/> </fieldset> <div style="margin:0px auto; width:100px"> <br/><br/> <input type="button" value="Start" id="startBtn"/> </div> <script> var ipadresse = "-undefined-"; var drehrichtung = 1; var schritteVolleUmdrehung = 4096; var schritte = 10; var geschwindigkeit = 1; if(drehrichtung === 1){ document.getElementById("vRbtn").checked = true; } else { document.getElementById("rRbtn").checked = true; } document.getElementById("spTField").value(geschwindigkeit); document.getElementById("sVUTField").value(schritteVolleUmdrehung); document.getElementById("sTField").value(schritte); document.getElementById("startBtn").onclick = startMotor; document.getElementById("cSBtn").onclick = saveConfiguration; function startMotor(){ window.open("http://"+ipadresse+"/index.html?start=1","_self"); } function saveConfiguration(){ var direction = document.getElementById("vRbtn").checked?1:2; var svu = document.getElementById("sVUTField").value; var st = document.getElementById("sTField").value; var sp = document.getElementById("spTField").value; window.open("http://"+ipadresse+"/index.html?direction="+direction+"&svu="+svu+"&st="+st+"&sp="+sp,"_self"); } </script> </body> </html> |
Dieser Html Code muss nun in den Arduino Sketch eingefügt werden. Dazu werde ich diesen Code auf das Minimum reduzieren, d.h. alle unnötigen Leerzeichen sowie Zeilenumbrüche werden entfernt.
Das kann man per Hand oder aber auch bequem über eine Seite wie https://www.willpeavy.com/minifier/ lösen.
Das Ergebnis zu meinem Code wäre:
1 | <html><head><meta charset="utf-8"> <title>Online Schrittmotorsteuerung</title><style>label{display:inline-block; width:230px;}.lbl{width:100px;}.textfield{width:60px;}</style></head><body><h2>Schrittmotorsteuerung</h2><fieldset> <legend>Konfiguration</legend> <label>Drehrichtung</label> <input type="radio" value="1" name="direction" id="vRbtn"/> <label for="vRbtn" class="lbl">Vorwärts</label> <input type="radio" value="2" name="direction" id="rRbtn"/> <label for="rRbtn" class="lbl">Rückwärts</label> <br/><br/> <label for="spTField">Geschwindigkeit</label> <input class="textfield" type="number" value="1" id="spTField" min="1" max="15"/> <br/><br/> <label for="sVUTField">Schritte für eine volle Umdrehung</label> <input class="textfield" type="number" value="4096" id="sVUTField" min="1"/> <br/><br/> <label for="sTField">Schritte</label> <input class="textfield" type="number" value="10" id="sTField" min="1"/> <br/><br/> <input type="button" value="Speichern" id="cSBtn"/></fieldset><div style="margin:0px auto; width:100px"><br/><br/><input type="button" value="Start" id="startBtn"/></div><script>var ipadresse="-undefined-";var drehrichtung=1;var schritteVolleUmdrehung=4096;var schritte=10;var geschwindigkeit=1;if(drehrichtung===1){document.getElementById("vRbtn").checked=true;}else{document.getElementById("rRbtn").checked=true;}document.getElementById("spTField").value(geschwindigkeit);document.getElementById("sVUTField").value(schritteVolleUmdrehung);document.getElementById("sTField").value(schritte);document.getElementById("startBtn").onclick=startMotor;document.getElementById("cSBtn").onclick=saveConfiguration;function startMotor(){window.open("http://"+ipadresse+"/index.html?start=1","_self");}function saveConfiguration(){var direction=document.getElementById("vRbtn").checked?1:2;var svu=document.getElementById("sVUTField").value;var st=document.getElementById("sTField").value;var sp=document.getElementById("spTField").value;window.open("http://"+ipadresse+"/index.html?direction="+direction+"&svu="+svu+"&st="+st+"&sp="+sp,"_self");}</script></body></html> |
Die Lesbarkeit ist nun auf fast 0% gesunken, jedoch sind durch diese Art der Komprimierung die Bytes welche für den String benötigt werden gesunken.

Damit diese Seite später in dem Sketch verwendet werden kann müssen alle Anführungszeichen escaped werden, d.h. es muss ein Backslash „\“ davor gestellt werden. Dieses mache ich in der Anwendung NotePad++ durch die Funktion „Suchen & Ersetzen“.
Durch das bearbeiten der Seite kann diese nun nicht mehr mit einem Browser vernünftig dargestellt werden.
Aufbau des Sketches in der Arduino IDE
Erzeugen des AccesssPoints
Wie man einen AccessPoint einrichtet habe ich im Tutorial Wemos D1 Mini (ESP8266) als AccessPoint einrichten bereits beschrieben, daher möchte ich hier auf die Besonderheit eingehen damit dieser eine Webseite anzeigen kann.
Wir benötigen für die Anzeige einer Webseite zusätzlich einen Serverdienst diesen binden wir über die Bibliothek „ESP8266WebServer.h“ in den Sketch ein. Der Webserver läuft über den Port 80 (dies ist der übliche Port für einen HTTP Webserver).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> ESP8266WebServer server(80); int countConnectedDevices = 0; // Wird ausgeuehrt wenn "http://<ip address>/" aufgerufen wurde void callHome(){ String text = ""; text+="Hallo Welt!"; server.send(200, "text/html", text); } void setup(){ Serial.begin(115200); Serial.println(); boolean result = WiFi.softAP("WemosAP", "geheim123"); Serial.print("Verbindung wurde "); if(result == false){ Serial.println("NICHT "); } Serial.print("erfolgreich aufgebaut!"); Serial.println("Server IP-Adresse:"); Serial.print(WiFi.softAPIP()); //Wenn der Client eine Anfrage startet. server.on("/", callHome); // Starte den Server server.begin(); } void loop(){ if(countConnectedDevices != WiFi.softAPgetStationNum()){ countConnectedDevices = WiFi.softAPgetStationNum(); Serial.printf("Anzahl der Verbundenen Geräte= %d\n", countConnectedDevices); } server.handleClient(); } |
Wenn dieser Sketch ausgeführt wird, dann wird als erstes auf dem seriellen Monitor der Arduino IDE folgende Ausgabe sichtbar:

Wir sollten also nun das gesicherte Netzwerk „WemosAP“ sehen.
Hat man sich erfolgreich zum Netzwerk verbunden so navigiert man mit
einen beliebigen Browser zur IP-Adresse „192.168.4.1“ es sollte
dann die Ausgabe „Hallo Welt!“ erscheinen.

Ersetzen wir also nun den Text „Hallo Welt!“ gegen unsere Webseite und ersetzen im JavaScript Block den Platzhalter für die IP-Adresse durch die echte.

Sketch mit der Webseite und dem Code für den Schrittmotor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <StepperMotor.h> ESP8266WebServer server(80); StepperMotor motor(D5,D6,D8,D7); int countConnectedDevices = 0; int drehrichtung = 1; int schritteVolleUmdrehung = 4096; int schritte = 10; int geschwindigkeit = 1; IPAddress ipAdresse; void callHome(){ Serial.println("callHome"); server.send(200, "text/html", getWebpage()); } void callStart(){ Serial.println("callStart"); printArgs(); motor.setStepDuration(geschwindigkeit); switch(drehrichtung){ case 1 : motor.step(schritte); break; case 2 : motor.step(-schritte); break; } server.send(200, "text/html", getWebpage()); } void callConfig(){ Serial.println("callConfig"); printArgs(); server.send(200, "text/html", getWebpage()); } void printArgs(){ for (int i = 0; i < server.args(); i++) { String parameterName = server.argName(i); String parameterValue = server.arg(i); if(parameterName == "svu"){ schritteVolleUmdrehung = parameterValue.toInt(); } else if(parameterName == "st"){ schritte = parameterValue.toInt(); } else if(parameterName == "sp"){ geschwindigkeit = parameterValue.toInt(); } else if(parameterName == "direction"){ drehrichtung = parameterValue.toInt(); } Serial.print(parameterName); Serial.print(" : "); Serial.println(parameterValue); } } String getWebpage(){ String webpage ="<html><head><meta charset=\"utf-8\"> <title>Online Schrittmotorsteuerung</title><style>label{display:inline-block; width:230px;}.lbl{width:100px;}.textfield{width:60px;}</style></head><body><h2>Schrittmotorsteuerung</h2><fieldset> <legend>Konfiguration</legend> <label>Drehrichtung</label> <input type=\"radio\" value=\"1\" name=\"direction\" id=\"vRbtn\"/> <label for=\"vRbtn\" class=\"lbl\">Vorwärts</label> <input type=\"radio\" value=\"2\" name=\"direction\" id=\"rRbtn\"/> <label for=\"rRbtn\" class=\"lbl\">Rückwärts</label> <br/><br/> <label for=\"spTField\">Geschwindigkeit</label> <input class=\"textfield\" type=\"number\" value=\"1\" id=\"spTField\" min=\"1\" max=\"15\"/> <br/><br/> <label for=\"sVUTField\">Schritte für eine volle Umdrehung</label> <input class=\"textfield\" type=\"number\" value=\"4096\" id=\"sVUTField\" min=\"1\"/> <br/><br/> <label for=\"sTField\">Schritte</label> <input class=\"textfield\" type=\"number\" value=\"10\" id=\"sTField\" min=\"1\"/> <br/><br/> <input type=\"button\" value=\"Speichern\" id=\"cSBtn\"/></fieldset><div style=\"margin:0px auto; width:100px\"><br/><br/><input type=\"button\" value=\"Start\" id=\"startBtn\"/></div><script>var ipadresse=\""+ipAdresse.toString()+"\";var drehrichtung="+drehrichtung+";var schritteVolleUmdrehung="+schritteVolleUmdrehung+";var schritte="+schritte+";var geschwindigkeit="+geschwindigkeit+";if(drehrichtung===1){document.getElementById(\"vRbtn\").checked=true;}else{document.getElementById(\"rRbtn\").checked=true;}document.getElementById(\"spTField\").value=geschwindigkeit;document.getElementById(\"sVUTField\").value=schritteVolleUmdrehung;document.getElementById(\"sTField\").value=schritte;document.getElementById(\"startBtn\").onclick=startMotor;document.getElementById(\"cSBtn\").onclick=saveConfiguration;function startMotor(){window.open(\"http://\"+ipadresse+\"/start.html?start=1\",\"_self\");}function saveConfiguration(){var direction=document.getElementById(\"vRbtn\").checked?1:2;var svu=document.getElementById(\"sVUTField\").value;var st=document.getElementById(\"sTField\").value;var sp=document.getElementById(\"spTField\").value;window.open(\"http://\"+ipadresse+\"/config.html?direction=\"+direction+\"&svu=\"+svu+\"&st=\"+st+\"&sp=\"+sp,\"_self\");}</script></body></html>"; return webpage; } void setup(){ Serial.begin(115200); Serial.println(); boolean result = WiFi.softAP("WemosAP", "geheim123"); Serial.print("Verbindung wurde "); if(result == false){ Serial.println("NICHT "); } Serial.println("erfolgreich aufgebaut!"); Serial.println(""); Serial.println("Server IP-Adresse:"); ipAdresse = WiFi.softAPIP(); Serial.print(ipAdresse); //Wenn der Client eine Anfrage startet. server.on("/", callHome); server.on("/start.html", callStart); server.on("/config.html", callConfig); // Starte den Server server.begin(); } void loop(){ if(countConnectedDevices != WiFi.softAPgetStationNum()){ countConnectedDevices = WiFi.softAPgetStationNum(); Serial.printf("Anzahl der Verbundenen Geräte= %d\n", countConnectedDevices); } server.handleClient(); } |