Servos ansteuern
Hallo,
heute gibt es ein kurzes Tutorial zum Thema Servomotor. Dazu brauchen wir ein Arduino und natürlich einen kleinen Servomotor der mit 5V betrieben werden kann [z.B. 230500 - 62 von Conrad].
Zunächst aber nochmal kurz gesagt, was denn der Unterschied vom Servomotor zum Elektromotor ist. Ein normaler Elektromotor erzeugt schlicht und einfach eine Drehbewegung, wobei man die Drehrichtung meist durch die Polung einstellen kann. Der einfache Elektromotor kann sich beliebig oft drehen, allerdings ist es schwierig genaue Bewegungen zu erzeugen - man kann nicht einfach sagen: “Jetzt 3 Umdrehungen vorwärts und dann 2 Rückwärts”.
Der Servo funktioniert komplett anders, da man normalerweise nicht mehr als eine halbe Umdrehung mit der Achse machen kann, diese aber auf wenige Grad genau steuern kann. Dazu ist im Servo bereits eine Steuerlogik und ein Getriebe verbaut.
Das Stecken der Verbindungen ist relativ einfach und in der Grafik ist das Breadboard eigentlich nur zur besseren Visualisierung vorhanden.
Da es in Fritzing zur Zeit leider noch keinen Servomotor gibt, kann ich euch das Sketch nicht zum Download bereit stellen. Ich weiß aber vom Fritzing-Team, dass da bald was passieren wird.
Nun gut, jetzt ist der Servo vermutlich angesteckt, aber wieso hat der eigentlich 3 Kabel? Damit wir den Servo so genau steuern können, ist es mit Ein- und Ausschalten nicht getan. Um genau zu sein, ist der Servo eigentlich immer eingeschaltet und über das dritte (gelbe) Kabel geben wir ihm das Signal auf welche Position er fahren soll.
Da dieses Signal nicht ganz so einfach erzeugt werden kann, ist die Programmierung für einen Servo leider auch etwas komplizierter - insbesondere wenn man ihn in komplexen Projekten mit anderen Teilen kombinieren muss.
Das Steuersignal besteht aus einem sehr kurzen Strompuls, wobei die Länge des Pulses bestimmt auf welche Position der Servo fahren soll. Dieses Pulssignal muss wiederum solange wiederholt werden, bis der Servo seine endgültige Stellung erreicht hat, es genügt also nicht nur ein einziger Puls.
Hier jedenfalls der Code:
/* Servo Steuerung by Tom Igoe additions by Carlyn Maw translation by Marcus Paeschke Created 28 Jan. 2006 Updated 7 Jun. 2006 Translated 9 May 2008 Die Werte für den kürzesten Puls (minPulse) und den längsten Puls (maxPulse) können je nach Modell des eingesetzten Servos variieren. Im Idealfall sollten die Pulse zwischen einer und zwei Millisekunden lang sein, in der Praxis haben sich aber auch Werte zwischen 500 und 2500 Mikrosekunden bewährt. Probiert selbst aus, welche Werte am besten für euch funktionieren. Dieser Code benutzt die Funktion millis() um die Zeit zwischen den Pulsen zu bestimmen. Die Funktion erzeugt allerdings nach etwa 5 Tagen Laufzeit einen Speicherüberlauf, d.h. die Zahl wird größer als sie in der Variable abgespeichert werden kann. Solltet ihr ein Programm schreiben, was entsprechend lange laufen muss, denkt bitte daran. */ int servoPin = 2; // Steuerpin für den Servo int minPulse = 500; // Minimalposition des Servos int maxPulse = 2500; // Maximalposition des Servos int pulse = 0; // Aktueller Pulswert long lastPulse = 0; // Zeitpunkt des letzten Pulses int refreshTime = 20; // Kurze Erfrischungszeit dazwischen boolean updown = true; // Gehts jetzt Hoch oder Runter void setup() { pinMode(servoPin, OUTPUT); // Servopin ist ein Ausgabepin pulse = minPulse; // Position des Servos startet auf Minimum Serial.begin(9600); // Serielle Verbindung zur Kontrolle } void loop() { if(updown) { pulse++; if(pulse >= maxPulse) { updown = false; } } else { pulse--; if(pulse <= minPulse) { updown = true; } } // Neuer Puls nach der eingestellten Pause if (millis() - lastPulse >= refreshTime) { digitalWrite(servoPin, HIGH); // Puls beginnt delayMicroseconds(pulse); // Länge des Pulses bestimmt die neue Servoposition digitalWrite(servoPin, LOW); // Puls endet lastPulse = millis(); // Speichert die aktuelle Zeit } }
Noch ein paar Bemerkungen am Rande:
Um so länger die Zeit zwischen den Pulsen ist, umso langsamer bewegt sich der Servo. Die minimale Zeit zwischen den Pulsen entspricht der maximalen Pulslänge.
Werden Servos überstrapaziert, z.B. durch zu extreme Pulswerte oder permanente Bewegung unter hoher Last können sie heiß laufen, was schnell zum Defekt führt.
Servos gehören zu den elektromagnetischen Bauteilen, die eine Rückkopplungsspannung - auch genannt Blowback - erzeugen, welche dem restlichen Stromkreis nicht besonders gut bekommt. Bei dem oben eingesetzten Miniservo gab es bisher keine Probleme, solltet ihr jedoch stärkere Servos, normale Elektromotoren oder Relais einsetzen, solltet ihr eine Diode benutzen um den Stromkreis zu schützen. Näheres dazu findet ihr im Beitrag über das Relais bzw. in einem zukünftigen Artikel.
Als kleine Hausaufgabe könnt ihr ja mal ein Potentiometer in die Schaltung integrieren, mit dem die Position des Servos steuern kann.
derMarc
20 Dez, 2008
changed the code a little bit. feels much smoother and much more accurate now… also added the possibility to change the speed of the servo.
happy about comments!
/*
Servo Steuerung
by Tom Igoe
additions by Carlyn Maw, Marc Tiedemann
translation by Marcus Paeschke
Created 28 Jan. 2006
Updated 7 Jun. 2006
Translated 9 May 2008
Die Werte für den kürzesten Puls (minPulse) und den längsten Puls
(maxPulse) können je nach Modell des eingesetzten Servos variieren.
Im Idealfall sollten die Pulse zwischen einer und zwei Millisekunden
lang sein, in der Praxis haben sich aber auch Werte zwischen
500 und 2500 Mikrosekunden bewährt. Probiert selbst aus, welche
Werte am besten für euch funktionieren.
Dieser Code benutzt die Funktion millis() um die Zeit zwischen den
Pulsen zu bestimmen. Die Funktion erzeugt allerdings nach etwa 5 Tagen
Laufzeit einen Speicherüberlauf, d.h. die Zahl wird größer als sie in
der Variable abgespeichert werden kann. Solltet ihr ein Programm
schreiben, was entsprechend lange laufen muss, denkt bitte daran.
*/
int servoPin = 10; // Steuerpin für den Servo
int minPulse = 500; // Minimalposition des Servos
int maxPulse = 2550; // Maximalposition des Servos
int pulse = 0; // Aktueller Pulswert
int servoSpeed = 5; // Bewegungsgeschwindigkeit
int refreshTime = 10; // Kurze Erfrischungszeit dazwischen
boolean updown = true; // Gehts jetzt Hoch oder Runter
void setup() {
pinMode(servoPin, OUTPUT); // Servopin ist ein Ausgabepin
pulse = minPulse; // Position des Servos startet auf Minimum
Serial.begin(9600); // Serielle Verbindung zur Kontrolle
}
void loop() {
// Neuer Puls nach der eingestellten Pause
if(updown) {
pulse = pulse+servoSpeed;
if(pulse >= maxPulse) {
updown = false;
}
} else {
pulse=pulse-servoSpeed;
if(pulse <= minPulse) {
updown = true;
}
}
digitalWrite(servoPin, HIGH); // Puls beginnt
delayMicroseconds(pulse); // Länge des Pulses bestimmt die neue Servoposition
digitalWrite(servoPin, LOW); // Puls endet
delay(refreshTime);
}
Bastian
17 Jan, 2009
Hi,
Ich hab mir mal erlaubt, den ursprünglichen Code um weitere Kommentare zu ergänzen und den Code umzuformatieren.
Mir erleichtert das das Lesen …
[quote]
[color=#777755]/*[/color]
[color=#777755]Servo Steuerung[/color]
[color=#777755] [/color]
[color=#777755] by Tom Igoe[/color]
[color=#777755] additions by Carlyn Maw[/color]
[color=#777755] translation by Marcus Paeschke[/color]
[color=#777755] Created 28 Jan. 2006[/color]
[color=#777755] Updated 7 Jun. 2006[/color]
[color=#777755] Translated 9 May 2008[/color]
[color=#777755] [/color]
[color=#777755] Die Werte für den kürzesten Puls (minPulse) und den längsten Puls[/color]
[color=#777755] (maxPulse) können je nach Modell des eingesetzten Servos variieren.[/color]
[color=#777755] Im Idealfall sollten die Pulse zwischen einer und zwei Millisekunden[/color]
[color=#777755] lang sein, in der Praxis haben sich aber auch Werte zwischen[/color]
[color=#777755] 500 und 2500 Mikrosekunden bewährt. Probiert selbst aus, welche[/color]
[color=#777755] Werte am besten für euch funktionieren.[/color]
[color=#777755] [/color]
[color=#777755] Dieser Code benutzt die Funktion millis() um die Zeit zwischen den[/color]
[color=#777755] Pulsen zu bestimmen. Die Funktion erzeugt allerdings nach etwa 5 Tagen[/color]
[color=#777755] Laufzeit einen Speicherüberlauf, d.h. die Zahl wird größer als sie in[/color]
[color=#777755] der Variable abgespeichert werden kann. Solltet ihr ein Programm[/color]
[color=#777755] schreiben, was entsprechend lange laufen muss, denkt bitte daran.[/color]
[color=#777755] */[/color]
[color=#996600]int[/color] servoPin = 2; [color=#777755]// Steuerpin für den Servo[/color]
[color=#996600]int[/color] minPulse = 500; [color=#777755]// Minimalposition des Servos[/color]
[color=#996600]int[/color] maxPulse = 2500; [color=#777755]// Maximalposition des Servos[/color]
[color=#996600]int[/color] pulse = 0; [color=#777755]// Aktueller Pulswert[/color]
[color=#996600]long[/color] lastPulse = 0; [color=#777755]// Zeitpunkt des letzten Pulses[/color]
[color=#996600]int[/color] refreshTime = 20; [color=#777755]// Kurze Erfrischungszeit dazwischen[/color]
[color=#996600]boolean[/color] updown = [color=#CC6600]true[/color]; [color=#777755]// Gehts jetzt Hoch oder Runter[/color]
[color=#CC6600]void[/color] [color=#993300][b]setup[/b][/color]() {
[color=#996600]pinMode[/color](servoPin, [color=#CC0000]OUTPUT[/color]); [color=#777755]// Servopin ist ein Ausgabepin[/color]
pulse = minPulse; [color=#777755]// Position des Servos startet auf Minimum[/color]
}
[color=#CC6600]void[/color] [color=#993300][b]loop[/b][/color]()
{
[color=#CC6600]if[/color](updown) [color=#777755]// wenn der Servo hoch drehen soll, setze auch die Pulslänge hoch[denn: die Pulslänge bestimmt ja die Position des Servos![/color]
{
pulse++;
[color=#CC6600]if[/color](pulse >= maxPulse) [color=#777755]// wenn der höchste Servostand erreicht ist[/color]
{
updown = [color=#CC6600]false[/color]; [color=#777755]// dann setz das Flag wieder auf “runterfahren”[/color]
}
}
[color=#CC6600]else[/color] [color=#777755]// wenn der Servo runter drehen soll, setze auch die Pulslänge runter …[/color]
{
pulse–;
[color=#CC6600]if[/color](pulse = refreshTime)
{
[color=#996600]digitalWrite[/color](servoPin, [color=#CC0000]HIGH[/color]); [color=#777755]// Puls beginnt[/color]
[color=#996600]delayMicroseconds[/color](pulse); [color=#777755]// Länge des Pulses bestimmt die neue Servoposition[/color]
[color=#996600]digitalWrite[/color](servoPin, [color=#CC0000]LOW[/color]); [color=#777755]// Puls endet[/color]
lastPulse = [color=#996600]millis[/color](); [color=#777755]// Speichert die aktuelle Zeit[/color]
}
}
[/quote]
Bastian
17 Jan, 2009
uh-oh. Tut mir leid. Hab gedacht, unter Arduino wäre “tools->copy for forum” das Mittel der Wahl …
:(
Bastian
17 Jan, 2009
Hoffe, jetzt wird’s besser …
/*
Servo Steuerung
by Tom Igoe
additions by Carlyn Maw
translation by Marcus Paeschke
Created 28 Jan. 2006
Updated 7 Jun. 2006
Translated 9 May 2008
Die Werte für den kürzesten Puls (minPulse) und den längsten Puls
(maxPulse) können je nach Modell des eingesetzten Servos variieren.
Im Idealfall sollten die Pulse zwischen einer und zwei Millisekunden
lang sein, in der Praxis haben sich aber auch Werte zwischen
500 und 2500 Mikrosekunden bewährt. Probiert selbst aus, welche
Werte am besten für euch funktionieren.
Dieser Code benutzt die Funktion millis() um die Zeit zwischen den
Pulsen zu bestimmen. Die Funktion erzeugt allerdings nach etwa 5 Tagen
Laufzeit einen Speicherüberlauf, d.h. die Zahl wird größer als sie in
der Variable abgespeichert werden kann. Solltet ihr ein Programm
schreiben, was entsprechend lange laufen muss, denkt bitte daran.
*/
int servoPin = 2; // Steuerpin für den Servo
int minPulse = 500; // Minimalposition des Servos
int maxPulse = 2500; // Maximalposition des Servos
int pulse = 0; // Aktueller Pulswert
long lastPulse = 0; // Zeitpunkt des letzten Pulses
int refreshTime = 20; // Kurze Erfrischungszeit dazwischen
boolean updown = true; // Gehts jetzt Hoch oder Runter
void setup() {
pinMode(servoPin, OUTPUT); // Servopin ist ein Ausgabepin
pulse = minPulse; // Position des Servos startet auf Minimum
}
void loop()
{
if(updown) // wenn der Servo hoch drehen soll, setze auch die Pulslänge hoch[denn: die Pulslänge bestimmt ja die Position des Servos!
{
pulse++;
if(pulse >= maxPulse) // wenn der höchste Servostand erreicht ist
{
updown = false; // dann setz das Flag wieder auf “runterfahren”
}
}
else // wenn der Servo runter drehen soll, setze auch die Pulslänge runter …
{
pulse–;
if(pulse = refreshTime)
{
digitalWrite(servoPin, HIGH); // Puls beginnt
delayMicroseconds(pulse); // Länge des Pulses bestimmt die neue Servoposition
digitalWrite(servoPin, LOW); // Puls endet
lastPulse = millis(); // Speichert die aktuelle Zeit
}
}
Bastian
17 Jan, 2009
ps: ich habe jetzt den seriellen Port nicht geöffnet bzw. die Zeile gelöscht, weil der Port im weiteren Verlauf des Scripts eh’ keine Verwendung gefunden hat ….