Servos und die Nutzung von Timers

Obwohl Arduino UNO nur 5 PWM Ausgänge hat und Mega nur 13, erlaubt servo.h das steuern von bis zu 48 Servos (Mega) und 12 Servos (UNO)

Wenn also mehr Servos attached werden als die Zahl der PWM-Ausgänge, dann wird hier die Software PWM benützt oder wie soll ich das verstehen?

Ich zitiere:

Dies entspricht dem Verfahren im Beispiel zur Software-PWM. Es läuft nun allerdings vollautomatisch im Hintergrund, sodass der Controller nicht damit belastet wird.

Belaste ich den Controller wenn ich zuviele Servos anschließe?

Verstanden habe ich bisher nur, dass immer mehr AnalogWrite-Pins nicht mehr genützt werden können, weil Timers für Servos angepasst werden.

Warum nicht nur ein einziger Timer für alle 48 Servos?

forgoden:
Belaste ich den Controller wenn ich zuviele Servos anschließe?

Meine Vorstellung ist folgendermaßen: Die Timer werden genutzt, um ISRs aufzurufen, die die notwendigen Aktionen zum Schalten der Ausgänge durchführen.

Die Timer laufen im Hintergrund in Teilen des Prozessors, belasten aber den normalen Programmablauf nicht1).

Eine ISR ist ein Stück Programm, das den normalen Programmablauf unterbricht, und genauso viel Zeit benötigt, wie ein normales Stück Programm. Das gilt ab dem ersten Servo, aber je mehr Servos, je mehr Belastung.

forgoden:
Warum nicht nur ein einziger Timer für alle 48 Servos?

Vermutlich ein Performanceproblem. Ändere SERVOS_PER_TIMER und finde es heraus :slight_smile:


Anm.:

  1. Pingelig betrachtet dürfte diese Aussage bei Nutzung von anderen Interrupts nicht stimmen.

Meines Wissens hat der UNO 6 PWM Ausgänge. Kann sein daß in den letzten paar Wochen einer wegrationalisiert worden ist aber ich bezweifle es. Ältere UNOs müßte aber dennoch immernoch 6 PWM Pins haben.

Die Servo-Bibliothek benutzt Timer. Darum funktionieren einige PWM Ausgänge nicht.

