Forum: Mikrocontroller und Digitale Elektronik Mehrere Servos mit OCR1A


von peka (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich baue einen I2C-gesteuerten Servocontroller mit einem tiny2313.
Um die PWM mit dem µC zu erzeugen, benutze ich Timer1 mit Prescaler 8 
(F_CPU=8MHz).
OCR1B=5000 um alle 5ms die Pegel für die Servos auf High zu setzen (sind 
Digitalservos, die können die 200Hz)

OCR1A = 800-2200 um die Leitung nach dem Impuls wieder auf Low zu legen, 
aber:
weil ich mehr als ein Servo steuern will, und zwar mit einem Timer, 
sortiere ich die Servoimpulse von kurz nach lang und stelle bei jedem 
Interrupt für OCR1A den nächst größeren Wert ein.

Beispiel:

Servo 1: 1500, Servo 2: 1000, Servo 3: 1600

...
mit OCR1B-Interrupt wird alles auf High gezogen,
1000µs später: OCR1A-Interrupt -> Servo2-Line low, OCR1A auf 1500 
stellen
500µs später: OCR1A-Interrupt -> Servo1-Line low, OCR1A auf 1600 stellen
100µs später: OCR1A-Interrupt -> Servo1-Line low, OCR1A auf 1000 stellen
...
(und wieder von vorne)


Soweit funktioniert das ganz gut. Die Servostellungen sollen natürlich 
verändert werden können. Ich hab sie also in ein Array gepackt und das 
der größe nach sortiert. Eine Index-Variable speichert, welcher 
servo-wert gerade eingestellt wurde und wird bei jedem OCR1A-Interrupt 
hochgezählt. In der ISR wird dann überprüft, zu welchem servo-Wert das 
aktuelle OCR1A passt und die entsprechende Datenleitung geschaltet.

Aber jetzt das Problem: ich habe das gefühl, dass der Zugriff auf das 
volatile uint16_t Array so langsam ist, dass die ISR verzögert wird. 
Denn das Servo "rauscht" in seiner Position sehr stark! Das zittert sehr 
munter in einem Bereich von umgerechnet so um die 500 µs.

Wenn ich statt ein Array zu benutzen, einfach die Servowerte unsortiert 
der Reihe nach einstelle (OCR1A==Servowert1, also muss jetzt Servowert2 
eingestellt werden, usw.), funktioniert das ansich ohne Probleme. 
Nachteil: die reaktionszeit des Systems ver-n-facht sich mit der Anzahl 
der Servos, weil das volle 5ms-Fenster für jeden Servo durchlaufen wird.

Meine Frage ist jetzt: Was mache ich falsch, dass der Zugriff auf das 
Array so lange dauert? Oder habe ich ein anderes Problem übersehen?

Ich hoffe, ihr könnt mir helfen!
Gruß
peka

von Peter B. (pbuenger)


Lesenswert?

Hallo peka,

mit Deiner Methode kriegst Du aber arge Probleme, sobald zwei 
Servopositionen sehr dicht beieinander sind. Beispielsweise hat ein 
Servo 1500, das andere 1505. Dann stellst Du im 1500er Interrupt den OCR 
auf 1505, der Timer ist dann aber möglicherweise schon viel weiter. Das 
Ergebnis wäre ein 5500ms-Puls am zweiten Servo.

Peter

von peka (Gast)


Lesenswert?

Hallo Peter,

da hast Du recht.
Auch wenn zweimal der selbe Wert vorhanden ist, gibts eine 5ms pause...

Ich hatte angenommen, dass die paar befehle nicht so lange brauchen. Das 
wäre natürlich nur der Fall, wenn weniger als 8 Taktzyklen benötigt 
werden (Timer-Prescaler 8). Aber das schaff ich wohl nicht.

von Jörg H. (dr_coolgood)


Lesenswert?

Es gab hier mal einen genialen Ansatz mit einem Schieberegister.
Das Schieberegister kann intern oder extern in HW realisiert sein.
Die Such' macht klug.

von Karl H. (kbuchegg)


Lesenswert?

Mehrere Servos macht man anders.
Jedes Servo kriegt seine Pause nach dem Puls, während gerade ein Puls 
für ein anderes Servo abläuft. D.h. du brauchst nicht einen kompletten 
Pulszyklus inklusive Pause danach abwarten, ehe du mit dem Puls für das 
nächste Servo beginnst.


Also nicht

             |            |
             | Servozyklus|
             | Puls + Pause
             |            |

             +---+                       +---
             |   |                       |
  Servo 1  --+   +-----------------------+

                          +---+
                          |   |
  Servo 2  ---------------+   +-----------


Sondern
              +---+       +---+
              |   |       |   |
  Servo 1  ---+   +-------+   +-----

                  +---+       +---+
                  |   |       |   |
  Servo 2  -------+   +-------+   +--

                      +---+       +---
                      |   |       |
  Servo 3  -----------+   +-------+


D.h. du generierst aktiv gar keine Pausen. Die Pausen nach dem Puls 
ergeben sich dadurch, dass in dieser Zeit die Pulse für die anderen 
Servos erzeugt werden.

Modellbauservo Ansteurung
ganz unten, der letzte Abschnitt

von peka (Gast)


Lesenswert?

Aha, das mit dem Schieberegister klingt sehr gut, danke für den Tipp!
Dass man die Servos nacheinander ansteuert ist natürlich ein Nachteil, 
außer man benutzt mehrere Schieberegister parallel, muss ich mir mal 
ansehen.
Von den 74HC164 hab ich auch noch einige da :)

