PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schnelle Ansteuerung für 4 Servos ohne "Servo"-Bef



Willa
02.10.2008, 08:37
Hi!
Ich möchte gerne 4 Servos schnell ansteuern (mit vielleicht 100 bis 200 Hz). Im Anhang findet Ihr ein Bild mit dem angedachten Aufbau. Die Framezeit scheint total unkritisch zu sein. Mein Programm funktioniert anscheinend wunderbar, allerdings frage ich mich wie effizient mein Code wohl ist...
Hier mal mein BASCOM Code:


$regfile = "m32def.dat"
$framesize = 32
$swstack = 32
$hwstack = 64
$crystal = 16000000
$baud = 9600

Config Timer0 = Timer , Prescale = 64 'je höher prescale desto resourcenschonender?
On Timer0 Timer_irq
Dim Servo1time As Byte 'servo1 high-time
Dim Servo2time As Byte 'servo2 high-time
Dim Servo3time As Byte 'servo3 high-time
Dim Servo4time As Byte 'servo4 high-time
Dim Kanal As Byte 'Kanal 1-4
Dim I As Byte
Dim Timeraufnull As Bit 'Timer Zurücksetzer


Enable Timer0
Enable Interrupts
Config Portb = Output

Portb.0 = 0 'hier hängt servo1
Portb.1 = 0 'hier hängt servo2
Portb.2 = 0 'hier hängt servo3
Portb.3 = 0 'hier hängt servo4

Kanal = 1
Timeraufnull = 0
Servo1time = 131 'Preload 131 = 2000Hz = 0.5ms pulse
Servo2time = 131
Servo3time = 131
Servo4time = 131



Do
'----- Das ist nur Code um servos zu bewegen --> unwichtig
For I = 0 To 255
'Servo1
Servo1time = I
Waitms 50 'bisschen warten damit servo auch position erreichen kann

'Servo2
If I < 163 Then
Servo2time = I + 20
Else
Servo2time = 131
End If

'Servo3
If I < 170 Then
Servo3time = 301 - I
Else
Servo3time = 150
End If

'Servo4
If I < 140 Then
Servo4time = I
Else
Servo4time = 170
End If
Next I
Loop
End



Timer_irq:

If Kanal = 1 Then
If Portb.0 = 0 Then 'wenn port low...
Timer0 = Servo1time 'dann timer auf gewünschte länge...
Portb.0 = 1 'und port auf high
Else 'portb.0 = 1
If Timeraufnull = 1 Then 'port erst wieder auf low wenn der timer
Portb.0 = 0 'servo1time gelaufen ist UND einmal zurückgesetzt wurde.
Incr Kanal 'das ergibt dann: 0 bis 1ms + 1ms = 1 bis 2ms high
Timeraufnull = 0
Else 'TimerAufNull=0
Timeraufnull = 1
Timer0 = 6 'ergibt 1ms bis zum erneuten überlauf
End If
End If
End If

'und hier das gleiche für die anderen kanäle...
If Kanal = 2 Then
If Portb.1 = 0 Then
Timer0 = Servo2time
Portb.1 = 1
Else
If Timeraufnull = 1 Then
Portb.1 = 0
Incr Kanal
Timeraufnull = 0
Else
Timeraufnull = 1
Timer0 = 6
End If
End If
End If

If Kanal = 3 Then
If Portb.2 = 0 Then
Timer0 = Servo3time
Portb.2 = 1
Else
If Timeraufnull = 1 Then
Portb.2 = 0
Incr Kanal
Timeraufnull = 0
Else
Timeraufnull = 1
Timer0 = 6
End If
End If
End If

If Kanal = 4 Then
If Portb.3 = 0 Then
Timer0 = Servo4time
Portb.3 = 1
Else
If Timeraufnull = 1 Then
Portb.3 = 0
Incr Kanal
Timeraufnull = 0
Else
Timeraufnull = 1
Timer0 = 6
End If
End If
End If