https://www.arduino.cc/en/Reference/Servo:
The Servo library supports up to 12 motors on most Arduino boards and 48 on the Arduino Mega. On boards other than the Mega, use of the library disables analogWrite() (PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins. On the Mega, up to 12 servos can be used without interfering with PWM functionality; use of 12 to 23 motors will disable PWM on pins 11 and 12.

Grüße Uwe

Hallo Leute,

ich habe ziemlich lange gebraucht um da irgendwas zu verstehen. Normalerweise ist Arduino dafür gedacht dass man schnell einsteigen kann und dass es eben schön alles funktioniert. Aber mit Servos ist dies nicht der Fall. Ausserdem fehlen da einfach ein paar Informationen habe ich den Eindruck.

Also erst mal ich verlinke das hier:
https://playground.arduino.cc/Code/MegaServo

Dieser Code "MegaServo Hardware Servo library" wurde jetzt längst implementiert in der Version 1.8.6 und funktioniert auch mit UNO allerdings nur bis 12 Servos.

In diesem Link sieht man eine Tabelle, dass die ersten 12 Servos Timer5 benützen. Dadurch kann ich kein AnalogWrite mehr auf 44,45,46 pins von Mega2560 verwenden. Würde ich den dreizehnten Servo attachen so wird ein weiterer Timer (Timer1) manipuliert und 11,12 wären untauglich. Und so weiter. In dieser Tabelle kann man schön sehen wie wann welche Timer belegt werden und wie dadurch immer mehr PWM-Pins untauglich werden. Diese Information fehlt aber auf der offizillen Arduino Servo Seite was für mich ziemlich uninformativ und irreführend ist. Schaue ich im Code von servo.h nach so sind die mit MegaServo Library fast identisch.

Anfänger die diese Tabelle nicht finden werden damit ziemlich große Probleme bekommen. Wenn ich zum Beispiel 18 Servos ansteuern will und gleichzeitig 8 PWM für andere Zwecke, dann muss ich wissen wo ich welche Pins belege.

Auf UNO werden nur PWM-Pins 9, 10 untauglich ?

Idealerweise nimmt man die Pins für die Servos, an denen PWM dann nicht mehr funktioniert.

Für eine größere Anzahl Servos lohnt sich der Einsatz eines entsprechenden Shields oder Moduls. Gleiches gilt auch für PWM Ausgänge. Ob man die auf weitere Arduinos auslagert, oder darauf spezialisierte Chips benutzt, kommt auf den jeweiligen Einsatz an.

Wer einen Arduino über das hinaus ausreizen möchte, was die Standardbibliotheken hergeben, der muß sich zwangsläufig mit den Interna befassen, und ggf. auch Register bitweise programmieren. Und verstehen, was sich mit der Hardware direkt machen läßt, und was nur mit Software zu erledigen ist.

forgoden:
Warum nicht nur ein einziger Timer für alle 48 Servos?

Dazu hätte ich noch eine Idee: Jedes Servosingnal hat eine übliche Periodenlänge von 20 ms. Der HIGH-Impuls liegt irgendwo zwischen 500 und 1500 µs. Damit passen ca. 12 Impulse in eine Periodenlänge.

Der Timer setzt erst den Impuls des ersten Servos, dann den des zweiten, ... dann den des zwölften, dann wieder den des ersten.

Theoretisch könnte ich mir auch vorstellen, 48 Servos mit einem Timer zu steuern, wird dann aber komplexer. Und dann stellt sich auch die Frage, ob nicht spezielle Hardware effizienter ist.

Di irrst.
Die Signallänge ist normalerweise zwischen 1000 und 2000 us, Servomitte bei 1500 us. kann aber bei neueren Servos auch durchaus von 500 bis 2500 us gehen.
Die 20 ms Signalabstand war einmal, inzwischen ist es vielen Servos egal.

Das was du meinst, mit mehreren Signalen für verschiedene Servos innerhalb einer Periodenlänge, das nennt sich PPM und wird heute aus Gründen der Kompatibilität noch viel im Modellbau verwendet.

ElEspanol:
Di irrst.

Das halte ich für möglich :slight_smile:

ElEspanol:
Die Signallänge ist normalerweise zwischen 1000 und 2000 us, Servomitte bei 1500 us. kann aber bei neueren Servos auch durchaus von 500 bis 2500 us gehen.

IDE 1.8.6 (also recht neu) liefert mir mit Servo.h mit drei Servos (Zeiten mit BitScope gemessen):

0 Grad = 0,531 ms
90 Grad = 1,47 ms
180 Grad = 2,38 ms
Periodendauer 20 ms (bis zu acht Servos, danach so lang wie nötig)

#include <Servo.h>

Servo myservo01;
Servo myservo02;
Servo myservo03;
Servo myservo04;
Servo myservo05;
Servo myservo06;
Servo myservo07;
Servo myservo08;
Servo myservo09;
Servo myservo10;
Servo myservo11;
Servo myservo12;

void setup() {
  myservo01.attach(31);
  myservo02.attach(32);
  myservo03.attach(33);
  myservo04.attach(34);
  myservo05.attach(35);
  myservo06.attach(36);
  myservo07.attach(37);
  myservo08.attach(38);
  myservo09.attach(39);
  myservo10.attach(40);
  myservo11.attach(41);
  myservo12.attach(42);
}

void loop() {
  bewege(0);
  delay(1000);
  bewege(90);
  delay(1000);
  bewege(180);
  delay(1000);
}
void bewege(int winkel) {
  myservo01.write(winkel);
  myservo02.write(winkel);
  myservo03.write(winkel);
  myservo04.write(winkel);
  myservo05.write(winkel);
  myservo06.write(winkel);
  myservo07.write(winkel);
  myservo08.write(winkel);
  myservo09.write(winkel);
  myservo10.write(winkel);
  myservo11.write(winkel);
  myservo12.write(winkel);
}

ElEspanol:
Das was du meinst, mit mehreren Signalen für verschiedene Servos innerhalb einer Periodenlänge, das nennt sich PPM …

Nö, der Unterschied ist mir bekannt.

Die Frage, warum es nun gerade zwölf Servos pro Timer sind, bleibt damit leider unbeantwortet :frowning:

0 Grad = 0,531 ms
90 Grad = 1,47 ms
180 Grad = 2,38 ms

Na, das deckt sich ja fast mit meinen Angaben. Mittelstellung (90º) ist bei den meisten Marken auf 1.500 us definiert, eine hat 1.520 us oder so.
Normale Servos reagieren nur von um die 900 bis max. 2.100 us.

Die 20ms Periodendauer ist aus Kompatibilität zu alten Servos und für gewöhnlich auch ausreichend. Es gibt jedoch Ausnahmen, wo kürzere Periodendauer vorteilhafter ist, z.B. bei schnellen Heli Heckservos.

Warum die Lib jetzt gerade 12 Servos macht, hab ich auch keine Ahnung. Vielleicht angelsächsischer Programmierer, der noch in Dutzend denkt :slight_smile:

Hat aber mit Sicherheit nichts mit der Periodendauer von 20 ms oder der Framelength von PPM (i.d.R. 20ms - 28ms) zu tun.

ElEspanol:
Hat aber mit Sicherheit nichts mit der Periodendauer von 20 ms oder der Framelength von PPM (i.d.R. 20ms - 28ms) zu tun.

War halt so eine Idee, die mir gefiel, aber nicht jede Idee stimmt.

ElEspanol:
Vielleicht angelsächsischer Programmierer, der noch in Dutzend denkt :slight_smile:

Die Erklärung nehme ich, bis jemand mit einer besseren um die Ecke kommt :smiley: