PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit Ultraschall und Infrarot gelöst



r0b3n
30.08.2006, 12:24
Moinmoin,

Ich habe mir letzte Woche den Ultraschallaufsatz für den Asuro nach der Anleitung von Lutz Mager gebaut (das geht übrigens auch ganz gut ohne die offizelle Erweiterungsplatine).
Als ich mit der Hardware fertig war, wollte ich das natürlich gerne testen, und das Beispielprogramm hat direkt mal versagt. Grade zum Kalbibrieren des Potis ist es in der Urform reichlich ungeeignet. Also dachte ich mir: geb ich mir die Entfernungsdaten doch einfach per Infrarot aus. Gesagt getan - intToString und SerWrite reingekloppt und gestartet und... nix! ](*,) Nach längerem Rumprobieren ist mir irgendwann mal aufgefallen, das für den Ultraschallsensor der interne Takt verstellt wird, und zwar direkt in der Init-Methode sowie bei jedem Ping.

Ich habe das jetzt so umgebaut, dass Ultraschall und IR gleichzeitig funktionieren ohne sich in die Quere zu kommen.



void localInit(void)
{
// Change Oscillator-frequency of Timer 2
// to 40kHz, no toggling of IO-pin:
// bad@init: TCCR2 = (1 << WGM21) | (1 << CS20);
// bad@init: OCR2 = 0x64; // 40kHz @8MHz crystal


ADCSRA = 0x00; // ADC off
// Analog comparator:
ACSR = 0x02; // Generate interrupt on falling edge
ADMUX = 0x03; // Multiplexer for comparator to
// ADC pin 3
SFIOR |= (1 << ACME); // Enable muliplexing of comparator
DDRD &= ~(1 << 6); // Port D Pin 6 is input!
}


unsigned int ping(unsigned char length)
{
unsigned int posmarker = 0;
int pos;

OCR2 = 0x64; // 40kHz @8MHz crystal
count72kHz = 0;
TCCR2 = (1 << WGM21) | (1 << COM20) | (1 << CS20); // Toggling of IO-Pin on


// generate the Chirp
while(count72kHz < length) {
OCR2 = 0x64 + length / 2 - count72kHz;
}

//TCCR2 = (1 << WGM21) | (1 << CS20); // Toggling of IO-Pin off
TCCR2 = (1 << WGM21) | (1 << COM20) | (1 << CS20); // This seems to work better

OCR2 = 0x64; // set frequency to 40kHz

for(pos = 0; pos < 100; pos++) {
Sleep(10);
if((ACSR & (1 << ACI)) != 0) {
if(posmarker == 0) { posmarker = pos; }
}
ACSR |= (1 << ACI);
}
OCR2 = 0x6E; // reset crystal to 36kHz @8MHz

return posmarker;
}


Einige der original Einstellungen sind noch als Kommentare vorhanden.

localInit() ruft man einmalig auf, ping(20) gibt einen Wert äquivalent zur Entfernung zum nächsten Hinderniss aus (hoffentlich) bzw 0 wenn keines erkannt worden ist. Ein Wert von 4-5 entspricht ca. 10 cm.

Da ich mit den Registern des Atmel nicht so vertraut bin, hoffe ich, dass das alles noch standardkomform ist!

Ich erreiche mit dem Ultraschall unter guten Bedingungen (Hinderniss groß und orthogonal zum asuro) eine Reichweite von ca. 2m.

Ich hoffe, ich kann ein paar Leuten mit dem Code Zeit und graue Haare ersparen!

Anmerkung: Mir ist aufgefallen, dass im Beispielcode nur auf eine Entfernung >12 überprüft wird, 0 aber nicht. Ist das nur bei mir so, dass der Wert 0 auftritt oder haben die das einfach vergessen?

Edit:
Ich sehe grade, dass "TCCR2 = (1 << WGM21) | (1 << COM20) | (1 << CS20);" in der ping-Methode doppelt steht. Das zweite kann man wahrscheinlich dann weglassen ;-)