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 Pinmit 10K gegen GND. Nach dem Impuls wird der Pin auf Eingang geschaltet und etwas verzögert wird dann der Wert eingelesen:
(Ansteuerung des Servos wie in RN-Wissen beschrieben.)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? }
Gruß
mic







Zitieren

Lesezeichen