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
Lesezeichen