Servo-Motoren mit Arduino

Einfacher Servomotor
Abb.: Einfacher Servomotor

Verwendete Bauteile

Anschluss des Servos

Eigentlich muss nur 5V mit dem roten Kabel, GND mit dem schwarzen Kabel und ein digitaler Pin mit PWM mit dem verbleibenden (meist gelben oder orangen Kabel) verbunden werden. Wichtig ist zu wissen, dass Servomotoren nur schlecht mit 3,3V laufen und daher oft beim Betrieb mit einer zu niedrigen Spannung brummen können, weil sie die Position nicht richtig einstellen können.

Achtung: Da alle Gleichstrommotoren eine recht hohe Stromaufnahme haben, sollte man auch Servo-Motoren NICHT direkt über die VCC-Pins des Mikrocontroller-Boards versorgen, sondern über eine externe Stromquelle (Batterie, Akku, etc.). Der Mikrocontroller könnte sonst Schaden nehmen!
Der direkte Anschluss an den Arduino wurde hier nur zur Vereinfachung verwendet (Verwendung auf eigene Verantwortung!)

Servomotor an Arduino anschließen
Abb.: Servomotor an Arduino anschließen

Servo mit Library ansteuern

Mit der Library Servo, die schon in der Arduino-IDE vorhanden ist, aber auch über GitHub bei Arduino/libraries/Servo geladen werden kann, ist eine Ansteuerung des Servos sehr einfach.
Hinweis: Die Zahl in servoMotor.write() ist immer der Winkel, der gestellt werden soll.
Wichtig: Die beiden letzten Parameter beim Aufruf von servoMotor.attach() entsprechen dem minimalen und maximalen Verzögerungszeit des PWM-Signals und sollten für den Motor richtig gewählt werden, damit die Stellwinkel auch wirklich stimmen!

#include <Servo.h>

#define SERVO_SIGNAL_PIN 9

Servo servoMotor;

void setup()
{
    servoMotor.attach(SERVO_SIGNAL_PIN, 900, 1500);
}

void loop()
{
    servoMotor.write(45);
    delay(500);

    servoMotor.write(135);
    delay(500);


    for(int i = 0; i<180; i+=5){
        servoMotor.write(i);
        delay(150);
    }

    delay(1000);

    for(int i = 180; i>0; i-=5){
        servoMotor.write(i);
        delay(150);
    }
}

Servomotor direkt ansteuern

Es ist auch möglich ohne Verwendung einer Library einen Servomotor mit einem Arduino anzusteuern.
Dazu muss zunächst ein HIGH über die Signalleitung geschickt werden. Anschließend ist eine Pause zwischen 1000µs bis 2000µs einzuhalten, je nachdem welcher Winkel gestellt werden soll. Dann folgt ein LOW, wobei darauf noch eine kurze Pause von ca. 20ms folgen sollte, damit der Motor genug Zeit hat, sich vollständig einzustellen.
In meinen Versuch ist aber herausgekommen, das es nicht der absolute Winkel ist, der gestellt wird, sondern der relative, d.h. man verstellt durch setServoAngle() immer nur UM einen bestimmten Winkel und nicht AUF einen Winkel. Außerdem ist der Servomotor nach dem Stellen manuell frei beweglich und nicht elektrisch gesperrt.

#define SERVO_SIGNAL_PIN 8

void setup()
{
    pinMode(SERVO_SIGNAL_PIN, OUTPUT);

    for(int i=0; i<180; i+=5){
        setServoAngle(i);
        delay(100);
    }
}

void loop()
{
}

void setServoAngle(byte angle)
{
    // calculate angle to delayTime
    int delayTime = map(angle, 0, 180, 1000, 2000);

    digitalWrite(SERVO_SIGNAL_PIN, HIGH);
    delayMicroseconds(delayTime);
    digitalWrite(SERVO_SIGNAL_PIN, LOW);
    delay(20); // short pause at the end of the regulating
}

360°-Servomotor "DS04-NFC"

