Da ich für ein neues Projekt auf den Einsatz eines Modellbau Servos nicht verzichten kann, möchte ich die Gelegenheit nutzen hier eine kleine Anleitung zum Betrieb von Modellbauservos mit dem Arduino zu schreiben.
Grundgedanken zur Theorie
Ein Servo besteht aus einer Steuerelektronik und einem Gleichspannungs-Elektromotor. Beide Einheiten sind dabei auf engstem Raum untergebracht. Die integrierte Elektronik ermittelt den Drehwinkel des Motors. Dabei erfolgt die Ermittlung des Drehwinkels zum Beispiel über ein Potentiometer. Die Schaltung vergleicht anschließend das Eingangssignal des Servos mit der aktuellen Position des Elektromotors. Somit kann die Position des Motores geregelt werden. Im Falle des Modellbau Servos, welches in den folgenden Aufbauten zum Einsatz kommt, nutze ich ein PWM Signal des Arduinos. Wobei die die Breite des Pulssignals dem Eingangssignal des Servos entspricht. Es handelt sich meist um eine Frequenz von 50 Hertz. Bei einer Periodendauer von 20 ms. Die Pulsweite des Eingangssignals liegt dann im Bereich von 1ms welches den linken Anschlag des Servos darstellt und 2 ms für den rechten Anschlag des Servos. Also liegt die Mittelposition bei ca. 1,5 ms. Während der restlichen Zeit der PWM Periode bleibt das Signal auf LOW.
Etwas zur Praxis
Die gängigsten Modellbau Servos haben 3 Anschlussleitungen. Wobei diese in der Regel wie folgt belegt sind:
- – GND (Schwarz)
- – PWM (Weiß*, Gelb, Orange)
- – +5V (Rot)
* In meinem Beispiel verwendetes Servo
Im folgenden werde ich 2 Möglichkeiten aufweisen, ein Servo über einen Arduino anzusteuern. Als erstes werde ich zeigen wie man die oben beschriebene Theorie in eigenen Code umwandelt. Im zweiten Beispiel kommt die bei der Arduino IDE bereits mitgelieferte Servo Bibliothek zum Einsatz. Die Bibliothek erspart dem Programmierer das Austüfteln der korrekten Impulsbreiten und Frequenzen.
Als erstes muss das Servo mit dem Arduino verkabelt werden. Die Abbildung zeigt die korrekte Verkabelung. Schwarzes Kabel des Servos auf GND am Arduino. Rotes Kabel des Servos an 5V. Und zuletzt das in meinem Fall weiße Kabel an einen der PWM Pin’s. Für die Nutzung der Servo Bibliothek wählen wir wie auf der Abbildung zu sehen ist Pin 9 oder Pin 10, da diese bereits für den ServoBetrieb reserviert sind.
Die Programmierung
Mit dem folgenden Code kann ein Servo betrieben werden ohne hinzunahme von Bibliotheken. Dies kann von Vorteil sein, wenn man Platz auf dem Controller sparen möchte. Es hier darauf zu achten, das im folgenden Code Pin 7 als Signalpin für das Servo verwendet wird. Das Servo sollte in diesem Fall also auch an Pin 7 angeschlossen sein.
Listing 1:
// Festlegen des Servo Pins
int servo = 7;
// Weitere Variablen für PWM und Drehwinkel (Position)
int pwm;
int pos;
/* Funktion um das Servo zu bewegen. Hier wird die Position
berechnet und der Wert der neuen Position an das Servo
übergeben. */
void servoMove(int servo, int pos){
//Winkel in Mikrosekunden umrechnen
pwm = (pos * 11) + 500;
// Servo Pin auf HIGH zum aktivieren des Servos
digitalWrite(servo, HIGH);
// Kurze Zeit warten
delayMicroseconds(pwm);
// Servo Pin auf LOW zum deaktivieren des servos
digitalWrite(servo, LOW);
// 20 ms warten
delay(20);
}
// Initialisieren des Servo Pins
void setup() {
pinMode(servo, OUTPUT);
}
// Hauptprogramm
void loop() {
for(pos=0; pos<180; pos++) {
servoMove(servo, pos);
}
}
Beim ausführen des Codes bewegt sich das Servo einmal bis zum Anschlag (180 Grad) und dreht wieder zum entgegengesetzten Anschlag zurück. Das ganze wiederholt sich anschließend.
Eine etwas einfachere Lösung zeigt Listing 2. Hier wird auf die in der Arduino IDE enthaltene Servo Library zurückgegriffen. Das Beispiel findet sich auch in der IDE unter File->Examples->Servo. Trotzdem möchte ich dieses Beispiel noch einmal hier aufführen um den direkten Vergleich der beiden Methoden nahezulegen. Achtung: bei Listing 2 wird Pin 9 verwendet.
Listing 2:
#include <Servo.h>
// Erzeugen eines Servo Objekts zur Servo Steuerung
Servo myservo;
// Variable zum Speichern der Position
int pos = 0;
// Initialisierung der Pins
void setup(){
myservo.attach(9);
}
// Hauptprogramm
void loop(){
for(pos = 0; pos < 180; pos++){
myservo.write(pos);
delay(15);
}
}
Listing 2 bewegt das Servo auf die gleiche Weise wie Listing 1. Der Unterschied der beiden Varianten liegt lediglich in der Menge zu schreibender Code. Es ist also viel einfacher und kofortabler die Servo Bibliothek zu verwenden.
Zuletzt möchte ich noch einmal kurz auf das in einigen anderen meiner Beiträge vorgestellte Motorshield von Lady Ada eingehen. Mit dem Shield können 2 Servos betrieben werden. Der Einsatz des Shields macht das Anschließen von Servos sehr einfach und es können außerdem gleichzeitig noch 2 Stepper oder 4 Elektromotoren betrieben werden. Auf der Webseite von Lady Ada gibt es eine genaue Beschreibung es Shields und viele Code Beispiele. Wer also einen einfachen Einstieg in Robotik mit dem Arduino sucht, dem kann ich das Motorshield nur empfehlen.
Hallo,
danke für deine Anleitung zur Manuellen PWM Erzeugung zur Ansteuerung eines Servos. Bei dem Beispielprogramm wird, um eine Frequenz von 50HZ zu erreichen. Während dieser Delayzeit ist ja das Arduino Board „blockiert“ und kann keine weitere Funktionen, zBsp das einlesen eines Analogwertes ausführen.
Kennst du für dieses Problem eine alternative Lösung?
MfG
Robert
Hallo,
wie schaffe ich es, dass der Servo bei 90 Grad stehen bleibt und ich dabei noch abfragen machen kann?
genau das durchschauen ich auch noch nicht so recht. Bist du weitergekommen ?
Hallo,
danke für den hilfreichen Beitrag. Ich habe eine Frage bzgl. der Pulsweite in dem Codebeispiel Listing 1. In der Einleitung hieß es dass die Pulsweite zwischen 1ms (linker Ausschlag und 2ms (rechter Ausschlag) dauert. Wenn man sich jedoch in dem Codebsp. pwm für pos=0 und pos=180 ausrechnet kommt man auf einen Wert zwischen 0,5ms bzw. 2,5ms. Woher rührt dieser Unterschied bzw. hat er eine Bedeutung?
MfG Dominik
Hallo Dominik, ich vermute mal, dass du eine falsche Überlegung angestellt hast. Das PWM-Signal hat eine Frequenz von etwa 50 Hz … daraus folgt, dass jede Periode 20ms lang ist. Innerhalb dieser 20 ms plaziert der Arduino die eigentlichen Informationen. Also einen Impuls von 1ms für links und 2ms für rechts. Diese Informationen werden so lange gesendet, bis das Poti als Rückmeldung die eingenommene Position bestätigt.
[…] den “Konzentrationswert” anzeigen. Mit ein paar zusätzlichen Code Zeilen und der Arduino Servo Library konnte ich dann das Servo über Gedanken […]
Hi,
bei meinen Tests einen Servo manuell anzusteuern kam ich auch auf solch komische Werte zwischen 0,5 ms und 2,5 ms für die PWM. Woran das liegt?!
Ich habe auch die Pause variiert (delayMicroseconds(20000-pwm), das half jedoch nicht.
LG Frerk
ps https://popovic.info/html/arduino/arduinoUno_1.html
Moin,
vielen Dank für diesen Beitrag!
Ich hatte auch davor schon die Idee gehabt, einen Digitalpin HIGH und nach delayMicroseconds(……) wieder LOW zu schalten. Leider hat das bei mir überhaupt nicht funktioniert, was wohl in einem Fehler anderswo lag. Du hast mir sehr geholfen!
Grüße,
Aeron
Seit wann darf man denn solch grosse Servos direkt an den Arduino anschliessen? Finde ich nicht toll solche Tipps an Anfänger zu verteilen und dann sterben die *duinos wie die Fliegen wenn mal ein bisschen Stellkraft zusammenkommt. Und das weil jemand wie Du dachte er müsste wieder halbgare Tipps unters Volk werfen. Bitte korrigieren.
Danke ich habe es zur Kenntnis genommen und werde bei Gelegenheit mal neue Fotos machen.
Hey wollte mal fragen wieso hier die pos mit 11 multipliziert wird. Kann man das nicht anders lösen?
Hi,
warum so schwierig?
Dafür gibt es die analogWrite Methode, die auf einen PWM PIN ausgeführt werden kann. Oder ist die gelieferte Frequenz mit dem Servo nicht kompatibel?
https://www.arduino.cc/en/Reference/AnalogWrite
Mein Artikel ist schon sehr alt.
[…] Quelle: Arduino – Servo Tutorial […]
Wie entsteht die Winkelberechnung pwm = (pos * 11) + 500;?