Hallo RP6-Fans
Zum xten mal ein Versuch eine LED als Helligkeitssensor zu verwenden. Wer das Thema schon gründlich durchgekaut hat wird hier wohl nichts neues lernen.
In einem Artikel habe ich kürzlich gelesen, LEDs haben in Sperrrichtung eine relativ große Kapazität. Dies kann man nutzen, indem man die Entladezeit der LED mißt; sie schwankt durch den Leckstrom welcher lichtabhängig ist. AHA! (Das steht auch im RN-Wissen unter Photodiode)
Das muste ich natürlich gleich mal testen: Eine LED (ohne Vorwiderstand, aber richtig gepolt!) in Sperrrichtung zwischen Pin und GND, den Pin kurz auf Ausgang/High, dann auf Eingang und Spannung einlesen. Zeit messen bis Spannung unter Schwellpegel. Je kürzer desto hell:
Das Progamm mißt die Zeit in Schleifendurchgängen. Je nach angeschlossener LED und Beleuchtung treten bei mir Werte zwischen 30 und 800 auf. Ohne Beschaltung von ADC0 und ADC1 liegt der Wertebereich zwischen 2 und weit über 4000! Und ohne LED reagiert der RP6 auf Annäherung mit der Hand oder einem Gegenstand. Ein sehr interessanter Effekt den man mal untersuchen sollte.Code:// LED-Sensor Vorbereitung zur Helligkeitsmessung mit einer LED 3.4.2008 mic // Die Pins ADC0 und ADC1 werden kurz auf High geschaltet, anschließend wird // mit dem ADC gemessen, wie lange es dauert, bis sie einen eingestellten // Spannungslevel unterschreiten. // Zum Testen der LED-Funktion kann man eine LED in Sperrichtung zwischen // Pin ADC0/1 und GND klemmen // Mit diesem Programm und mit unbeschalteten ADC0/1 (ich habe bei meinem RP6 // nur Steckerleisten angelötet) reagieren die Pins schon auf eine bloße Annäherung // mit der Hand oder einem Gegenstand. Diesen Effekt sollte man mal näher untersuchen. #include "RP6RobotBaseLib.h" uint16_t count0, count1; int main(void) { initRobotBase(); DDRA &= ~3; // Eingang ohne Pullup PORTA &= ~3; while(1) { DDRA |= 3; // Ausgang setzen PORTA |= 3; sleep(20); count0=0; DDRA &= ~1; // Eingang 0 PORTA &= ~1; // ohne Pullup while(readADC(0) > 500) count0++; count1=0; DDRA &= ~2; // Eingang 1 PORTA &= ~2; // ohne Pullup while(readADC(1) > 300) count1++; writeInteger(count0, 10); writeString_P(" - "); writeInteger(count1, 10); writeString_P("\n\r"); mSleep(300); } return(0); }
Aber zurück zu Helligkeitsmessung. LEDs messen im Bereich des Abstahlwinkels. Man könnte sie deshalb beim RP6 vielleicht besser zur Peilung verwenden als die eingebauten LDRs. Die einzigen dafür nutzbaren LEDs sind wohl die vom ACS, deshalb gleich mal ein Test mit Bordmitteln:
Das funktioniert schon mal prima, bei "Hell" werden Werte unter 10 gemessen, "Dunkel" bis zu 2000. 2000ms! Total lahm. Das liegt daran, das ich hier einen normalen Pin ohne ADC verwende. Es wird die Zeit gemessen, nach der der Pin wieder Low wird. Da die Pegel für Low- und High-Erkennung nicht identisch sind, bringt folgendes Programm eine Besserung:Code:// LED-Sensor Die ACS-LEDs werden kurz in Sperrichtung "geladen" 4.4.2008 mic // und dann wird die Entladezeit gemessen. (Kathode gegen 5V geschaltet) #include "RP6RobotBaseLib.h" int main(void) { initRobotBase(); // Beide ACS-LEDs allpollig auf GND legen DDRB |= ACS_PWRH | ACS_L; // Pins als Ausgang DDRC |= ACS_R; DDRD |= ACS_PWR; PORTB &= ~(ACS_PWRH | ACS_L); // alle auf GND PORTC &= ~ACS_R; PORTD &= ~ACS_PWR; while(1) { DDRB |= ACS_L; // Kathoden als Ausgang DDRC |= ACS_R; PORTB |= ACS_L; // Kathoden gegen 5V schalten PORTC |= ACS_R; sleep(10); // Kurz warten und Stoppuhren starten setStopwatch1(0); setStopwatch2(0); startStopwatch1(); startStopwatch2(); DDRB &= ~ACS_L; // Kathoden als Eingang DDRC &= ~ACS_R; PORTB &= ~ACS_L; // PullUps aus PORTC &= ~ACS_R; // Entladung messen while((PINB & ACS_L) || (PINC & ACS_R)) { if(!(PINB & ACS_L)) stopStopwatch1(); if(!(PINC & ACS_R)) stopStopwatch2(); } stopStopwatch1(); // sicher ist sicher! stopStopwatch2(); // Debug writeInteger(getStopwatch1(), 10); writeString_P(" - "); writeInteger(getStopwatch2(), 10); writeString_P("\n\r"); //mSleep(300); // weniger hecktisch :) } return(0); }
Hier wird nicht Vcc geschaltet sondern GND. Gemessen wird die Zeit, nach der wieder High anliegt und erzeugt werden Werte von ca. 2-200. Allerdings wird dabei nicht seitenunabhängig ausgewertet weil die PWR-Leitungen beider ACS-LEDs verbunden sind. Die unterschiedlichen Werte kommen von den PWR-Vorwiderständen (R8/9, 1k5/2k2). (Wenn man zusätzlich die PullUps als Entladewiderstand verwendet ist die Zeit == 0 ;)Code:// LED-Sensor Die ACS-LEDs werden kurz in Sperrichtung "geladen" 4.4.2008 mic // und dann wird die Entladezeit gemessen. (Anode gegen GND geschaltet) #include "RP6RobotBaseLib.h" int main(void) { initRobotBase(); // Beide ACS-LEDs allpollig auf 5V legen DDRB |= ACS_PWRH | ACS_L; // Pins als Ausgang DDRC |= ACS_R; DDRD |= ACS_PWR; PORTB |= (ACS_PWRH | ACS_L); // alle auf 5V PORTC |= ACS_R; PORTD |= ACS_PWR; while(1) { DDRD |= ACS_PWR; // Pins als Ausgang DDRB |= ACS_PWRH; PORTD &= ~ACS_PWR; // Anoden gegen GND schalten PORTB &= ~ACS_PWRH; sleep(10); // Kurz warten und Stopuhren starten setStopwatch1(0); setStopwatch2(0); startStopwatch1(); startStopwatch2(); DDRD &= ~ACS_PWR; // Anoden als Eingang DDRB &= ~ACS_PWRH; // Entladung messen while((!(PIND & ACS_PWR)) || (!(PINB & ACS_PWRH))) { if(PIND & ACS_PWR) stopStopwatch1(); if(PINB & ACS_PWRH) stopStopwatch2(); } stopStopwatch1(); // sicher ist sicher! stopStopwatch2(); // Debug writeInteger(getStopwatch1(), 10); writeString_P(" - "); writeInteger(getStopwatch2(), 10); writeString_P("\n\r"); mSleep(300); } return(0); }
Gruß
mic







Zitieren

Lesezeichen