@Merlin321
So eine Servoansteuerung passiert eigentlich immer mit einem Puls von 1...2ms gefolgt von einer Pause mit ca. 20ms.
Ich bau für meine Servoansteuerungen immer eine ISR im Comparematch Interrupt auf.
Dazu verwendest Du einen 16Bit Timer (Timer 1) und lässt diesen mit Prescaler 8 laufen.
Dabei entspricht dann ein Count 0,5µs, also 1ms einem Zählerwert von 2000.
Der Trick dabei ist nun die Servoimpulse, falls man mehrere Servos verwendet, nacheinander zu erzeugen und nach dem letzten Impuls eine Pause einzufügen, die die gewünschten 20ms voll macht.
Beispiel:
Du hast 4 Servos mit 1,5ms = 6ms.
Die Pause wäre somit 20ms-6ms=14ms = Counterwert 28000.
Die Servoimpulse werden dann, gesteuert von einer Variablen, nacheinander an verschiedenen Ausgängen ausgegeben.
Dazu wird der Zählerstand des TCNT1 Registers ausgelesen, der Wert der gewünschten Servoimpulslänge dazugezählt und dieser ins OCR1A Register für den nächsten Comparematch Interrupt reingeschrieben.
Nun folgt die Pause, wo kein Ausgang aktiv ist und somit kein Servo angesteuert wird.
Mit dieser Methode kann man bis zu 8 Servos ansteuern und der Controller langweilt sich dabei sogar noch.
Codeschnipsel für 2 Servos:
Code:
// Timer 1 Comparematch A interrupt service Routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
unsigned int ui_buffer=0;
ui_buffer=TCNT1;
if(uc_servocount==0)
{
SERVO1=0;
SERVO2=0;
ui_buffer+=ui_pause;
OCR1A=ui_buffer;
}
if(uc_servocount==1)
{
SERVO1=1;
SERVO2=0;
ui_buffer+=ui_servo1;
OCR1A=ui_buffer;
}
if (uc_servocount==2)
{
SERVO1=0;
SERVO2=1;
ui_buffer+=ui_servo2;
OCR1A=ui_buffer;
}
uc_servocount++;
if(uc_servocount>2){uc_servocount=0;}
}
Lesezeichen