Beim Code vom Roboternetz, nimmt man den Timer2 dazu, aller 10us einen Overflow auszulösen.
Dies geschieht, indem man den OCR in Abhängigkeit von der CPU-Frequenz setzt und bei erreichen des OCR-Wertes den Timer wieder auf null setzt (CTC=Clear Timer on Compare)
In der entsprechenden Interrupt-Routine wir nun zum einen bis 2000 gezählt um 2000x10us = 20ms Periode zu erreichen. Ist der count unter bspw. 150(servopos) wird der Port angeschaltet (150x10us=1500ms), ansonsten wird er abgeschaltet.Code:TCCR2 |= (1<<WGM21) | (1<<CS20); //Prescale=1, CTC mode OCR2 = F_CPU/100000; //alle 10µS ein IRQ
Das Ganze kann man dann auf beliebig viele Servos ausweiten, indem man einfach die entsprechenden Ports und Servo-Positionen da mit einbaut.
Als Port nimmst du da die ganz normalen I/O-Pins, da das hier ja eher ein Software-PWM ist (das togglen der Pins wird ja vom Programmierer vorgegeben)
Ja und mit den Registern... ich red ja blöderweise auch die ganze Zeit vom Timer1, weil ich alle 3 PWM Channels benutze. Da kann man das noch angeben, beim Timer2 (den du ja benutzen willst) nicht.
Bei mir sieht das Ganze dann so aus:
Was benutzt du zum programmieren? AVRStudio? Da kann man das relativ gut debuggen und sieht, was für Timings rauskommen. Spart man sich den Oszi.Code:cli(); //disable interrupts TCCR1A |= (1<<WGM11)|(1<<COM1A1)|(1<<COM1A0); //9BIT PWM, inverted TCCR1B = (1<<CS12); //Prescaler 256 // macht bei meinem 12MHz mega8 21.84ms servo1_move(defaultPos); //setzt den OCR1A entsprechend //TIMSK |= (1<<OCIE1A); //activate timer1 compare match interrupt for timing debugging DDRB |= (1 << PB1); //set PB1 output PORTB |= ( 1 << PB1 ); //set PB1 Pull up on sei();







Zitieren

Lesezeichen