Hallo

Die Idee: Was macht die Signalleitung des Servos, wenn kein Impuls ansteht?

Das Ergebniss: Mein RP6 erkennt, wenn ich mit dem Daumen gegen das Servohorn drücke:

Bild hier   Bild hier   Bild hier  
http://www.youtube.com/watch?v=fPnOa-c63zY
http://www.youtube.com/watch?v=ADkI8TLyGUY
http://www.youtube.com/watch?v=RDQ292-rrWc

Als Timer für das Servo dient der ADC-Interrupt. Die Steuerleitung des Servos hängt an E_INT (XBUS Pin mit 10K gegen GND. Nach dem Impuls wird der Pin auf Eingang geschaltet und etwas verzögert wird dann der Wert eingelesen:
Code:
// Servo-Lastmessung am Steuerpin                                 7.2.2008  mic

// In der 20ms-Signalpause wird die Spannung am Steuerpin des Servos gemessen
// und ausgewertet. (Servoansteuerung kompatibel zur RP6-Lib durch ADC-ISR)

#include "RP6RobotBaseLib.h"

uint8_t adc_pos, adc_count; // Position des Servos, Belastungszähler
uint16_t adc_servo;         // Messwert der Signalleitung

void servo_ON(void)         // Servo-ISR starten
{
	cli();
// Freeruning, 5V-Ref, ISR enable, prescale /16
// AVCC with external capacitor at AREF pin, Ergebniss rechtsbündig, Kanal ADC4 (E_INT)
	ADMUX = (0<<REFS1) | (1<<REFS0)  | (0<<ADLAR) | 4;
// setzte free running triggern
	SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// Interrupt ein, Wandler einschalten, prescaller /16
	ADCSRA = (1<<ADIE) | (1<<ADEN) | (1<<ADPS2) | (0<<ADPS1)  | (0<<ADPS0);
// Autotriggern bedeutet jetzt free running aktivieren, altes Flag löschen
	ADCSRA |= (1<<ADATE) | (1<<ADIF);
// Initialisierung starten
	ADCSRA |= (1<<ADSC);
// und noch die wohl eher unnötige Initiallesung
	while (!(ADCSRA & (1<<ADIF)));
	ADCSRA |= (1<<ADIF);
	sei();
}

void servo_OFF(void) // Servo-ISR stoppen
{
	cli();
	// Initialize ADC: (Defaultsetup der RP6-Library)
	ADMUX = 0; //external reference
	ADCSRA = (0<<ADIE) | (0<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADIF);
	SFIOR = 0;
	sei();
}

int main(void)
{
	initRobotBase();
	adc_pos=55;				// 20-90 ist der Drehbereich der Servos
	adc_servo=0;         // Startwerte setzen
	adc_count=0;
	servo_ON();          // Servo-ISR starten

	while(1){
		if (adc_servo)    // wenn die Messspannung größer 0 ist
		{
		   if (adc_count < 255) adc_count++; // counter hochzählen
		   if (adc_count>4) setLEDs(63);     // Schwelle für Belastung
		}
		else
		{
		   adc_count=0; // keine Belastung
		   setLEDs(0);  //
		}
		mSleep(200); // kurz warten
	}
	return 0;
}

ISR(ADC_vect)
{
	static uint16_t count=0; 				// Zykluszähler
	if (count>adc_pos)                  // Servoimpuls senden?
	{
		DDRA &= ~16;                     // nein: E_INT auf Eingang ohne PullUp
		PORTA &= ~16;
		if (count == adc_pos+100)        // seit 100 Takten auf Eingang gesetzt,
		{
			adc_servo=ADC;                // jetzt messen wir die Spannung!
		}
	}
	else
	{
		DDRA |= 16;                      // Impuls senden, Pin auf Ausgang
		PORTA |= 16;                     // und high
	}
	if(count<1000) count++; else count=0; // Zyklus fertig?
}
(Ansteuerung des Servos wie in RN-Wissen beschrieben.)

Gruß

mic