Hallo robo.fr
Wie du ja weißt habe ich mit der IR-Abstandsmessung auch schon gespielt. Letztlich habe ich dann einen mit Folie beschichteten "Reflektor" gebastelt und ihn unter den Kabelbinder des Motors geklemmt:
Bild hier
Und noch ein Video dazu:
Bild hier
http://www.youtube.com/watch?v=6-5pah_oQUw
Ganz wichtig dabei ist ein lichtdichtes Irgendwas (Karton, Folie, aufgeschnittener Schrumpfschlauch...) zwischen den IR-Empfänger und die Platine zu klemmen und es seitlich hoch zwischen Empfänger und IR-LED zu biegen um "Kriechlicht" zu verhindern!
Der "Rüssel" auf der IR-LED besteht aus mehreren Lichtwellenleitern (ca. 1€/Meter) in einem Schrumpfschlauch und dient der Bündelung des Lichtstrahls. Es funktioniert aber auch ohne recht gut, aber nicht so scharfkantig.
Hier noch der Code MIT Kantensuchen (ich hoffe, er funktioniert noch):
Code:
/* asuro haelt mittels IR-Messung vorgewaehlten
Abstand zu einem Gegenstand und richtet sich dabei nach einer Kante aus.
14.2.2007 mic
*/
#include "asuro.h" // Version mit dutycycles und TOIE2 in Init() (ab ca. v2.5)
unsigned char i, ir_bits, dist, dir_l, dir_r; // zaehler, bitzaehler, abstand, richtungen
unsigned int bitspeicher, delay; // filter, rythmus
int main(void)
{
Init();
MotorDir(FREE,FREE); // Stillstand vorbelegen
MotorSpeed(150,150); // je mehr desto hektisch
bitspeicher = 1; // 16 Bits Filter für IR-Echos
dist=240; // Sollabstand (zw. 0x90 und ca.250, je groesser desto nah)
delay=Gettime(); // Rythmus fuers Kantensuchen
while (1) {
// vor und zurueck
DDRD |= (1 << DDD1); // IR-LED an
PORTD &= ~(1 << PD1);
OCR2 = dist; // gewuenschter Abstand
bitspeicher = bitspeicher*2+(PIND & (1 << PD0));
ir_bits=0; // bei diesem Abstand soll auf 2 von 8 Nicht-Echos gefahren werden
for (i=0; i<8; i++) if (bitspeicher & (1 << i)) ir_bits++; // letzte 8 Echos
dir_l=dir_r=FREE;
if (ir_bits > 4 ) dir_l = dir_r = FWD; // mehr als zweimal kein Echo = zu weit
if (ir_bits < 2 ) dir_l = dir_r = RWD; // weniger als zwei Nicht-Echos = zu nah
MotorDir(dir_l,dir_r); // Abstand korrigieren
if (Gettime() >= delay) { // mehr als eine Sekunde seit dem letzen Suchen der Kante
// nach links drehen bis kein Echo mehr kommt
if ((dir_l) == (FWD)) { // bei Vorwaertsfahrt
dir_l = FREE; dir_r = FWD;
} else if ((dir_l) == (RWD)) { // bei Rueckwaertsfahrt
dir_l = RWD; dir_r = FREE;
} else { dir_l=FWD; dir_r=RWD; }; // im Stillstand
MotorDir(dir_l,dir_r);
//MotorDir(RWD,FWD);
DDRD |= (1 << DDD1); // IR-LED an
PORTD &= ~(1 << PD1);
OCR2 = 0x90; // maximale Distanz
do {
bitspeicher = bitspeicher*2+(PIND & (1 << PD0)); // Bitspeicher fuellen
ir_bits=0;
for (i=0; i<16; i++) if (bitspeicher & (1 << i)) ir_bits++;
} while (ir_bits < 15); // alle Bits gesetzt bedeutet keine Echo = Kante ueberfahren
// rechts drehen und mit Soll-Distanz nach Echo suchen (sicherheitshalber mehrfach!)
if ((dir_l) == (FREE)) { // abhaengig von verwendeter Methode zurückschwenken
dir_l = FWD; dir_r = FREE;
} else if ((dir_r) == (FREE)) {
dir_l = FREE; dir_r = RWD;
} else { dir_l=RWD; dir_r=FWD; };
MotorDir(dir_l,dir_r);
//MotorDir(FWD,RWD);
DDRD |= (1 << DDD1); // IR-LED an
PORTD &= ~(1 << PD1);
OCR2 = dist; // Messdistanz laden
for (i=0; i<10; i++) { //mehrfach pruefen und gegebenfalls fahren um die Kante sicher zu finden
bitspeicher=1; // alle Bits geloescht bedeutet volles Echo = Kante wiedergefunden
do bitspeicher = bitspeicher*2+(PIND & (1 << PD0)); while (bitspeicher != 0);
//for (bitspeicher=1; bitspeicher != 0; bitspeicher*2+(PIND & (1 << PD0)));
}
if (((dir_l) != (FREE)) && ((dir_r) != (FREE))) MotorDir(FREE,FREE); // anhalten oder durchstarten
//MotorDir(FREE,FREE);
delay=Gettime()+500; // einmal pro Sekunde die Kante suchen
}
} // endloss
while(1); return 0;
}
Der asuro hält den vorgegebenen Abstand zum Blatt und richtet sich nach der linken Blattkante aus. Die IR-Echos werden gefiltert und erst nach einer festgelegten Anzahl von Echos/Nichtechos wird reagiert. Achtung, die verwendete asuro-Lib muss die IR-Erweiterung nach Waste enthalten und den Timer zur IR-Pulserzeugung folgendermaßen Initialisieren:
Code:
//-------- seriell interface programmed in boot routine and already running -------
// prepare 36kHz for IR - Communication
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
OCR2 = 0x91; // duty cycle for 36kHz
TIMSK |= (1 << TOIE2); // 36kHz counter for sleep
(aus Init() in asuro.c ab ca. 2.5)
Wenn man OCR2 ändert, kann man nicht mehr per IR mit dem Terminal kommunizieren, weil die 36kHz-Trägerfrequenz nicht mehr stimmt. Zuvor muss man wieder den Defaultwert (OCR2 = 0x91) wieder laden.
wie gehts dem ASURO Motortreiber? Laufen die Motoren schon wieder?
Er ist leider immer noch "krank", ich hatte noch keine Zeit danach zu schauen.
Gruß
mic
Lesezeichen