Hallo

Ich habe den Code etwas umgestrickt. Der Impuls wird nun über einen 8bit-Timer per Interrupt erzeugt. In der Servo-ISR wird zum richtigen Zeitpunkt (der ist extrem wichtig!) das einmalige Wandeln des ADC angestoßen. Wenn die Wandlung beendet ist, wird in einer ADC-ISR das Ergebniss in adc_servo gespeichert. In der Hauptschleife wird dieser Wert mit LEDs ausgegeben (für den RP6):
Code:
// Servo-Lastmessung am Steuerpin                                 9.2.2008  mic

// In der 20ms-Signalpause wird die Spannung am Steuerpin des Servos gemessen
// und ausgewertet.

#include "rblib.h"
#include "rblib.c"

uint8_t adc_pos; 				// Position des Servos
uint16_t adc_servo;        // Messwert der Signalleitung

void servo_ON(void)        // Servo-ISR starten
{
	cli();
	TCCR0 =  (0 << WGM00) | (1 << WGM01);					// CTC-Mode
	TCCR0 |= (0 << COM00) | (0 << COM01);					// ohne OCR-Pin
	TCCR0 |=	(0 << CS02)  | (0 << CS01) | (1 << CS00);	// prescaler /1
	TIMSK =  (1 << OCIE0); 										// Interrupt ein
	OCR0  = 105;

// 5V-Referenz, Kanal 0
	ADMUX = (0<<REFS1) | (1<<REFS0) | 0;
// Interrupt ein, ADC enable, prescal /16, altes Flag löschen
	ADCSRA = (1<<ADIE) | (1<<ADEN) | (1<<ADPS2) | (1<<ADIF);

	sei();
}

int main(void)
{
	rblib_init();
	adc_pos=100;			// Position der Servos
	adc_servo=0;         // Startwerte setzen
	servo_ON();          // Servo-ISR starten

	while(1)
	{
		setLEDs(adc_servo);
  	}
	return 0;
}

ISR(ADC_vect)
{
	adc_servo=ADC;                		// jetzt messen wir die Spannung!
}

ISR(TIMER0_COMP_vect)
{
	static uint16_t count=0; 				// Zykluszähler
	if (count>adc_pos)                  // Servoimpuls senden?
	{
		DDRA &= ~1;                      // nein: auf Eingang ohne PullUp
		PORTA &= ~1;
		if (count == adc_pos+100)        // seit 100 Takten auf Eingang gesetzt,
		{
		   	ADCSRA |= (1<<ADSC);      // ADC starten
		}
	}
	else
	{
		DDRA |= 1;                      // Impuls senden, Pin auf Ausgang
		PORTA |= 1;                     // und high
	}
	if(count<2000) count++; else count=0; // Zyklus fertig?
}
Hier noch eine Anwendung für einen 8MHz-Mega32 ohne RP6-Funktionen:

Code:
// Servo-Lastmessung am Steuerpin mit einem 8MHz-ATMega32         10.2.2008 mic

// In der 20ms-Signalpause wird die Spannung am Steuerpin des Servos gemessen
// und ausgewertet. Servoimpuls wird mit einem 8bit-Timer im CTC-Mode per ISR
// erzeugt. Kurz nach Ende des Impulses wird der ADC gestartet und der Messwert
// in einer ADC-ISR eingelesen.

#include <avr/io.h>			// I/O Port definitions
#include <avr/interrupt.h>	// Interrupt macros

// Position des Servos, Belastungszähler
uint8_t servo_pos;
// Messwert der Signalleitung, Verzögerung
volatile uint16_t servo_adc, servo_count, pause;

void init_servo(void)         // Servo-ISR starten
{
	cli();
	TCCR0 =  (0 << WGM00) | (1 << WGM01);					// CTC-Mode
	TCCR0 |= (0 << COM00) | (0 << COM01);					// ohne OCR-Pin
	TCCR0 |=	(0 << CS02)  | (0 << CS01) | (1 << CS00);	// prescaler /1
	TIMSK =  (1 << OCIE0); 										// Interrupt ein
	OCR0  = 105;                                       // Servomitte=100?

// 5V-Referenz, Kanal 0
	ADMUX = (0<<REFS1) | (1<<REFS0) | 0;
// Interrupt ein, ADC enable, prescaler /16, altes Flag löschen
	ADCSRA = (1<<ADIE) | (1<<ADEN) | (1<<ADPS2) | (1<<ADIF);
	sei();
}
void wait(uint8_t p)
{
	pause=p;
	while(pause);
}
int main(void)
{
	servo_pos=100;			// Position des Servos
	servo_adc=-1;         // Startwerte setzen
	init_servo();        // Servo-ISR starten
	wait(20);

	while(1)
	{
weiter2:
	   servo_pos+=2;
		servo_count=0;
    	while((servo_pos++ < 200))
		{
	   	wait(1);
	   	while(servo_count > 8)
	   	{
	   	   if (servo_count > 15) goto weiter1;
	   	}
		}
weiter1:
	   	servo_pos-=2;
		servo_count=0;
    	while((servo_pos-- > 30))
		{
	   	wait(1);
	   	while(servo_count > 8)
	   	{
	   	   if (servo_count > 15) goto weiter2;
	   	}
		}
	}
	return 0;
}

ISR(ADC_vect)
{
	servo_adc=ADC;                		// ADC-Messung beendet, Wert speichern
	if (servo_adc) servo_count++; else servo_count /=2;
	
}

ISR(TIMER0_COMP_vect)
{
	static uint16_t count=0; 				// Zykluszähler
	if (count>servo_pos)                  // Servoimpuls senden?
	{
		DDRA &= ~1;                      // nein: auf Eingang ohne PullUp
		PORTA &= ~1;
		if (count == servo_pos+100)        // seit 100 Takten auf Eingang gesetzt,
		{
		   ADCSRA |= (1<<ADSC);      		// ADC starten
		}
	}
	else
	{
		DDRA |= 1;                      // Impuls senden, Pin auf Ausgang
		PORTA |= 1;                     // und high
	}
	if(count<2000) count++; else {     // Zyklus fertig?
		count=0;
		if (pause) pause--;
	}
}
und das Video dazu:
Bild hier  
http://www.youtube.com/watch?v=39tOx0IxQ40

Der Steuerpin hängt dabei ohne weitere Beschaltung direkt am ADC-Pin. Gemessen habe ich Werte bis über 30. Direkt nach dem Impuls messe ich noch für einige Zyklen das High des Impulses, gegen Ende des Zyklus bleibt der Wert immer bei 0. Gut funktioniert's um 100, sogar mit diesem Müll-Code...

Gruß

mic