Einen speziellen Servo ist das folgende Modell, welches sich um 360° kontinuierlich drehen kann. Laut Hersteller besitzt es folgende Eigenschaften:

Gewicht: 38g
Abmessungen: 40,8 × 20,0 × 39,5 mm
Geschwindigkeit: 0,22s / 60° (bei 4,8V)
Betriebsspannung: 4,8V - 6V
Betriebsstrom: <1000mA
Drehmoment: 5,5kg/cm (bei 4,8V)
Servomotor DS04-NFC mit 360°-Drehfähigkeit
Abb.: Servomotor DS04-NFC mit 360°-Drehfähigkeit

Funktionsweise laut Hersteller

"The signal terminal needs to be input one 50 HZ square wave, then the duration of high level pulse, which is used to control signal cycle, can control speed and forward/backward rotation as well as stalling. The duration of A high level corresponds to a speed. When high level is 1ms~1.5ms, servo rotates forward(the rotate speed is the fastest when it is 1ms, the later the lower, servo will stop rotating when reaching 1.5ms). When high level is 1.5 ~2ms, the servo rotates backward (The servo stops rotating when reaching 1.5ms, when the duration is closer to 2ms, the closer, the faster. The backward rotation speed is the fastest when reaching 2ms)

This servo carries meso-position adjustment potentiometer(it can only be seen by peeling off the outer cover and circuit board). We can set high level pulse at 1.5ms to observe that whether servo stops rotating. If it doesn’t stop rotating, we keep adjusting the potentiometer until it does.

Just enter the square wave signal terminal a 50Hz signal, and then controls the duration of the high-level pulse signal cycle can control the speed and reversing and stalling. A high level pulse corresponds to the duration of a speed. HIGH 1 ms - 1.5 ms, Steering gear forward (1 msec fastest forward, closer to 1.5 milliseconds slower, 1.5 ms Steering gear stalled), the high level of 1.5 ms to 2 ms when the Steering gear reverse (1.5 ms Steering gear stalling, the closer the faster reverse speed 2 ms, 2 ms fastest reversal)

Note: This servo can draw relatively high currents, especially with load. (up to approximately 1000mA at 4.8V at standstill) So choose a suitable power supply for the servo. It is not recommended to take the Arduino power."

Servomotor DS04-NFC mit 360°-Drehfähigkeit
Abb.: PWM Signal timings

Sketch

#include <Servo.h>

#define SERVO_SIGNAL_PIN  9

// define the duration of the signal in milliseconds
#define STOP 1500
#define ROTATE_CLOCKWISE   1000
#define ROTATE_COUNTERCLOCKWISE  2000

Servo servoMotor;

void setup()
{
    servoMotor.attach(SERVO_SIGNAL_PIN);

    servoMotor.writeMicroseconds(STOP);
    delay(2000);

    servoMotor.writeMicroseconds(ROTATE_CLOCKWISE);
    delay(2000);

    servoMotor.writeMicroseconds(ROTATE_COUNTERCLOCKWISE);
    delay(2000);

    servoMotor.writeMicroseconds(STOP);
}

void loop()
{
}

Servo mit Feedback

Einige Servo-Motoren, wie der Adafruit Micro Servo oder der Feetech FT90M-FB haben zusätzlich zu den drei Standard-Anschlüssen eine weitere sog. Feedback-Leitung. Hierbei geht ein Kabel vom internen Potentiometer des Servos zurück und kann als Sensor-Anschluss z.B. beim Arduino verwendet werden. Dies ist hilfreich, wenn man den absoluten Stellwert des Servos auslesen und kennen möchte.
Die einfachen Servo-Motoren, wie z.B. der populäre SG90, besitzt keinen solchen Feedback-Anschluss. Jedoch kann mit recht geringem Aufwand auch solch ein normaler Servo mit einem Feedback-Kanal nachgerüstet werden. Dazu ist lediglich ein weiteres Kabel nötig, welches in etwa denselben Durchmesser wie die anderen Servokabel haben.

