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