Hallo
Multitasking können die AVRs natürlich nicht. Für Aufgaben, die quasi im Hintergrund ablaufen sollen, verwendet man deshalb die Timerfunktionen der AVRs. Hier wird die "klassische" Servoansteuerung beschrieben:
http://www.rn-wissen.de/index.php/Servo
PHP-Code:
#define SERVOPIN 7
#define SERVOPORT PORTD
#define DDRSERVO DDRD
volatile unsigned char servopos;
void servo_init()
{
TIMSK|=(1<<OCIE2);
TCCR2 |= (1<<WGM21) | (1<<CS20); //Prescale=1, CTC mode
OCR2 = F_CPU/100000; //alle 10µS ein IRQ
DDRSERVO|=(1<<SERVOPIN);
};
ISR(TIMER2_COMP_vect)
{
static int count;
if(count>servopos)SERVOPORT&=~(1<<SERVOPIN);
else SERVOPORT|=(1<<SERVOPIN);
if(count<2000)count++;
else count=0;
};
Wie funktioniert das? Der Timer wird so programmiert, dass er alle 10µs die Interruptserviceroutine (ISR) aufruft. Die Aufrufe werden in der ISR mitgezählt (count), der Zählerstand wird zwischen den Aufrufen gespeichert (static). Zusätzlich wird in der ISR der Zählerwert mit dem Wert für die Servoposition (servopos) verglichen und dem Ergebniss entsprechend der Servoausgang gesetzt oder gelöscht. Bei 10µs oder 0,01ms pro Aufruf ist nach 100 Aufrufen eine Millisekunde vergangen, nach 2000 sind es 20ms.
Alles klar soweit? Wie verwendet man das nun beim asuro? Man könnte Timer0 verwenden, denn der wird von der Library des asuro nicht verwendet. Oder man klinkt sich in den Timer1 ein der ja schon für die PWM-Ansteuerung der Antriebe genutzt wird:
PHP-Code:
#include "asuro.h"
volatile unsigned char servopos=40; // 40 ist ca. 1 ms
SIGNAL (SIG_OVERFLOW1)
{
static int count = 1;
if(count > servopos) BackLED(OFF,OFF); else BackLED(ON,OFF);
if(count < 780) count++; else count=1;
}
int main(void)
{
Init();
TIMSK |= (1 << TOIE1); // Timer1 Overflow-ISR einklinken für Servo
unsigned char l;
int data[2];
FrontLED(ON);
l=108;
Sleep(255);
Sleep(255);
MotorDir(FWD,FWD);
MotorSpeed(130,130);
while(1) {
LineData(data);
if(data [0] < data[1])
{l=l+4;
MotorSpeed(100,140);}
else if(data[0] == data[1])
{l=l;}
else
{l=l-4;
MotorSpeed(140,100);}
//servo(l);
servopos = l; // Servoposition setzen
if(l > 120)
{l=120;}
else if(l < 80)
{l=80;}
else
{l=l;}
}
return 0;
}
ungetestet
Gruß
mic
Lesezeichen