If Kanal > 4 Then
Kanal = 1
End If
Return





Ablauf:
Kanal = 1 und Portb.0 ist aus. Der Preload des Timers wird auf die gewünschte Länge gesetzt , z.b. 152 = 2400Hz = 0,416ms. Der Port wird angeschaltet, der Rest des Timer_irq wird nicht ausgeführt.
Nach 0,416ms wird erneut in Timer_irq gesprungen. Nun wird die Variable "Timeraufnull" auf "1" gesetzt, und der Preload des Timers auf 6 = 1000Hz = 1ms gesetzt. Timer_irq wird wieder verlassen.
Nach 1,416ms wird nochmal ins Timer_irq gesprungen. Jetzt wird Portb.0 ausgeschaltet, die Kanalnummer um eins erhöht und "Timeraufnull" wieder auf 0 gesetzt. Noch während dieses Interrupts wird das ganze für Servo2 eingeleitet usw....


Meine Fragen:

Es gibt 8 Interrupts von Timer0 um alle Servos zu stellen. Ist das gut so, oder nimmt man besser Timer1 mit Prescale=1?? Das ergäbe auch ne gute Auflösung, außerdem nur 4 Interrupts um 4 Servos zu stellen. Aber der Prescale wäre nur 1, und das ist doch ungünstig?

Wie stelle ich Performance des Programms fest? Im Simulator steht was von Cycles und "mS", kann man das benutzen um zu errechnen wie schnell ein Programm läuft?

In Zukunft soll das Programm auf einem ATmega644 mit 20 MHz laufen. Dann ist die maximale Pulslänge den ich mit Prescale=64 erreichen kann 0,8159ms und nicht mehr 1,019 ms. D.h. ich komme nicht mehr auf 2 ms wenn ich zwei Interrupts zusammenzähle, sondern nur noch auf ca. 1,632 ms. Das reicht nicht für den Vollausschlag eines Servos... Was tun? Evtl drei Interrupts zusammenhängen? Das wird aber ungleich komplizierter....

Wenn mir jemand ein bisschen weiterhelfen könnte wäre das fantastisch....!

jeffrey
02.10.2008, 13:46
hi,
also eine servo ansteuerung mit 100hz macht meiner meinung nach keinen sinn, weil ein servo signal 20ms dauert, also kannst du auch nur alle 20 ms eine neue position vorgen, sprich du schaffst maximal 50 hz.
mfg jeffrey

Willa
02.10.2008, 15:51
Hi!
Das ist die allgemein anerkannte Meinung, allerdings stimmt das anscheinend nicht. Wenigstens akzeptieren meine Servos (3 unterschiedliche Hersteller) und meine Fahrtregler alle Signale mit 333 Hz Wiederholrate. Und die Servos machen keinen Unterschied daraus ob bspw. das 1.5ms High-Signal mit 200 Hz oder mit 20 Hz kommt. Ob die Servos dann tatsächlich so schnell stellen lässt sich wohl schwer feststellen, aber ausschließen würde ich es nicht.

Dirk
02.10.2008, 19:36
Wenigstens akzeptieren meine Servos (3 unterschiedliche Hersteller) und meine Fahrtregler alle Signale mit 333 Hz Wiederholrate.
Das "schaffen" meine Servos auch, es bringt aber keinen Vorteil. Selbst wenn man (nach Spezifikation) alle 20ms einen Impuls sendet, können die Servos mit der Positionierung des Stellhebels (mechanisch) nicht nachkommen. Ein Impuls von 1ms, nach 20ms direkt gefolgt von einem 2ms Impuls würde den Servohebel von ganz links nach ganz rechts drehen. Je nach Servo würde diese Stellzeit bis zu 2 Sekunden (!) dauern, obwohl nur 20ms zwischen den Impulsen liegen.

Also: Eine wesentlich höhere Wiederholrate macht keinen Sinn, manche Servos haben aber angeblich "mehr Kraft", wenn man die Wiederholrate etwas anhebt.

Gruß Dirk