Ach, es geht um Servoimpulse, alles klar.
Vielleicht wäre das eine Basis:
Code:
// Servoansteuerung mit 16Bit-Timer1 (mit arexx cat16) mic 18.1.2011
// Die 8 Servos werden an Port B und C angeschlossen:
// Servo0 - PB0
// Servo1 - PB1
// Servo2 - PC2
// Servo3 - PC3
// Servo4 - PC4
// Servo5 - PC5
// Servo6 - PC6
// Servo7 - PC7
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t count_20ms;
volatile uint16_t servo[9] ={1700, 1700, 1700, 1700, 1700, 1700, 1111, 1111, 40000}; // Servopositionen
void sleep(uint8_t pause); // 1/50 Sekunde blockierende Pause
int main(void)
{
cli();
// für 16MHz-ATMega16
TCCR1A = (0<<WGM11)|(0<<WGM10); // CTC-Mode 4
TCCR1B = (0<<WGM13)|(1<<WGM12);
TCCR1B |= (0<<CS12)|(1<<CS11)|(0<<CS10); // prescaler /8
TIMSK = (1<<OCIE1A); // MatchCompare-Interrupt erlauben
DDRB = 0b00000011; // Datenrichtung Servoausgänge setzen
DDRC = 0b11111100;
sei();
sleep(100);
while(1) // Demo
{
cli();
servo[0]=2500;
servo[1]=servo[2]=1600;
sei();
sleep(50);
cli();
servo[0]=servo[1]=servo[2]=1700;
sei();
sleep(50);
}
return(0);
}
ISR(TIMER1_COMPA_vect)
{
static uint8_t nr=8; // Nummer des aktuellen Servos
PORTB &= ~0b00000011; // alle Servoimpulse low
PORTC &= ~0b11111100;
if(nr < 3) // Impuls für Servo oder Pause? (8 Servos)
{
if(nr<2) PORTB |= (1<<nr); // Impulsleitung des aktuellen Servos
else PORTC |= (1<<nr); // auf High setzen und
OCR1A = servo[nr]; // Impulslänge in OCR1A laden
servo[8] -= servo[nr]; // Impulslänge von der Pause abziehen
nr++; // nächstes Servo
}
else
{
OCR1A = servo[8]; // servo[8] ist die Impulspause
servo[8] = 40000; // Startwert 20ms laden
nr = 0; // beim nächsten ISR-Aufruf Impuls
// für Servo 0 erzeugen
if(count_20ms) count_20ms--; // blockierende Pause aktiv?
}
}
void sleep(uint8_t pause) // 1/50 Sekunde blockierende Pause
{
count_20ms=pause+1;
while(count_20ms);
}
(Aus https://www.roboternetz.de/community...l=1#post522751)
Das Programm wurde für einen 16MHz-Mega16 geschrieben, sollte aber auch auf dem Mega32 laufen. Der Timer1 läuft im CTC-Mode mit Prescaler/8 von 0 bis 40000 in 20ms. Während eines Zyklus werden nacheinander jeweils die Impulse für bis zu 8 Servos erzeugt. Die Servopositionen sind in servo[0] bis servo[7] gespeichert, 2000 sind eine Millisekunde (0,001s). In servo[8] ist der Wert für das Zyklusende gespeichert, ein kleinerer Wert (muss aber größer als die Summe der Servos sein, z.B TCNT1+=10) erhöht die Wiederholfrequenz. Mit if(nr < 3) kann man die Anzahl der verwendeten Servos ändern.
Gruß
mic
Lesezeichen