Hallo,
ATmega8, 8Mhz interner RC-Takt, avr-gcc (WinAVR 20080512) 4.3.0
Schon zig Beiträge im Forum, ich finde leider trotzdem keine Lösung für
mein Problem. Vielleicht kann jemand einen Blick auf den Code werfen und
sieht einen Fehler.
Timer0 verwende ich für die Tasten-Entprellung. Ich möchte per Taster
die Stellung des Servos verändern.
Der Servo reagiert nicht, bekommt also keine vernünftigen Impulse.
Ich hab den Servo probiert über eine einfache delay-Funktion
anzusteuern, das funktioniert. Ich bin noch relativ ungeübt mit
Timern/Interrupts, allerdings will ich mir das aneignen und ich denke es
ist die wesentlich elegantere Variante als über eine Delay-Funktion.
Gruß Udo
Hallo Udo,
um zwei Servos an den OC1A und OC1B Pins eines Mega8 zu betreiben,
reicht schon eine Handvoll Codezeilen:
1
// Servo Frame-Time:
2
#define FRAME_TIME 20 // msec
3
4
// init timer 1:
5
ICR1=FRAME_TIME*1000;// PWM cycle time in usec
6
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);// OC1A/B clr on match, set on TOP
7
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS11);// TOP = ICR1, clk = sysclk/8 (->1us)
8
TCNT1=0;// reset Timer
9
10
OCR1A=1000;// set Servo 1 to 1ms-position
11
OCR1B=2000;// set Servo 1 to 2ms-position
Durch die Verwendung der Output-Compare-Funktion des 16bit-Timers 1
bleiben die Servos gesteuert, ohne dass der Prozessor auch nur einen
einzigen Befehl dazu abarbeiten müsste. Mit Deinen Tasten brauchst Du
jetzt nur noch die OCR-Register zu verändern.
Gruß,
Peter
P.S. Dein Code ist ja echt gruselig ..
@Peter
Danke werd es damit mal probieren.
Inwiefern ist der gruselig ? In Bezug auf den Stil oder Inhalt ?
@Alexander
Die Tasten entprell ich mit Timer0, die haben mit meinem Problem
eigentlich nichts zu tun.
1
//Es wird immer nur IF-Bedingung ausgeführt, da TCCR2 immer 5 bleibt!!!
2
3
if(TCCR2==5){// Prescaler 1024 (nach 20ms)
4
TCNT2=151;//
5
TCCR2=(1<<CS22);// wird hier nicht ein neuer Wert für TCCR2 gesetzt, der erst mit der nächsten else-Schleife wieder auf 5 geändert wird ?
> Inwiefern ist der gruselig ? In Bezug auf den Stil oder Inhalt ?
Beides. Bespiel für Stil:
Du initialisierst TCCR2 schön lesbar mit
"(1<<CS22)|(1<<CS20)|(1<<CS21)", fragst dann aber in der ISR auf "(TCCR2
== 5)" ab. Hier muss der Leser unnötigerweise erstmal Bits in Dezimal
umrechnen. Und eine Abfrage ">=255" mit einer 8Bit unsigned-Variablen
ist ziemlich verwirrend, da deren Wertebereich eben nur mal bis 255
geht.
Beispiel Inhalt:
Delay-Funktionen innerhalb einer ISR sind absolut PFUI, BAH! Dann
scheinst Du die Funktionsweise des Timers noch nicht verstanden zu
haben. Wenn Du TCNT2 mit 151 beschreibst, dann zählt der Timer von dort
aus weiter bis 255 und erzeugt einen Interrupt. Bis dahin hat er 255-151
Takte gezählt, und nicht 151.
Gruß,
Peter
Peter Bünger wrote:
> Hallo Udo,>> um zwei Servos an den OC1A und OC1B Pins eines Mega8 zu betreiben,> reicht schon eine Handvoll Codezeilen:>>>
1
// Servo Frame-Time:
2
>#defineFRAME_TIME20// msec
3
>
4
>// init timer 1:
5
>ICR1=FRAME_TIME*1000;// PWM cycle time in
6
>usec
7
>TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);// OC1A/B clr on match,
8
>setonTOP
9
>TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS11);// TOP = ICR1, clk =
10
>sysclk/8(->1us)
11
>TCNT1=0;// reset Timer
12
>
13
>OCR1A=1000;// set Servo 1 to 1ms-position
14
>OCR1B=2000;// set Servo 1 to 2ms-position
15
>
>>> Durch die Verwendung der Output-Compare-Funktion des 16bit-Timers 1> bleiben die Servos gesteuert, ohne dass der Prozessor auch nur einen> einzigen Befehl dazu abarbeiten müsste. Mit Deinen Tasten brauchst Du> jetzt nur noch die OCR-Register zu verändern.>> Gruß,> Peter>> P.S. Dein Code ist ja echt gruselig ..
Hallo,
dieser Thread ist zwar schon ein paar Monate alt, aber das hier
gepostete Problem dekt sich ganz gut mit meinem.
Auch ich möchte zwei Servos ansteuern und habe auch den Timer1 dafür
gedacht.
Die von Peter Bünger geposteten Codezeilen scheinen also auch für mein
Problem die richtigen zu sein.
Mein Problem ist jetzt nur, dass ich einen Mega32 verwende. Der mit
einem Takt von 16Mhz betrieben wird. Also müsste ich ja eigentlich den
Prescaler auf 16 setzten, den es aber leider nicht gibt. Also hab ich
mir als nächstes gedacht, dass ich bei ICR1 40000 setzte. Damit er
länger braucht um den Match zu haben.
Nur leider funktioniert das ganze nicht so, wie es soll. Ich muss bei
OCR1X Werte zwischen ca. 1000 und ca. 5000 angeben, damit er sich
ziemlich weit dreht. Allerdings erreicht er dadurch noch nicht seine
Endpositionen. Bei Werten über 6000 "zittert" er nur noch.
Wahscheinlich habe ich bei der Berechnung der Frequenz und des Puls /
Pause Verhältnisses etwas noch nicht richtig verstanden.
Über Hinweise und Lösungsvorschläge würde ich mich sehr freuen.
Gruß Christian
>Also hab ich mir als nächstes gedacht, dass ich bei ICR1 40000 setzte. >Damit er
länger braucht um den Match zu haben.
Schon mal richtig gerechnet.
>Nur leider funktioniert das ganze nicht so, wie es soll. Ich muss bei>OCR1X Werte zwischen ca. 1000 und ca. 5000 angeben, damit er sich>ziemlich weit dreht. Allerdings erreicht er dadurch noch nicht seine>Endpositionen. Bei Werten über 6000 "zittert" er nur noch.
Bei 16MHz und einer Teilung durch Acht, ergibt sich eine
Timer-Tick-Periodendauer von 0,5µs (oder auch 500 Nanosekunden).
1 ms sind dann 2000 Ticks (OCR1x-Wert), 2 ms sind dann 4000 Ticks.
Alles dazwischen sollte dein Servo anfahren können. Alles darüber
verwirrt ihn nur.
Danke für die hilfreichen Erklärungen TOP
Funktioniert nun alles wie gewünscht.
Ich hatte gestern Versucht mit Hilfe einer For Schleife den ganzen
Wertebereich immer durchzuzählen. Dabei habe ich dann noch vergessen,
dem Servo Zeit zu gegben, die Position anzufahren. Daduch hat er auch
nie die Endpunkte erreicht.
Danke schön und Gruß
Christian