Hi,

Ich habe mich nochmal daran gemacht mein Programm von Grundauf neu zu überdenken. Es ist sch**ße, wenn die Impulse von einer funktion erzeugt werden, die von der main Funktion aus aufgerufen wird. Die Gefahr, dass irgendeine andere funktion einmal zu lange braucht, ist zu groß.
Daher habe ich die impulserzeugung jetzt in den ISR verlegt.
Eine kleine Erläuterung steht im Header. Ein standardmäßiger Grundimpuls zur erhöhung der Auflösung, sowie weitere Calibrierungsfunktionen folgen.
Allerdings muss da noch irgendwo ein minimaler zufallskinken drin sein. gelegentlich muss ch mehrmals den Reset button drücken, bis das Programm Ordnungsgemäß läuft. Wenn ich den ISP entferne ist der Fehler weg.
Code:
// Servos ansteuern mit 16MHz Mega32 und 8-Bit Timer0 und Timer2 (als ms stopwatch verwendbar) 

// Die Servosimpulse werden simultan erzeugt. Die Impulsdauer jedes Servos 
// besteht nur aus einem Wert, der zwischen 0 und 255 liegen muss. Der Stellbereich liegt dann bei
// ungefähr zwischen 50 und 230. --> ~180 werte für 180 grad, also eine auflösung bis auf ein Grad.

// In der ISR wird ein 1 ms Timer2 verwendet, um einen Zähler alle 20ms zurückzusetzen und den impulsmessenden Timer0 zu starten. 
// Während Timer0 läuft ist die maximale Auslastung: alle 160 Takte ein interupt, mit maximal 100 Befehlen 63% im Durchschnitt 30% nur für den ISR
// Daher wird der Timer0 auch diret nach der Pulserzeugung gestoppt und erst ~18ms später von Timer2 aufgerufen. 
// Während der Pause läuft also nichts außer einem 1ms Timer. Viel Zeit um andere Dinge zu erldigen. 

// 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 
						//PA0 Servo 12, PB0-4 Servo 11/10/7/8/9, PC2-7 Servo 4/5/6/3/2/1, PD2-7 Servo 15/14/13/16/17/18
#define DDRAinit {	DDRA = 0b00000001;DDRB = 0b00011111;DDRC = 0b11111100;DDRD = 0b11111100;} 
#define servo1on  PORTC |=  (1<<PC7) 
#define servo1off PORTC &= ~(1<<PC7) 
#define servo2on  PORTC |=  (1<<PC6) 
#define servo2off PORTC &= ~(1<<PC6) 
#define servo3on  PORTC |=  (1<<PC5) 
#define servo3off PORTC &= ~(1<<PC5) 
#define servo4on  PORTC |=  (1<<PC2) 
#define servo4off PORTC &= ~(1<<PC2) 
#define servo5on  PORTC |=  (1<<PC3)
#define servo5off PORTC &= ~(1<<PC3) 
#define servo6on  PORTC |=  (1<<PC4) 
#define servo6off PORTC &= ~(1<<PC4) 
#define servo7on  PORTB |=  (1<<PB2) 
#define servo7off PORTB &= ~(1<<PB2) 
#define servo8on  PORTB |=  (1<<PB1) 
#define servo8off PORTB &= ~(1<<PB1) 
#define servo9on  PORTB |=  (1<<PB0) 
#define servo9off PORTB &= ~(1<<PB0) 
#define servo10on  PORTB |=  (1<<PB3) 
#define servo10off PORTB &= ~(1<<PB3) 
#define servo11on  PORTB |=  (1<<PB4) 
#define servo11off PORTB &= ~(1<<PB4) 
#define servo12on  PORTA |=  (1<<PA0) 
#define servo12off PORTA &= ~(1<<PA0) 
#define servo13on  PORTD |=  (1<<PD5) 
#define servo13off PORTD &= ~(1<<PD5) 
#define servo14on  PORTD |=  (1<<PD6) 
#define servo14off PORTD &= ~(1<<PD6) 
#define servo15on  PORTD |=  (1<<PD7) 
#define servo15off PORTD &= ~(1<<PD7) 
#define servo16on  PORTD |=  (1<<PD4) 
#define servo16off PORTD &= ~(1<<PD4) 
#define servo17on  PORTD |=  (1<<PD3) 
#define servo17off PORTD &= ~(1<<PD3) 
#define servo18on  PORTD |=  (1<<PD2) 
#define servo18off PORTD &= ~(1<<PD2) 