von Berichtiger (Gast)


Lesenswert?

Der obige Link funktioniert bei mir nicht : Ansteuerung
                                                    ^
http://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung

von Josef (Gast)


Lesenswert?

Hallo Peka,
weder du noch Peter haben Recht.

Gerade bei digitalen Servos ist es ein Vorteil, wenn die Ansteuerung 
gleichzeitig erfolgt. Streng genommen sollte die fallende Flanke genau 
gleichzeitig sein, damit alle Servos 100% parallel laufen. Die guten 
Empfänger können genau das.

Mit dem tiny müsste es auch gehen.
1. Du sortierst alle Werte
2. du fasst alle gleichen zusammen
3. du berechnest den Abstand der verbliebenen
3. wenn der Abstand zwischen den verbliebenen Impulsen zu klein ist um 
den Interrupt zu verlassen und wieder einzutreten, verlässt du den 
Interrupt nicht und machst mit NOPs die Verzögerung.

Falls Interesse besteht, kann ich den Code für einen ATMEGA beisteuern.
(Auflösung 1µs, Jitter < 0,5µs, möglich müssten sogar 16 Kanäle 
gleichzeitig sein, bei mir sind es 2 * 4)

Gruß
Josef

von Karl H. (kbuchegg)


Lesenswert?

Josef schrieb:

> Gerade bei digitalen Servos ist es ein Vorteil, wenn die Ansteuerung
> gleichzeitig erfolgt. Streng genommen sollte die fallende Flanke genau
> gleichzeitig sein, damit alle Servos 100% parallel laufen. Die guten
> Empfänger können genau das.

Wow.
Du kannst das erkennen, wenn ein Servo ein paar Millisekunden später zu 
laufen anfängt? Und deine Anlenkungen sind alle absolut und zu 100% 
spielfrei? Und deine Gestänge zeigen keinerlei Durchbiegung? Deine 
Scharniere haben 0 Spiel in den Lagern? Deine Gabelköpfe sind sowohl 
leichtgängig als auch spielfrei, genauso wie deine Kugelköpfe. Und 
natürlich sind alle Ruderhörner bis auf den 10-tausendstel Millimeter 
gleich lang und sitzen mit derselben Präzision von der Drehachse gleich 
weit entfernt.
Respekt!

Also ich benutze den Code aus dem Artikel für 12 Servos und ich kann mit 
freiem Auge absolut nicht erkennen, dass ein Servo etwas später zu 
laufen anfangen würde. Scheint so, als ob das für meinen Hexabot nicht 
wirklich wichtig wäre.

Nur damit wir uns richtig verstehen: Ich sag nicht, dass schlampig 
arbeiten in Ordnung ist. Aber man muss auch wissen, ab wann noch mehr 
Genauigkeit nur noch Mehraufwand bedeutet und in der Praxis einfach 
nichts mehr bringt.

von Josef (Gast)


Lesenswert?

Natürlich kann ich das nicht erkennen, aber ich kann es messen. Und ob 
es Sinn in der Praxis macht, muss jeder selbst entscheiden. Es gibt 
genug Leute die genau deshalb manche Fernsteuerung bevorzugen. Genauso 
wenig wie grundsätzlich digitale Servos besser sind. Es geht wie immer 
um Aufwand und Nutzen.
Aber es ist technisch möglich gleichzeitig die Signale auszugeben und 
genau darum geht es in diesem Fred

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.