Nachrüsten einer analogen Feedback-Leitung bei einem SG90 Servo

Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #1
Schritt #1: Zunächst ritzt man mit einem scharfen Messer (Cutter) den Aufkleber auf beiden Seiten des Servo-Gehäuses an der Stelle ein, wo sich die Naht des unteren Deckels befindet (2). Zusätzlich fixiert man auf beiden Seiten des Gehäuses den oberen Deckel mit Klebeband (1), damit später nach dem Öffnen des Gehäuses nicht das ganze Getriebe herausfällt.
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #2
Schritt #2: Nun entfernt man vorsichtig die vier Schrauben auf der Unterseite des Servo-Gehäuses.
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #3
Schritt #3: Der untere Deckel lässt sich nun abheben und das Gehäuse ist nun offen.
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #4
Schritt #4: Nun hebelt man vorsichtig die Steuerplatine aus dem Gehäuse
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #5
Schritt #5: Nun lokalisiert man den Löt-Anschluss auf der Platine, der mit dem Schleifer (=Gleitkontakt) des internen Potentiometers des Servo verbunden ist. In diesem Fall war es der Mittlere (siehe Pfeil)
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #6
Schritt #6: Hier sieht man die Lötstelle des Kabels , welches mit dem Schleifer des Potentiometers verbunden ist. (Rückseite der Platine)
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #7
Schritt #7: Auf diesen Anschluss lötet man nun zusätzlich ein weiteres Kabel (ohne den Kontakt des bestehenden Kabels zu lösen).
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #8
Schritt #8: Nun kann man die Steuerplatine wieder zurück in die Ausgangslage bringen und das neue Feedback-Kabel aus dem Gehäuse mit einem zusätzlich geschaffenen, kleinen Durchgang führen und das Gehäuse wieder zusammenschrauben.
Servo SG90 mit Feedback-Anschluss nachrüsten - Schritt #9
Schritt #9: Um das neue Feedback-Kabel am Breadboard bzw. direkt auf einem Arduino-Entwicklerboard zu verwenden, empfiehlt sich noch das Anlöten eines Steckkontaktes
Setup auf dem Breadboard
Abb.: Nun kann man das neue Feedback-Kabel mit einem analogen Pin des Arduino (hier: A0) verbinden

Der folgende Sketch kalibriert zunächst einmal die Werte, die vom analogen Feedback bei 0° und 180°-Drehung zurückgeliefert werden. Dann werden verschiedene Stellwinkel an den Servo geschickt. Wenn man die hier verwendete Funktion setMotorAngle() verwendet, muss keine Verzögerung nach dem Stell-Befehl eingebaut werden, denn die Funktion wartet wirklich nur so lange, bis der interne Potentiometer über das Feedback-Kabel meldet, dass der gewünschte Winkel eingestellt wurde. (Die 5000ms-Verzögerungszeiten sind lediglich zur besseren Veranschaulichung)

#include <Servo.h>

#define SERVO_SIGNAL_PIN 9
#define PIN_FEEDBACK     A0

int valMin = 0, valMax = 0;
Servo servoMotor;

void setup()
{
    Serial.begin(9600);
    servoMotor.attach(SERVO_SIGNAL_PIN, 900, 1500);
    pinMode(PIN_FEEDBACK, INPUT);

    Serial.print("Calibrating servo...");
    servoMotor.write(0);
    delay(1000);
    valMin = analogRead(PIN_FEEDBACK);
    servoMotor.write(180);
    delay(1000);
    valMax = analogRead(PIN_FEEDBACK);
    Serial.println("[ok]");
}

void loop()
{
    for (int i = 0; i <= 180; i += 10) {
        setMotorAngle(i);
    }
    for (int i = 180; i >= 0; i -= 10) {
        setMotorAngle(i);
    }
    delay(5000);

    setMotorAngle(0);
    setMotorAngle(135);
    setMotorAngle(45);
    setMotorAngle(180);
    setMotorAngle(90);
    delay(5000);
}

void setMotorAngle(int angle)
{
    servoMotor.write(angle);
    while (abs(angle - map(analogRead(PIN_FEEDBACK), valMin, valMax, 0, 180)) > 5) {
    }
}
zurück