uint8_t servo1, servo2, servo3, servo4, servo5, servo6, servo7, servo8, servo9, servo10, servo11, servo12, servo13, servo14, servo15, servo16, servo17, servo18; 

volatile unsigned char	timer1 = 0;
volatile unsigned char 	timer2 = 0;
volatile unsigned char	signals = 0;

int main(void) 
{ 
	DDRAinit; // Datenrichtung der Servopins einstellen 
	//Timer 0
	TCCR0 |= (1 << CS00);		//normal mode, prescaler 1
	//TIMSK |= (1 << TOIE0);	//Timer0 Interrupt freigegeben (wird von timer 1 freigegeben und vorgeladen)
	//TCNT0 = 256 - 160;		//Timer0 mit 96 vorladen, 1/16MHz*160 = 10µs
	
	//Timer 2
	TCCR2 |= (1 << CS22);		//normal mode, prescaler 64
	TCNT2  = 256-250;			//Timer2 mit 6 vorladen, 64/16MHz*250=1ms
	TIMSK |= (1 << TOIE2); 	//Timer2 Interrupt freigeben
	sei();						//Interrupts freigegeben

   servo1=210; // Mittelposition 
   servo2=210; 
   servo3=210; 
   servo4=210; 
   servo5=210; 
   servo6=210; 
   servo7=210; 
   servo8=210; 
   servo9=210;
   servo10=210; 
   servo11=210; 
   servo12=210; 
   servo13=210; 
   servo14=210; 
   servo15=210; 
   servo16=210; 
   servo17=210;
   servo18=210;

   while(1) // Hauptschleife 
   { 
   } 
   return(0); 
}
SIGNAL (SIG_OVERFLOW2)		//frisst ~7% der ProzessorLeistung
{
	TCNT2 = 256 - 250;		//Timer2 mit 6 neu vorladen
	timer2++;
	if(timer2 == 20)
	{
		timer2 = 0;				//timer2 endet bei 20ms
		timer1 = 0;
		TCNT0 = 256 - 160;		//Timer0 mit 96 vorladen, 1/16MHz*160 = 10µs
		//alle Impulse starten
		servo1on;
		servo2on;
		servo3on;
		servo4on;
		servo5on;
		servo6on;
		servo7on;
		servo8on;
		servo9on;
		servo10on;
		servo11on;
		servo12on;
		servo13on;
		servo14on;
		servo15on;
		servo16on;
		servo17on;
		servo18on;
		TIMSK |= (1 << TOIE0);	//Timer0 Interrupt freigegeben
		signals = 18;			//Anzahl der laufenden Signale
	}
}

SIGNAL (SIG_OVERFLOW0)		//frisst ~95% der ProzessorLeistung
{
	TCNT0 = 256 - 160;		//Timer0 mit 96 neu vorladen
	timer1++;				//timer1 Zähler misst die impulsdauer in 10µs Schritten
							//Bei erreichen der Sollpulsdauer wird der jeweilige Impuls beendet
	if(timer1 == servo1){servo1off;signals--;}
	if(timer1 == servo2){servo2off;signals--;}
	if(timer1 == servo3){servo3off;signals--;}
	if(timer1 == servo4){servo4off;signals--;}
	if(timer1 == servo5){servo5off;signals--;}
	if(timer1 == servo6){servo6off;signals--;}
	if(timer1 == servo7){servo7off;signals--;}
	if(timer1 == servo8){servo8off;signals--;}
	if(timer1 == servo9){servo9off;signals--;}
	if(timer1 == servo10){servo10off;signals--;}
	if(timer1 == servo11){servo11off;signals--;}
	if(timer1 == servo12){servo12off;signals--;}
	if(timer1 == servo13){servo13off;signals--;}
	if(timer1 == servo14){servo14off;signals--;}
	if(timer1 == servo15){servo15off;signals--;}
	if(timer1 == servo16){servo16off;signals--;}
	if(timer1 == servo17){servo17off;signals--;}
	if(timer1 == servo18){servo18off;signals--;}
	if(signals == 0){TIMSK &= ~(1 << TOIE0);}		//Timer0 stoppen, sobald alle Impulse erzeugt sind
}
mfg WarChild