Mega48 @ 16Mhz Hi, wie Servos funktionieren ist mir klar und ich hab die dinger auch schon zum laufen gebracht ;) Ich möchte 2 Servos mit Timer1 ansteuern und habe mir folgendes überlegt: Timer1 Compare Interrupt auf 16ms (OCR1A = 1000 und prescaler auf 256) anschliessend auf PWM umschalten und in OCR1A und OCR1B die Position der servos laden (davor mit 62 multiplizieren und prescaler auf 1). Beim Timer1 Overflow wieder auf 16ms ist das eine "schoene" loesung? so haette die cpu einmal ca.20ms und einmal ca. 4ms zeit um andere spielerrein durchzurechnen?! oder gibt es noch eine einfachere Lösung? meistens wird ja ein 1ms/255 interrupt erzeugt und darueber die servoposition und 20ms pause eingestellt/perechnet, aber dies ist ja doch recht cpu lastig?! Ich bitte um kritik^^
Misst, ich mein Tiny2313, aber kommt ja (fast) aufs gleiche raus^^ ich habs mal kurz zusammengeschrieben, kanns aber erst heut abend testen.
1 | void main (void){ |
2 | DDRB |= (1<<PB3) | (1<<PB4); |
3 | OCR1AH = 0x03; |
4 | OCR1AL = 0xE8; |
5 | TIMSK |= (OCIE1A); //Output Compare Match Interrupt |
6 | TCCR1B |= (1<<CS12); //Run Timer1 prescaler 256 -> 16ms |
7 | sei() |
8 | |
9 | while(1){;} |
10 | }
|
11 | |
12 | ISR (TIMER1_COMPA_vect){ |
13 | TCCR1B = 0x00; //Timer1 Stop |
14 | TIMSK &= ~(1 << OCIE1A); //Output Compare Interrupt |
15 | TIMSK |= (1<<TOIE1); //Timer1 Overflow Interrupt |
16 | TCCR1A |= (1<<COM1A1) | (1<<COM1B1); //Clear OC1A/OC1B on compare Match |
17 | /*
|
18 | OCR1AH =
|
19 | OCR1AL =
|
20 | OCR1BH =
|
21 | OCR1BL =
|
22 | */
|
23 | PORTB |= (1 << PB3); |
24 | PORTB |= (1 << PB4); |
25 | TCCR1B |= (1<<CS10); //Run Prescaler 1 |
26 | }
|
27 | |
28 | |
29 | ISR (TIMER1_OVF_vect){ |
30 | TCCR1B = 0x00; //Timer1 Stop |
31 | TIMSK &= ~(1<<TOIE1); //Timer1 Overflow Interrupt |
32 | TIMSK |= (1 << OCIE1A); //Timer1 Output Compare Interrupt |
33 | |
34 | OCR1AH = 0x03; |
35 | OCR1AL = 0xE8; |
36 | |
37 | TCCR1B |= (1<<CS12); //Run Timer1 Prescaler 256 |
38 | }
|
Nicht ganz optimal .... Nimm den Timer1 Mode 14 (Fast PWM). Also 16MHz -> 62.5ns cycle time. Für die PWM Periode brauchts rund 20ms. => 20ms / 62.5ns = 320.000 ==> Prescaler 8 also ICR1 = 40000 (PWM Periode) für OCR1A und OCR1B kannst Du dann Werte zwischen 2000 und 4000 nehmen (1 - 2 ms). Grüße, Michael
Nachtrag: hier der Code: // Timer1, Mode 14, Fast PWM, Prescaler 8, OCP A (clear), OCP B (clear) ICR1 = 40000; OCR1A = 3000; OCR1B = 3000; TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1); TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); Die Servo Impuls Eingänge dann einfach an die Pins PB3 und PB4 .... Grüße, Michael
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.