Hallo ich würde gerne n bißchen Kritik an meinenm Programm und evtl. Hilfestellung von euch bekommen. Ich möchte über ein poti einen Servo ansteuern und habe das jetz erstmal wie folgt gelöst oder versucht bin absoluter Anfänger also seid bitte nicht zu hart :-) Ist das so richtig und stimmen meine berechnungen ? Vielen Dank !
Jetzt sind die Leute schon zu blöd eine Assemblerdatei mit der Endung .asm zu speichern.
Du machst den klassischen Anfängerfehler aller Servoansteuerer. Du klebst an den 20ms. Dadurch ergeben sich für die Servo-PWM bei dir nur noch 9 mögliche Servopositionen, weil du nur 9 gültige Werte für die PWM hast. Vergiss die 20ms! Sieh zu, dass du den Einstellbereich der PWM für die 1 bis 2ms vernünftig ausnutzen kannst. Und was dann noch übrig bleibt - das Servo ist damit zufrieden. Wenn du es so hindrehen kannst dass zb du die 1 bis 2 ms mit 64 Werten abbilden kannst, dann kannst du den ADC Wert in den OCR Wert umrechnen und bist nicht mehr auf lediglich 3 Servowerte fixiert. Dein Servo bewegt sich dann einigermassen flüssig mit dem Poti mit anstelle bei nur 3 Servopositionen 'einzurasten'. Modellbauservo Ansteuerung
Karl heinz Buchegger schrieb: > Vergiss die 20ms! Sieh zu, dass du den Einstellbereich der PWM für die 1 > bis 2ms vernünftig ausnutzen kannst. Und was dann noch übrig bleibt - > das Servo ist damit zufrieden. Leider ist das in der Allgemeinheit nicht richtig. Die meisten Servos mögen keine Pausenzeit unter ca.15ms. Selbst bei den neuen Fernsteuerungen, die mit sehr geringer Pausenzeit < 10ms arbeiten, kann man auf 20ms umstellen, damit alte Servos verwendet werden können. Ich habe mit meinen Weichenantrieben ca. 50 Servotypen getestet, und nur ganz wenige konnten Pausenzeiten <10ms.
Eigentlich doch kein Problem: Man nehme 2 Timer, einen 16-Bit-Timer mit PWM und einen anderen 8-Bit-Timer für die Wiederholung. Das PWM wird auf rund 1ms bis rund 2ms limitiert (mit einer Auflösung von mindestens 8Bit) und im Compare-Interrupt wird der PWM-Timer dann abgeschaltet und der Wiederholtimer gestartet. Dieser läuft mit einem Overflow oder Compare auf 20ms. Ist der 2. Timer abgelaufen, wird in dessen Interrupt der 2. Timer gestoppt und der PWM-Timer wieder angestossen. Somit hat man eine komplett in Hardware laufende Ausgabe und muss lediglich noch die OCR-Register für das PWM updaten. Wenn man 2 oder mehr PWM-Ausgänge an dem 16-Bit-Timer hat, kann man die entsprechende Zahl an Servos fast komplett in Hardware steuern. Die CPU kann dann andere Peripherie (ADC, UART) bedienen oder Werte auf Display oder PC ausgeben.
Wenn man einen 16-Bit-Timer hat, lässt man den mit ca. 20ms Zyklus laufen. In meinen Weichenatrieben habe ich den Timer einfach bis 20000 zählen lassen. Mit den Compare-Registern hat man dann eine PWM mit 1µs Auflösung. Das sind dann, bezogen auf den Impuls, 0,1%. Diese Auflösung wird von keinem servo erreicht, und der Totbereich eines Servos liegt typisch bei >2µs. In einem ATMega8 kann man dann ohne jeden Interrupt o.ä. 2 Servos steuern. Die Software setzt einfach nur die Compare-Register.
Erstmal vielen Dank dann muss ich mich mal noch dahintersetzen, momentan habe ich allerdings nur einen Attiny13 der hat nur 8bit Timer ? ist es mit dem 13er überhaupt möglich Servos vernünftig anzusteuern oder kann ich das mit dem eher vergessen ?
Es geht auch mit 8-Bit Timern. Allerdings darfst du dann nicht mehr auf Hardware PWM setzen, sondern musst dem Teil mit einer ISR etwas unter die Arme greifen und die Pins in Software ansteuern. Aber ansonsten ist das kein Problem. Ich steuere mit einem 8-Bit Timer 12 Servos (allerdings nicht mit einem Tiny, der hätte nicht genug Pins).
Ich hab mal ein wenig gerechnet. Mit den 9.6Mhz geht sichs nicht besonders gut aus. 4.8Mhz wären besser Bei 4.8Mhz Taktfrequenz und einem Vorteiler von 64 hast du eine Durchlauffrequenz des Timers von 0 bis 256 mit 292.9 Hz Das sind 3.4 ms Das heisst um Zeiten zwischen 1 und 2 ms einzustellen, bewegt sich der Comparewert zwischen 75 und 150. Das wären dann immerhin 75 Positionen, die das Servo anfahren kann. Sollte eigentlich reichen. Meine Strategie wäre deshalb: Ich klemm mich an den Overflow Interrupt Ich zähle die Aufrufe der ISR mit. Bei jedem 5.ten Aufruf mache ich: Den Servo-Pin auf 1 schalten Ins Compare Register den Vergleichswert für die Zeit laden Sicherheitshalber das Interrupt Flag für den Compare Interrupt löschen Den Compare Interrupt einschalten Im Compare Interrupt Den Pin wieder auf 0 setzen den Compare Interrupt ausschalten. Dadurch ergibt sich automatisch ein Timing, dass einen Puls mit der gewünschten Länge erzeugt und eine Pause hinten nach, die sich im Bereich von ca 17ms bewegt. Und damit sollte jedes Servo zufrieden sein. Der Trick besteht darin, dass der Pulsanfang vom Overflow Interrupt erzeugt wird und das Pulsende vom Compare Interrupt. Der Overflow Interrupt richtet gleichzeitig auch alles so ein, dass der Compare Interrupt zum gewünschten Zeitpunkt nach dem Pulsanfang aufgerufen wird.
also software PWM wie im Beispiel: http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM mit den verschiedenen Helligkeitswerten, nur anstatt den Werten für versch. Helligkeit, setze ich dafür meine verschiedenen positionen des Servos verstehe ich das so richtig ? und wie im Beispiel der PWMcount ist dann meine (20 oder 10ms) Pause ?
Man könnte auch (etwas einfacher), nur mit dem Compare Match (dem OCR0A Register) arbeiten, indem man den CTC Modus benutzt. Den stellt man so ein, dass der CTC die gewünschte Pulszeit ergibt. Zusätzlich benötigt man noch einen Softwarezähler, der die Anzahl der ISR Aufrufe mitzählt. Ist der zähler auf 0, so wird der Ausgangspin auf 1 gesetzt Ist er auf 1, so wird der Pin wieder abgeschaltet Hat der Zähler 10 erreicht, so wird der Zähler wieder auf 0 zurück gesetzt. Auch das ergibt ein Timing, mit dem ein Servo etwas anfangen kann.
Mit dem ATTiny geht es sicher auch, bei meiner PIC-Version hatte ich auch nur einen 8-Bit-Timer. Wenn der Prozessor nichts anderes zu tun hat, kann man das per Software machen. Wenn allerdings, wie bei meinen Weichenantrieben, alle 50µs noch ein Interrupt kommt, kann man alle Softwarelösungen vergessen, denn ein Jitter von > 4µs bringt das Servo zum Brummen oder sogar Zappeln. Wenn Du es also einfach und sicher haben willst, nimm so etwas wie den ATMega8 und mache es in Hardware.
Michi K------ schrieb: > also software PWM wie im Beispiel: > http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM > > mit den verschiedenen Helligkeitswerten, nur anstatt den Werten für > versch. Helligkeit, setze ich dafür meine verschiedenen positionen des > Servos verstehe ich das so richtig ? Nicht ganz. > und wie im Beispiel der PWMcount ist dann meine (20 oder 10ms) Pause ? Nicht wirklich. Das Prinzip ist ähnlich, aber doch ganz anders.
Kurt Harders schrieb: > Jitter von > 4µs das bedeutet bei 4.8Mhz eine Verzögerung von 20 Takten. Die hat er nie (wenn die Anwendung so bleibt, wie sie sich im Moment abzeichnet)
Wichtig ist nur, dass man die Servo-Pins direkt nach dem Einsprung in die ISR beeinflusst und bedingte Sprünge, die zwischendrin unbedingt sein müssen, mit "NOP" Instruktionen ausgleicht, so dass sich immer gleiche Codelaufzeiten ergeben, wenn das Timing kritisch ist. Einen Interrupt-Jitter von 0...3 Takten hat man ohnehin immer.
Knut Ballhause schrieb: > Wichtig ist nur, dass man die Servo-Pins direkt nach dem Einsprung in > die ISR beeinflusst und bedingte Sprünge, die zwischendrin unbedingt > sein müssen, mit "NOP" Instruktionen ausgleicht, so dass sich immer > gleiche Codelaufzeiten ergeben, wenn das Timing kritisch ist. Einen > Interrupt-Jitter von 0...3 Takten hat man ohnehin immer. Hattest du bei deiner Lösung damit Probleme? Meine Erfahrung ist eher: die Unterschiede sind so minimal, das lohnt nicht, sich da groß den Kopf zu zerbrechen. Ob ein Puls mal 1/10 µs länger oder kürzer ausfällt, lässt das Servo völlig kalt. So genau sind die Potis (als mechanisches Bauteil) in den Servos gar nicht.
Du hast recht, aber es sind nicht die Potis, sondern die eingebauten Elektroniken haben ca. 4µs Totzeit. Bei Digitalservos kann man diese Totzeit einstellen, bekommt dann aber eventuell massives Brummen des Servos mit sehr hoher Stromaufnahme.
Ich hab mich mal an den Assebmler geklemmt benutzt hab ich die Variante: Alles im Compare Interrupt mit CTC. Leider hab ich keinen Tiny13 da, sondern nur einen Mega16. Daher kann ich den auch nicht mit 4.8Mhz laufen lassen, sondern nur mit 4Mhz :-) Die Timer Einstellung sollte aber sonst identisch sein. Vorteiler: 64 Das Servo wird verstellt, indem man an OCR0 neue Werte zuweist. Bei dir müssten das rein rechnerisch Werte zwischen 75 und 150 sein. Die im Programm momentan verwendeten 100, sind bei mir in etwa Mittelstellung meiner Servos, aber ich hab ja auch 4Mhz und nicht 4.8 Ach ja, ich erzeuge an PortA, Pin 7 das Signal. Hat keine besonderen Gründe, ausser dass ich da leicht mit dem Servokabel rankomme.
1 | .include "m16def.inc" |
2 | |
3 | .equ XTAL = 4000000 |
4 | |
5 | rjmp init |
6 | |
7 | .org OC0addr |
8 | rjmp Compare_vect |
9 | |
10 | init: |
11 | ldi r16, HIGH(RAMEND) ; Stackpointer initialisieren |
12 | out SPH, r16 |
13 | ldi r16, LOW(RAMEND) |
14 | out SPL, r16 |
15 | |
16 | ldi r16, 0x80 |
17 | out DDRA, r16 ; Servo Ausgangspin -> Output |
18 | |
19 | ldi r17, 0 ; Software-Zähler |
20 | |
21 | ldi r16, 100 |
22 | out OCR0, r16 ; OCR0 ist der Servowert |
23 | |
24 | ldi r16, 1<<OCIE0 |
25 | out TIMSK, r16 |
26 | |
27 | ldi r16, (1<<WGM01) | (1<<CS01) | (1<<CS00) ; CTC, Prescaler: 64 |
28 | out TCCR0, r16 |
29 | |
30 | sei |
31 | |
32 | main: |
33 | rjmp main |
34 | |
35 | Compare_vect: |
36 | in r18, SREG |
37 | inc r17 |
38 | cpi r17, 1 |
39 | breq PulsOn |
40 | cpi r17, 2 |
41 | breq PulsOff |
42 | cpi r17, 10 |
43 | brne return |
44 | ldi r17, 0 |
45 | return: out SREG, r18 |
46 | reti |
47 | |
48 | PulsOn: sbi PORTA, 7 |
49 | rjmp return |
50 | |
51 | PulsOff: cbi PORTA, 7 |
52 | rjmp return |
Da der Wertebereich damit so ca 75 Werte umfasst, würde es sich anbieten, den Wert vom ADC (den du ja mittels ADLAR schon auf 0..255 eingeschränklt hast) noch durch 4 zu dividieren (einfach um 2 Bit nach rechts schieben), noch 75 dazuzählen und ab damit ins OCR Register. Das ergibt dann 64 Servo Stellungen, die mit dem Poti abgefahren werden können.
Yep. Funktioniert bei mir tadellos
1 | .... |
2 | |
3 | ldi r16, (1<<WGM21) | (1<<CS22) ; CTC, Prescaler: 64 |
4 | out TCCR0, r16 |
5 | |
6 | ldi r16, (1<<ADLAR)| (1<<REFS0) | (1<<MUX1) | (1<<MUX0) |
7 | out ADMUX, r16 |
8 | ldi r16, (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0) |
9 | out ADCSRA, r16 |
10 | |
11 | sei |
12 | |
13 | main: |
14 | sbi ADCSRA, ADSC |
15 | adc_wait: sbic ADCSRA, ADSC |
16 | rjmp adc_wait |
17 | |
18 | in r16, adch |
19 | lsr r16 ; durch 4 |
20 | lsr r16 |
21 | subi r16, -75 ; +75 addieren! |
22 | |
23 | out OCR0, r16 |
24 | |
25 | rjmp main |
26 | |
27 | ... |
Karl heinz Buchegger schrieb: > Da der Wertebereich damit so ca 75 Werte umfasst Bei 75 Schritten auf 90° Drehwinkel sind das 1,2° pro Schritt. Das ist sehr grob. Eine Auflösung von 512 Schritten sollte es für anspruchsvollere Bewegungen schon sein. Die Totzeit macht es schon schwer genug, langsame Bewegungen umzusetzen.
Kurt Harders schrieb: > Karl heinz Buchegger schrieb: >> Da der Wertebereich damit so ca 75 Werte umfasst > > Bei 75 Schritten auf 90° Drehwinkel sind das 1,2° pro Schritt. Das ist > sehr grob. Zugegeben. Ich seh bei meinen Servos deutlich den Schritt (auch wenn es dann in Natura weit weniger dramatisch aussieht als es sich hier anhört) Allerdings ist es mit den vorhandenen Mitteln nicht mehr so einfach, diese Auflösung zu erreichen. Machbar ist es, keine Frage. Aber lass den Fragesteller erst mal mit Timern und den Möglichkeiten vertraut werden und wie man mit ISR und Softwarezählern längere Zeiträume bei gleichzeitig hoher zeitlicher Auflösung abzählt. Gegenüber seinen ursprünglich 9 Servostellungen sind 75 schon recht viel :-)
Karl heinz Buchegger schrieb: > Knut Ballhause schrieb: >> Wichtig ist nur, dass man die Servo-Pins direkt nach dem Einsprung in >> die ISR beeinflusst und bedingte Sprünge, die zwischendrin unbedingt >> sein müssen, mit "NOP" Instruktionen ausgleicht, so dass sich immer >> gleiche Codelaufzeiten ergeben, wenn das Timing kritisch ist. Einen >> Interrupt-Jitter von 0...3 Takten hat man ohnehin immer. > > Hattest du bei deiner Lösung damit Probleme? > Meine Erfahrung ist eher: die Unterschiede sind so minimal, das lohnt > nicht, sich da groß den Kopf zu zerbrechen. Ob ein Puls mal 1/10 µs > länger oder kürzer ausfällt, lässt das Servo völlig kalt. So genau sind > die Potis (als mechanisches Bauteil) in den Servos gar nicht. Jitter kann sich im ungünstigsten Fall addieren. Bei einem mit 4Mhz-Controller kann der Jitter dann im Bereich von 2µs liegen, bei einer Software-Pin-Ansteuerung über Interrupt-Service. Ausserdem darf in dem Fall nur ein einziger Interrupt zu einer Zeit erlaubt sein, da sonst der Interrupt mit dem PWM auf einen anderen warten muss. Hier kann der Jitter dann so groß werden, dass das ganze Signal zusammenbricht. Bei einer Hardware-Steuerung des PWM über einen Timer und dessen OCR-Register ist der Jitter der steigenden PWM-Flanke praktisch "Null" und da das OCR mit dem Timerumlauf übernommen wird, gilt dies auch für die fallende Flanke. Am Oszi steht solch ein Signal wie eine 1 ;-). Software-PWM für Servos macht also nur auf einem Controller Sinn, der recht schnell getaktet ist und wo das Addieren von Interrupt-Reaktionszeit plus Portausgabe dann nicht mehr in´s Gewicht fällt.
Vielen vielen Dank für die Antworten ich muss jetz wenn ich wieder ein bißchen Zeit habe mich nochmal dransetzen und mir alles genau durchlesen und dann kommen bestimmt noch viele Fragen :-) wünsche jetz aber erst mal nen guten Rutsch !
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.