Hallo, hab wieder mal eine Frage - und JA auch ich habe die vielen Servo Einträge bereits gelesen! Ich verwende ATMEGA8 mit 8MHz intern. Die Servo-Signalleitung hängt an PD3 und ist als Ausgang konfiguriert. Als Servo-Versorgung benutze ich 4x1.5V Batterien, sollte doch genügen. Wenn ich eine LED an PD3 hänge sehe ich das flackern, kann auch die Werte per Tastendruck ändern und die LED flashed dementsprechend anders. Nur leider bekomme ich bei selben Programm und angeschlossenen Servo NULL Veränderung der Servostellung. Timer1 mit 16bit verwende ich prescale=8. Timer beginnt 22ms vor Überlauf und PD3=H. Bei CompareA wird PD3=L, dies geschieht 1.5ms nach dem Startwert. Lt. meinem ServoSignalverständnis muss zwischen 1. und 2. ms ein High auf Low Pegelwechsel geschehen. Danach 20 ms gleichen Pegel bis wieder von vorne beginnt -> Periodendauer von 22ms! (lt. Roboternetz Zeitplan) fclk=8MHZ/8 -> 0,001ms 2ms/0,001ms = 2000 zyk -> 20ms = 20 000 zyk Timer läuft bis 2^16 = 0...65535 -> 65535 - 20 000 = 45535 45535 - 2000 (2ms) = 43535, was der Startwert ist. 43 535 = AA0F = Startwert 44 535 = B1DF = Startwert + 1ms 45 035 = = Startwer + 1.5ms = Servomitte 45 535 = ADF7 = Startwert + 2ms 65 535 = FFFF = Startwert + 22ms Zu den Registereinträgen: /* timer1 for PWM (16bit) */ /*8 MHz Chip clock, appr. 1° -> 0,004ms per clock */ TCNT1H =0xAA; // start @ 43535 TCNT1L =0x0F; TIMSK |=(1<<OCIE1A) | (1<<TOIE1); // compare A + overflow interrupt enable OCR1AH =0xAF; // 1,5ms = 45035 OCR1AL =0xEB; TCCR1A = 0x00; TCCR1B |=(1<<CS11); // clk/8 SERVO_ON; Danke
Hai Daniel, mal unabhängig von der Frage, wer denn Deinen Timer nach einem Überlauf wieder auf 0xAA0F setzt: Warum machst Du Dir die Sache so kompliziert? Einfacher Weg: "Fast PWM Mode", "Bottom" ist hier automatisch immer Null, "Top" kannst Du in ICR1 setzen, in Deinem Fall also auf 22000. Die Werte für OCR1 kannst Du dann einfach in usec einsetzen, also 1500 für die Mittelstellung. Feddisch! Gruß, Peter
>Timer beginnt 22ms vor Überlauf
Warum? Es gibt Timer-Modi, die dafür besser geeignet sind, als ein
manuelles Nachladen des Timers, da sie das ganz alleine machen.
Der einzige Nachteil bei diesen Modi ist, dass man an bestimmte Portpins
gebunden ist, wenn man die Servo-PWM komplett in Hardware ausgeben will.
STK500-Besitzer schrieb: >>Timer beginnt 22ms vor Überlauf > > Warum? Es gibt Timer-Modi, die dafür besser geeignet sind, als ein > manuelles Nachladen des Timers, da sie das ganz alleine machen. > Der einzige Nachteil bei diesen Modi ist, dass man an bestimmte Portpins > gebunden ist, wenn man die Servo-PWM komplett in Hardware ausgeben will. Danke, für den Tipp und leider schreibst du auch schon das Problem dass bei der Verwendung der speziellen Modi kommt - die vorgegebenen PINS. PD3 ist der letzte Pin und vorgesehene für SERVO. Zum Nachladen der Werte: Werden in der ISR overflow wieder auf Startwert gesetzt und PD3 wieder HIGH. Bei ISR compareA wird PD3 LOW.
Trotzdem sollte ein CTC-Modus mit ISR für Overflow und einem Compare Match einfacher sein. Zumindest brauchst du dich nicht ums Nachladen kümmern und musst auch nicht vom 'oberen' Ende des Zahlenbereichs wegrechnen. > Danach 20 ms gleichen Pegel bis wieder > von vorne beginnt -> Periodendauer von 22ms! Das ist ein Missverständnis. Ein kompletter Zyklus dauert 20ms. Wobei diese Zeit bei vielen alten Servos keine Tragik ist. Die 20ms haben sich aus dem Impulstelegram auf der Funkstrecke ergeben. Den Servos sind die 20ms meistens egal, die interessieren sich nur für die Pulsbreite.
> Den Servos sind die > 20ms meistens egal, die interessieren sich nur für die Pulsbreite. Das kann ich bestätigen. Ich steuere z.B. die Servos eines Modellbahn-Schrankenantriebs alle 64ms an, um die Stromaufnahme der Servos klein zu halten. Einen schon etwas älteren, aber gut funktionierenden Servoimpuls-Generator mit Mega48 findest Du hier: http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html ...
Danke für die vielen Beiträge. Vielleicht kann mir der eine oder andere noch mehr helfen. Wills jetzt mit dem CTC Modus versuchen, jedoch mit folgenden unveränderbaren Vorgaben! 1.) Servo-Steuerleitung ist PD3 2.) Atmega läuft mit 8 MHZ und Timer1 prescale = 8 3.) Servo soll alle 20ms neuen Impuls bekommen Hab nun im Manual nachgelesen und folgende Registerwerte festgelegt. TIMSK |=(1<<OCIE1A) | (1<<TOIE1); OCR1A = Impulsdauer; TCCR1A |=(1<<WGM11) | (1<<WGM10); TCCR1B |=(1<<CS11) | (1<<WGM13) | (1<<WGM12); PD3_EIN; TCNT1 müsste doch bei 0 beginnen und PD3 HIGH. Bei TCNT1 = OCR1A wird PD3 LOW. Dies sollte nach 1 - 2 ms der Fall sein. Danach soll der TCNT1 noch für weitere 18ms weiterlaufen eher TCNT1 = TOP ist und PD3 wieder HIGH wird. Ich check nicht wie ich TOP festlege und ob da dann im CTC Mode PD3 automatisch wieder gesetzt wird oder manuell gemacht werden muss. Danke
>Danke, für den Tipp und leider schreibst du auch schon das Problem dass >bei der Verwendung der speziellen Modi kommt - die vorgegebenen PINS. >PD3 ist der letzte Pin und vorgesehene für SERVO. Dann kann man die Sache halt nicht komplett in Hardware machen, sondern muss auf die ISR der jeweiligen Interrupts zurückgreifen >TCNT1 müsste doch bei 0 beginnen und PD3 HIGH. richtig >Bei TCNT1 = OCR1A wird PD3 LOW. richtig. >Dies sollte nach 1 - 2 ms der Fall sein. >Danach soll der TCNT1 noch für weitere 18ms weiterlaufen eher TCNT1 = TOP ist >und PD3 wieder HIGH wird. Auch richtig. >Ich check nicht wie ich TOP festlege und ob da dann im CTC Mode PD3 >automatisch wieder gesetzt wird oder manuell gemacht werden muss. Es gibt zwei CTC-Modi: Mode 4 und 12 Im Mode 4 wird OCR1A als TOP verwendet und im Mode 12 ICR1. Wenn diese Vergeichswerte erreicht werden, wird der Timer auf 0 zurückgesetzt und ein Timer-Overflow-Interrupt ausgelöst. In der ISR zu diesem Interrupt kann man dann PD3 auf 1 setzen. Die Pulsdauer legt man durch den Wert von OCR1B fest. Auch hierzu gibt es einen Interrupt-Vektor. In der ISR zu OCR1B wird PD3 = 0 gesetzt. Hab ich irgendwann schon mal lauffähig (in C) hinbekommen. Wie Hannes schon anmerkte: Servos stört eine größere Pause nicht unbedingt. Die Ansteuer-Periode kann auch kürzer sein. Wichtig ist nur die Pulslänge. Weder die Periodendauer, noch der Tastgrad sind wirklich relevant.
Hi >Wenn diese Vergeichswerte erreicht werden, wird der Timer auf 0 >zurückgesetzt und ein Timer-Overflow-Interrupt ausgelöst. Nein. In den CTC-Modes wird wird der Overflow-Interrupt bei MAX (65535) ausgelöst. Hier muss anstelle des Overflow-Ints der OCR1A- bzw. der ICR-Interropt benutzt werden. MfG Spess
Hi, zu deiner Antwort: > Es gibt zwei CTC-Modi: Mode 4 und 12 > Im Mode 4 wird OCR1A als TOP verwendet und im Mode 12 ICR1. > Wenn diese Vergeichswerte erreicht werden, wird der Timer auf 0 > zurückgesetzt und ein Timer-Overflow-Interrupt ausgelöst. > In der ISR zu diesem Interrupt kann man dann PD3 auf 1 setzen. JA soweit komm ich auch, wann bzw. was nehm ich dann aber als Signalende? Mit deiner vorgeschlagenen Variante bekomme ich ja nur den Impuls von 1-2ms hin. 1-2ms 10-65ms -- -- ... __| |____________| |_______ ... 1 2 3 1 2 3 1... Start in Mode 4 od. 12 ist egal, da nur andere Register TOP sind 2... Timer erreicht TOP, hier setz ich mit ISR_TOP PD3 = LOW Leider fängt aber hier der Timer auch wieder mit NULL an und ich wäre wieder bei 1 statt bei 3! Trennt ihr etwa das Steuersignal in zwei Teile auf - Impulsdauer + Wartezeit? Sprich Timer mit zwei konfigurationen während eines ganzen Impuls laufen lassen?
> Trennt ihr etwa das Steuersignal in zwei Teile auf - Impulsdauer + > Wartezeit? Das wäre die eine Möglichkeit. Einfacher ist es, Impulsdauer und Periodendauer separat zu behandeln. Die Periodendauer (Impulszeit + Impulspause) ergibt sich aus dem Zählumfang des Timers und kann in einem der CTC-Modi mittels der ICR1-Register gesetzt werden. Die Impulsdauer kann dann mit einem der OCR1-Register festgelegt werden. Man kann die Periodendauer (Top) aber auch mit OCR1A festlegen und mit OCR1B die Impulsdauer. Es kann der zugehörige OC-Pin eingebunden werden (Clear by Compare, Set by Bottom). Man kann aber auch ISRs aufrufen lassen und in diesen einen beliebigen Pin per Programm setzen und löschen. Das Ganze funktioniert aber auch mit dem freilaufenden Timer, indem man in der Compare-ISR das Compare-Register ausliest, das Intervall dazu addiert und als nächsten Interrupt-Termin ins Compare-Register zurück schreibt. Dies hat den Vorteil, dass sich die andere Compare-Einheit um weitere zeitkritische Dinge kümmern kann und die ICP-Einheit nebenher auch noch exakt von außen kommende Impulse messen kann. Das letzte Verfahren (Addieren des Intervalls auf den aktuellen Compare-Wert) hat den weiteren Vorteil, dass man damit auch mehrere Servos mit nur einer Compare-Einheit ansteuern kann. Man zählt in der ISR einen Zähler hoch, den man als Index (auf RAM-Array) für die Zeit bis zum nächsten Interrupt und das Bitmuster für die Servoimpulsausgänge nutzt. Man richtet (im Array und Zählumfang des Index) einen Datensatz mehr ein als man Servos hat und gibt dem Dummy-Datensatz die Restzeit des Servo-Zyklusses. So werden im Hintergrund (Interrupt nur einer Compare-Einheit) sämtliche Servoimpulse generiert, während sich die Mainloop ganz gemütlich neben anderen Aufgaben um die Bereitstellung der Positionsdaten (im SRAM-Array) kümmert. Wer es ganz genau haben will, korregiert bei jeder Impulsdauer-Änderung einfach die Restzeit mit (Subtraktion der Impulsdauer aller Kanäle vom Fixwert für 20ms). Wer es noch genauer haben will, schreibt die neuen Daten in einen Puffer (zweites Array) und kopiert sie dann in der ISR im Dummy-Takt, was auch nebenbei das Problem mit dem atomaren Zugriff auf die 16-Bit-Werte erschlägt. Wie bereits gesagt, stehen dabei der andere Compare-Interrupt, der Input-Capture-Interrupt und notfalls auch der Überlauf Interrupt (ohne Timer-Preload!!) für andere Zwecke zur Verfügung. Viele Wege führen zum Ziel, der optimale Weg richtet sich nach den Randbedingungen, einen "ultimativen einzig richtigen Weg" gibt es nicht. ...
Hab ich mich falsch ausgedrückt? PD3 wird bei OCR1B gelöscht und bei TOP gesetzt. 1-2ms 10-65ms -- -- ... __| |____________| |_______ ... 1 2 3 1 2 3 1: TOP ==> PD3 setzen 2: OCR1B ==> PD3 löschen 3: hat keinen Namen, braucht auch keinen
Hallo zusammen, ich nochmal. Hab anscheinend das Problem teilweise gelöst. Ich fahr nun mit Timer1 und COMPA und COMPB. Wobei COMPA = TOP und COMPB die Impulsdauer darstellen. Mit Teiler 8 komme ich auf 1us / Timertakt -> Impulsdauer zwischen 1000 und 2000 sowie Periodendauer von 10 000 bis 65 000. Mit einer angeschlossenen LED funktioniert das toll, flashed schön und schaut richtig aus (Oszi keines da!). Wenn ich aber nun den Servo, marke billigshofer anschließe bewegt sich nichts! Die Servoversorgung kommt aus 4x 1.5V AAA Batterien, die auf Braun und Rot angeschlossen sind. Das Signal sollte laut Herrsteller auf das Orange Kabel gehen - so geschieht auch aber nix. Was mit noch aufgefallen ist ist dass bei Versorgen, der Servo immer in eine Endlagenrichtung geht, egal ob Steuerleitung angeschlossen ist oder nicht. Dachte schon das vielleicht eine andere Ltg die Steuerleitung ist, aber dann macht der Servo recht komische Geräusche ;-) Hab euch mal die main.c und Aufbau-Foto angehängt vielleicht hab ja doch noch einen fehler, Danke
> Mit einer angeschlossenen LED funktioniert das toll, flashed schön und > schaut richtig aus (Oszi keines da!). Naja, bei 2 ms alle 20 ms "flasht" da eigentlich nix, 50 Hz erkennt das Auge fast noch als Dauerlicht. Ich vermute, dass Deine Impulsbreite nicht stimmt, weil Dein Controller nicht mit dem Takt läuft, den Du wünscht bzw. vermutest. Geh' mal davon aus, dass ein neuer (unumgefuster) Mega8 mit 1 MHz internem Takt arbeitet. Nimm den Timer-Vorteiler versuchsweise mal raus und schau, ob das Servo immernoch auf Anschlag fährt. Das wäre dann ein Beweis, dass/ob der Mega8 mit 1MHz tuckert. Weiterhin besteht die Möglichkeit, dass Dir aufgrund von Störungen der Mega8 abstürzt, bzw. einen Reset ausführt. - Sind die Betriebsspannungen von AVR und Servo sauber entkoppelt? - Hast Du den obligatorischen 1k-Widerstand in Reihe in der Impulsleitung? - Sind am AVR alle 100n-Abblock-Kerkos (direkt an den Anschlusspins) vorhanden? - Welche Aufgabe hat der SMD-AVR auf dem Aufsteck-Board des STK500? könnte der stören? (es soll nur Einen geben) ...
>(es soll nur Einen geben) Nein, es kann nur Einen geben. http://de.wikipedia.org/wiki/Highlander_%E2%80%93_Es_kann_nur_einen_geben ;-) MfG Paul
1 | #define SERVO_ON ( PORTD &= ~(1<<SERVO) )
|
2 | #define SERVO_OFF ( PORTD |= (1<<SERVO) )
|
ist fürs Servo ungeeignet. sollte wohl eher so aussehen:
1 | #define SERVO_OFF ( PORTD &= ~(1<<SERVO) )
|
2 | #define SERVO_ON ( PORTD |= (1<<SERVO) )
|
Umgekehrt halt...
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.