Hallo
Obwohl hier im RN-Forum schon einige Möglichkeiten gezeigt werden wie man viele Servos mit wenig Microkontroller ansteuert möchte ich hier noch meinen Weg vorstellen und testen lassen. Ich verwende das aber erst seit ein paar Tagen mit nur 4 Servos und kann deshalb nicht sagen ob es mit 8 (oder mehr) Servos auch so gut funktioniert.
Ohne viele Worte hier der Code:
Code:
// Servos ansteuern mit 8MHz Mega32 und 8-Bit Timer2 Overflow-ISR 22.3.2008 mic
// Die Servosimpulse werden nacheinander erzeugt. Die Impulsdauer jedes Servos
// setzt sich aus einem Grundimpuls (der für alle Servos gleich ist) und seinem
// Positionswert zwischen 0 und 255 zusammen.
// In der ISR werden im Wechsel ein Grundimpuls und ein Positionswert erzeugt
// und zum jeweiligen Servo gesendet. Nach den Servoimpulsen wird eine
// Pause eingefügt um die 50Hz Wiederholfrequenz (20ms) zu erzeugen.
// Diese auf acht Servos aufgebohrte Version scheint zu funktionieren,
// ich habe es allerdings nur mit angeschlossenen Servos 1-4 ausprobiert.
#include <avr/io.h>
#include <avr/interrupt.h>
// Servoausgänge 1-8
#define servoinit {DDRB |= (1<<PB7); PORTB &= ~(1<<PB7); DDRC |= 0b01110000; PORTC &= ~0b01110000;}
#define servo1on PORTC |= (1<<PC4)
#define servo1off PORTC &= ~(1<<PC4)
#define servo2on PORTC |= (1<<PC5)
#define servo2off PORTC &= ~(1<<PC5)
#define servo3on PORTC |= (1<<PC6)
#define servo3off PORTC &= ~(1<<PC6)
#define servo4on PORTB |= (1<<PB7)
#define servo4off PORTB &= ~(1<<PB7)
#define servo5on PORTB |= (1<<PB0) // Dummyservos 4-8 an SL6
#define servo5off PORTB &= ~(1<<PB0)
#define servo6on PORTB |= (1<<PB0)
#define servo6off PORTB &= ~(1<<PB0)
#define servo7on PORTB |= (1<<PB0)
#define servo7off PORTB &= ~(1<<PB0)
#define servo8on PORTB |= (1<<PB0)
#define servo8off PORTB &= ~(1<<PB0)
uint8_t servo1, servo2, servo3, servo4, servo5, servo6, servo7, servo8;
int main(void)
{
servoinit; // Datenrichtung der Servopins einstellen
//Timer2 Initialisierung
// für 8MHz Takt:
TCCR2 = (0 << WGM21) | (0 << COM20) | (1 << CS22); // Normal Mode, prescaler /64
// für 16MHz Takt:
//TCCR2 = (0 << WGM21) | (0 << COM20) | (1 << CS22) | (1 << CS20); // /128
TIMSK |= (1 << TOIE2); // Timer2 Overflow-Interrupt erlauben -> Servos an
//TIMSK &= ~(1 << TOIE2); // Timer2 Overflow-Interrupt verbieten -> Servos aus
sei();
servo1=125; // Mittelposition, Drehbereich ist von 0-255!
servo2=125;
servo3=125;
servo4=125;
servo5=125;
servo6=125;
servo7=125;
servo8=125;
while(1) // Hauptschleife
{
}
return(0);
}
ISR (TIMER2_OVF_vect)
{
static uint8_t servo_nr=0, grundimpuls=0; // Gestartet wird am Ende der Pause
static uint16_t impulspause;
if(servo_nr)
{
// Endweder wird hier der Grundimpuls erzeugt (Länge 56 Einheiten)
if(grundimpuls++ & 1) { TCNT2=200; impulspause-=256-200; } else
// Oder der zur Servoposition gehörende Impuls (0-255, 0 ist der längste Impuls!)
{
if(servo_nr==1) {TCNT2=servo1; servo1on; impulspause-=servo1;}
if(servo_nr==2) {TCNT2=servo2; servo1off; servo2on; impulspause-=servo2;}
if(servo_nr==3) {TCNT2=servo3; servo2off; servo3on; impulspause-=servo3;}
if(servo_nr==4) {TCNT2=servo4; servo3off; servo4on; impulspause-=servo4;}
if(servo_nr==5) {TCNT2=servo5; servo4off; servo5on; impulspause-=servo5;}
if(servo_nr==6) {TCNT2=servo6; servo5off; servo6on; impulspause-=servo6;}
if(servo_nr==7) {TCNT2=servo7; servo6off; servo7on; impulspause-=servo7;}
if(servo_nr==8) {TCNT2=servo8; servo7off; servo8on; impulspause-=servo8;}
if(servo_nr==9) {servo8off; servo_nr=0;}
if(servo_nr) servo_nr++;
}
}
else
// Anschliessend wird die Impulspause erzeugt. Sie ergibt sich aus der Startlänge-
// der Summe der einzelnen Impulslängen. Bei acht Servos errechnet sich der
// kleinste benötigte Startwert für Impulspause etwa so:
// 8*56 + 8*256 = 2496 (Summe der Grundimpulse + Summe der Positionsimpulse)
{
if(impulspause>256) impulspause-=256; // Gesamtpause in 256er-Schritten
else {TCNT2=-impulspause; servo_nr++; impulspause=3000;} // die Restpause
}
}
(Das wird bei mir mit genau 500 Bytes übersetzt, ist das ein Ohmen?)
Es wäre nett wenn das mal jemand testen würde, bei Interesse kann ich auch noch ein bisschen mehr über die Funktion plaudern.
Gruß
mic
Lesezeichen