Hallo, für meinen ersten Servotest hab ich ein kleines Programm geschrieben, welches folgenden Teil in einer ISR alle 20ms ausführt: [asm] sbi PORTA, 0 ldi XL, lo8(n) 1 ldi XH, hi8(n) 1 L1: sbiw XL, 1 2 brne L1 2/1 nop 1 cbi PORTA, 0 1 [/asm] Die Anzahl der Takte zwischen sbi und cbi sind also: 7+4*(n-1) Mit F=7372800Hz lassen sich die Zeiten für Links-Rechts-Anschlag berechnen: n = (Zeit*F-7)/4+1 Leider hab ich zwischen den errechneten Werten und den tatsächlichen Werten (Ausprobieren) große Abweichungen. 1ms ~ 1842 (gerechnet) 1200 (Ausprobieren) 1,5ms ~ 2764 (gerechnet) 2ms ~ 3686 (gerechnet) 4000 (Ausprobieren) Woran kann das liegen? Grüße, Freakazoid
Hallo, Poste mal das gesamte Programm.. mit dem Fetzen kann man nix anfanngen
??? Generell versteh ich Dein Anliegen, aber die ISR ist nicht viel länger ;-) Wenn aber das 'Brimborium' drumherum von Interesse ist, bitte: #define __SFR_OFFSET 0 #include "avr/io.h" .global main .global TIMER0_COMP_vect #define Crystal 7372800 main: ldi 18, 0xff // PortA -> Output out _SFR_IO_ADDR(DDRA), 18 ldi 18, (1<<WGM01)|(1<<CS02)|(1<<CS00) // CTC, Prescale 1024 -> 7200 Zählererhöhungen/Sek out _SFR_IO_ADDR(TCCR0), 18 ldi 18, 144-1 out _SFR_IO_ADDR(OCR0), 18 ldi 18, (1<<OCIE0) out _SFR_IO_ADDR(TIMSK), 18 sei L0: rjmp L0 TIMER0_COMP_vect: push 18 in 18, _SFR_IO_ADDR(SREG) push 18 sbi PORTA, 0 ldi XL, lo8(1500) ldi XH, hi8(1500) L1: sbiw XL, 1 brne L1 nop cbi PORTA, 0 pop 18 out _SFR_IO_ADDR(SREG), 18 pop 18 reti Denke aber trotzdem, daß der Fehler im 'Fetzen' liegt. Die ISR wird alle 20ms aufgerufen. Grüße, Freakazoid
7372800Hz / 1024(Pre) / 144(OCR) macht 50Takte / Sekunde also alle 20mS ein Interrupt, wenn ich mich nicht verguckt habe Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn Nullstellung Servo) ausloessen lassen, und dann toggeln in asm zB. mit eor wert, bit Wie lannge die ISR braucht ist fuer dich unwichtig. Mit dem Wert in OCR0 kannst du dann die Position bestimmen
> 7372800Hz / 1024(Pre) / 144(OCR) macht 50Takte / Sekunde also > alle 20mS ein Interrupt, wenn ich mich nicht verguckt habe Das ist Richtig und soll auch so sein (Zykluszeit) > Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn > Nullstellung Servo) ausloessen lassen, und dann toggeln > in asm zB. mit eor wert, bit Hm. Dann ist die Zykluszeit aber 4ms (2ms low, 2ms high). Meines Wissens nach - und ich denke genau da ist das Problem g - ist die Zykluszeit 20ms mit einer variablen Pulsdauer (High-Phase) von 1...2 ms, oder? > Wie lannge die ISR braucht ist fuer dich unwichtig. Ja. Sonst hätte ich auch keine 'Warteschleife' in der ISR gebastelt. Ich weiß, daß das böse ist. Ist mein erster Versuch mit Servos und ich wollte das Programm so einfach wie möglich gestalten. Grüße, Freakazoid
Noch was: > Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn > Nullstellung Servo) ausloessen lassen Wieso hast Du 'Nullstellung' dazugeschrieben? Ist es nicht der Sinn eines Servos eine Stellung abhängig von der Impulsdauer anzufahren? Dann sollte die Startstellung doch irrelevant sein, oder? Grüße, Freakazoid
Schau mal.. der Timer generiert alle 1mS +/- 0,5mS einen INT.. du Springst in die INT rein (Timer MUSS im ctc mode laufen) und kannst sogar den Timer über PWM den Portpin toggeln lassen.. Nur muss der Timer eben mit der doppelten frequenz laufen. (Tiny 45) ldi wr0, (1<<WGM01) out TCCR0A, wr0 ldi wr0, (1<<CS02 | 1<<CS00) out TCCR0B, wr0 ldi wr0, (39) out OCR0A, wr0
> tatsächlichen Werten (Ausprobieren) große Abweichungen. > > 1ms ~ 1842 (gerechnet) 1200 (Ausprobieren) > 1,5ms ~ 2764 (gerechnet) > 2ms ~ 3686 (gerechnet) 4000 (Ausprobieren) Hast du die Zeiten gemessen oder einfach das Servo angehängt und solange probiert bis du am Linksanschlag warst? Die meisten Servos kommen auch mit Pulsen kürzer als 1 ms bzw. länger als 2 ms ohne Probleme zurecht.
? 1. Version: > Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn > Nullstellung Servo) ausloessen lassen, 2. Version: > der Timer generiert alle 1mS +/- 0,5mS einen INT.. Das verwirrt mich ;-) > du Springst in die INT rein (Timer MUSS im ctc mode laufen) und > kannst sogar den Timer über PWM den Portpin toggeln lassen.. > Nur muss der Timer eben mit der doppelten frequenz laufen. Das ist klar. ABER: Warum INTs in so kurzen Abständen? Ich hab ja nichts gegen Deinen Vorschlag, aber WARUM funktioniert das Programm oben nicht, wenn der INT alle 20ms aufgerufen wird? Ich weiß, daß der AVR mir mit der PWM viel abnehmen kann. Das ist aber nicht der Punkt. Nachdem was ich gelesen habe sollte es funktionieren. Tut es ja auch, aber eben nicht so exakt wie berechnet. Das ist mein Problem ;-( Halt mich bitte nicht für stur (ich bin Dir sogar dankbar für die Tipps), aber ich würde gerne erstmal in dem simplen Programm oben den Fehler finden, bevor ich 1000 andere Kniffe ausprobiere. Grüße, Freakazoid
> Hast du die Zeiten gemessen oder einfach das Servo > angehängt und solange probiert bis du am Linksanschlag > warst? Letzteres. > Die meisten Servos kommen auch mit Pulsen kürzer > als 1 ms bzw. länger als 2 ms ohne Probleme zurecht. Okay. Das heißt also er würde sich nicht selbst zerstören ;-) Aber warum erreicht er die Anschläge nicht wie berechnet? Kann man sich eigentlich auf das 1..2 ms verlassen, oder haben Servos große Abweichungen? Ich hab auch mal sowas wie 0,8 .. 2,2 gelesen ;-( Grüße, Freakazoid
> aber WARUM funktioniert das Programm oben nicht, wenn der > INT alle 20ms aufgerufen wird? Weil es so ist, dass die 20 ms so ziemlich das unwichtigste bei der ganzen Servoansteuerung sind. Die Pulsdauer ist wichtig. In welchen Abständen die Pulse kommen interessiert normalerweise kein Servo. OK, die 20ms sollte man nicht länger machen, aber kürzer ist kein Problem. -> Für das allerunwichtigste (20ms) benutzt du ein tolles Hardwarefeature (Timer), dass dich von allen Sorgen befreit. Für das wirklich kritische, nimmst du eine Loop in einem Interrupt und handelst dir damit auf lange Sicht ne Menge Probleme ein. Allerdings: So wie du das programmiert hast, müsste das ohne Probleme gehen (in diesem Testfall). Daher die Frage: Wie hast du die 1 ms ausgemessen? Mit Messgerät oder mit der Annahme dass, wenn das Servo auf Linksanschlag liegt, auch 1ms anliegen.
> Kann man sich eigentlich auf das 1..2 ms verlassen
Absolut nicht.
Servos unterliegen Streuungen. Ausserdem würde es
kein Hersteller wagen, ein Servo bei 1 ms in den mechanischen
Anschlag zu treiben. Ist auch kein Problem im Modellbau.
Das Servo dreht so weit wie es eben dreht und den Weg stellt
man sich durch das Gestänge ein (war früher mal so), bzw.
man stellt Senderseitig die Endpunkte ein. Und auf so manchem
Sender findet mann dann schon mal eine Einstellung von 110%
für die Endlage.
> Weil es so ist, dass die 20 ms so ziemlich das unwichtigste > bei der ganzen Servoansteuerung sind. Oha. Dachte, daß die 'Kraft' des Servos davon abhängig wäre (in grobem Rahmen). Zykluszeiten von >50ms sind angeblich schlecht. > OK, die 20ms sollte man nicht länger machen, aber kürzer ist kein > Problem. Also doch. Auch wenn 'kürzer' kein Problem ist (das hab ich ja auch nie behauptet), ist es eine höhere Last für den AVR. NUR für Servoansteuerung wäre okay, aber das Baby soll vielleicht noch was anderes machen ;-) > -> Für das allerunwichtigste (20ms) benutzt du ein tolles > Hardwarefeature (Timer), dass dich von allen Sorgen befreit. > Für das wirklich kritische, nimmst du eine Loop in einem > Interrupt und handelst dir damit auf lange Sicht ne Menge > Probleme ein. Ey. Das ist unfair. Wie ich schon oben erwähnt habe, weiß ich das eine Loop in einem ISR böse ist. Das ist ein TESTPROGRAMM. Das wird nie, nie, nie so später aussehen. Es soll nur simpelst sein. (BTW: Ich würde auch nie sleep(xxx) in einem Programm - vor allem der ISR - verwenden oder andere zeitintensive Sachen in ISRs machen. Glaube mir g) > Allerdings: So wie du das programmiert hast, müsste das > ohne Probleme gehen (in diesem Testfall). Okay. Danke. Back to the roots ;-) > Daher die Frage: Wie hast du die 1 ms ausgemessen? > Mit Messgerät oder mit der Annahme dass, wenn das Servo auf > Linksanschlag liegt, auch 1ms anliegen. Letzteres (Datenblatt). Deswegen auch oben die Frage bezüglich der möglichen Abweichungen. Mein Ziel ist es nicht die supertollste Ansteuerung zu konzipieren, sondern Grundwissen zu sammeln, welches später hilfreich ist. Sollte ein Servo z.B. große Abweichungen haben, wird es in komplexeren Programmen später schwierig den Fehler zu finden. Grüße, Freakazoid
> findet mann dann schon mal eine Einstellung von 110% > für die Endlage. Was aber immer noch nicht heisst, das man damit an den mechanischen Grenzen des Servos angelangt ist. Der mechanische Anschlag hat nur den einen Sinn zu verhindern das das Servo rundum dreht. Mehr nicht! Ob dieser mechanische Anschlag nun bei einer Auslenkung von 60° oder bei 90° ins Spiel kommt, hängt einzig und allein von der mechanischen Auslegung des Getriebes ab. Wenn schon, dann könnte man Linksausschlag bzw. Rechtsausschlag so definieren, dass die anliegen, wenn eine Auslenkung von 45° (oder 60° oder was auch immer) vorliegen. Aber: Im Modellbaubereich interessiert das (mit Ausnahme von 180° Servos) niemanden wirklich.
>> Kann man sich eigentlich auf das 1..2 ms verlassen > Absolut nicht. Damit ist das Problem wohl gelöst. Ich hatte nur Angst das Servo zu zerstören, wenn es weiter getrieben wird als es kann: 'Dreh', 'Kann nicht', 'Sollst drehen Du Sau', 'Krrgh' ;-) 'Mechanischer Anschlag' hört sich zudem auch nach Endzeit an. Wenn das Poti (also der Feedbackgeber) sagt: 'Noch nicht am Ziel' würde ich vermuten, daß der Motor weiter angesteuert wird. Zudem würde wohl der Stromverbrauch ansteigen (blockierte Motoren machen das gerne). Grüße, Freakazoid
> > OK, die 20ms sollte man nicht länger machen, aber kürzer ist kein > > Problem. > Also doch. Auch wenn 'kürzer' kein Problem ist (das hab ich ja auch > nie behauptet), ist es eine höhere Last für den AVR. NUR für > Servoansteuerung wäre okay, aber das Baby soll vielleicht noch was > anderes machen ;-) Genau darum gehts: Diese Pulse kann der Timer ganz alleine erzeugen. Da braucht er keinen ISR dazu. Timer eingestellt und er tickert dir den Pin im gewünschten Zeittakt. Du möchtest das Timing ändern. Kein Problem. Ein Register neu beschreiben und der Timer macht wieder den Rest. Noch besser als wenn praktisch 0% Rechenzeit dafür draufgehen kannst du es nicht kriegen.
Eben, und einfach ist es auch noch, man muss nur den einfachen timer kennen :D
Datenblatt leider nicht elektronisch ;-(
Aber ich hab nochmal nachgesehen. Die geben eine Abweichung in der
Pulsbreite von 0,6ms an. Das ist viel. Hab ich wohl übersehen.
> Du weisst, dass der Timer weiter laeuft, wenn du in der ISR bist??
Ja. Warum?
Denke der Thread kann geschlossen werden. Servos unterliegen also
größeren Abweichungen als ich dachte. Gut. Dafür sind sie billig ;-)
Grüße und Danke an Euch beiden, Freakazoid
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.