PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Asuro mit Ultraschallmodul ARX-ULT10



TEL12AT
18.04.2015, 16:20
Hey Leute,

ich bin gerade dabei das Ultraschallmodul von ARX auszutesten. Das ganze funktioniert aber noch nicht.
Hat jemand schon einmal den Bausatz erfolgreich verwendet mit den bereitgestellten Funktionen aus der Asuro-Bib?
Ich habe nämlich die Vermutung, dass das ultrasonic-Modul noch nicht ganz ausgereift ist.


void InitUltrasonics(void)
{
// Change Oscillator-frequency of Timer 2
// to 40kHz, no toggling of IO-pin:
cli();
#if defined(__AVR_ATmega168__)
// fast PWM, set OC2A on compare match, clear OC2A at bottom, clk/1
TCCR2A = _BV(WGM21);
TCCR2B = _BV(CS20);
// interrupt on timer overflow
TIMSK2 &= ~_BV(TOIE2);
TIMSK2 |= _BV(OCIE2A);
#else
TCCR2 = _BV(WGM21) | _BV(CS20);
TIMSK &= ~_BV(TOIE2);
TIMSK |= _BV(OCIE2); // OCIE2: Timer/Counter2 Output Compare Match Interrupt Enable
#endif
// 40kHz carrier/timer
OCR2 = 100;

ADCSRA = 0; // deactivate ADC
ACSR |= _BV(ACIS1); // Comparator Interrupt on Falling Output Edge

ADMUX = 0x03; // connect ADC3-input with comparator
#if defined(__AVR_ATmega168__)
ADCSRB |= _BV(ACME); // connect ADC multiplexer to comparator
#else
SFIOR |= _BV(ACME); // connect ADC multiplexer to comparator
#endif
DDRD &= ~_BV(6); // use Port D Pin 6 as input (AIN0)
sei();
}

Diese Funktion verwende ich für die Initialisierung. Bevor diese aufgerufen wird, wird noch die normale Init() Funktion ausgeführt.
Mit der InitUltrasonics() will man doch den CTC-Mode aktivieren ohne Prescaler um auf 40kHz zu kommen und diese Frequenz mit dem Register OCR2 während dem Chirp verändern.
Aber so wie die Register momentan gesetzt werden, wird kein CTC-Mode aktiviert oder? Das TCCR2 Register wurde doch schon durch die "normale" Init() Funktion auf PWM gesetzt. Jetzt müsste man doch zuert einmal das komplette Register auf 0 setzen und dann die Bits für CTC-Mode setzen oder? Außerdem kann das mit der Zeitmessung also Sleep() doch auch nicht mehr funktionieren wenn die Frequenz auf 40 KHz bzw. 20 KHz umgestellt wurde ( weil doch jeder Compare Match den Counter hochzählt)? Wie kommt man dann bei der Distanzberechnung auf 72?? Vielleicht könnt ihr ja etwas Licht ins Dunkle bringen. Das wäre echt nett :)


Chirp Funktion:

int Chirp(void)
{
unsigned int sleeptime = 0, dist = 0;

InitUltrasonics();

// chirpen:
count36kHz = 0;

while(count36kHz != 20) {
OCR2 = 100 + 20 / 2 - count36kHz;
}

#if defined(__AVR_ATmega168__)
TCCR2A = _BV(WGM21);
TCCR2B = _BV(CS20);
#else
TCCR2 = _BV(WGM21) | _BV(CS20);
#endif
OCR2 = 100;

// analyse echoes:
while(TRUE) {
Sleep(1);
sleeptime++;

if((ACSR & _BV(ACI))) {
dist = (unsigned int) ((long) ((344L * ((sleeptime * 1000L) / 72L) / 10000L) / 2L));
ACSR |= _BV(ACI);
break;
}

ACSR |= _BV(ACI);

if(sleeptime > 3500) {
return -1;
}
}

RestoreAsuro();
return dist;
}

Interrupt Service Routine für Compare Match

#if defined(__AVR_ATmega168__)
SIGNAL(TIMER2_COMPA_vect)
#else
SIGNAL(TIMER2_COMP_vect)
#endif
{
count36kHz++;
if (!count36kHz)
timebase ++;
}

radbruch
18.04.2015, 21:48
Hallo

Willkommen im RN-Forum. Eine hübsche Nuss gibst du uns hier in deinem ersten Beitrag zum Knacken. Ich kann deine Fragen nur "theoretisch" beantworten, weil ich das Ultraschall-Modul nicht besitzen. Aber ich kann mal den Anfang machen:

TCCR2 = _BV(WGM21) | _BV(CS20); // Timer 2 im CTC-Mode, Takt ohne Prescaler, Normal port operation, OC2 disconnected? (siehe Edit)
TIMSK &= ~_BV(TOIE2); // Overflow-Interrupt aus
TIMSK |= _BV(OCIE2); // Compare-Interrupt einschalten

Durch das "=" in "TCCR2 =" wird das alte Setup von TCCR2 überschrieben. count36kHz wird in der neuen CTC-ISR hochgezählt, die Zeitbasis für sleep() ist nun aber 80kHz und nicht 36kHz. Wie genau die 40kHz an den OC2 kommen kann ich im Moment noch nicht sagen. Der Pin sollte bei 80kHz (8MHz/100) wohl getoggelt werden (COM 21:20 = 0:1), im TCCR2 wird OC2 aber auf "nicht verbunden" gesetzt (COM 21:20 = 0:0). Das sollten wir wohl noch klären...

count36kHz = 0;

while(count36kHz != 20) {
OCR2 = 100 + 20 / 2 - count36kHz;
}

Das erzeugt 10 Impulse mit ansteigender Frequenz von OCR2=110 bis OCR2=90. Das erscheint mir im Moment noch etwas fragwürdig, vielleicht klärt sich das im Verlaufe dieses Threads.

Nun zur Auswertung. Der ADC wird ausgeschaltet, der AC wird aktiviert. ACME in ADCSRB wird gesetzt, deshalb wird nicht mit AIN1 sondern mit PC3 (ADMUX=3, vermutlich Eingang vom Ultraschall anstelle von Liniensensor T9) verglichen. Vergleichspin AIN0 ist der Pin der LineLED PD6, der wird im Setup auf Eingang gesetzt, möglicherweise ist der aber vom Ultraschallmodul mit einer Referenzspannung versorgt:

ADCSRA = 0; // deactivate ADC
ACSR |= _BV(ACIS1); // Comparator Interrupt on Falling Output Edge

ADMUX = 0x03; // connect ADC3-input with comparator
SFIOR |= _BV(ACME); // connect ADC multiplexer to comparator
DDRD &= ~_BV(6); // use Port D Pin 6 as input (AIN0)

Nach dem Senden des Ultraschall-Signals wartet der asuro auf ein Echo. Gemessen wird die Laufzeit des Signals, erkennbar am gesetzten ACI-Bit in ACSR mit if((ACSR & _BV(ACI))). Und hier kommen wir dann auch zur ominösen Formel:

dist = (unsigned int) ((long) ((344L * ((sleeptime * 1000L) / 72L) / 10000L) / 2L));

344 soll wohl die Schallgeschwindigkeit in Luft sein, 72 ist möglicherweise ein Überrest der 72kHz Urlibrary. Der Rest ist wohl das Ergebniss einiger Versuche. Da sleeptime in der while(TRUE)-Schleife völlig unabhängig von irgendwelchen Timer-Ticks erhöht wird, kann man die Einheit pro Sekunde wohl nur mit dem Asemblerlisting des kompilierten Programms erahnen. Aber nur so kann die Laufzeit mit möglichst hoher Auflösung gemessen werden.

Das count36kHz deutet darauf hin, dass zumindest eine neuere Version der Library (so ab V2.3 ca.) verwendet werden sollte. Meine Ausführungen beziehen sich auf den Mega8 und sind ohne Gewähr, denn ich habe keine praktische Erfahrungen mit dem Ultraschall-Modul.

Gruß

mic

Edit: OC2 ist wohl gar nicht verbunden, das TCCR2 wird ja im Setup für das Ultraschall mit COM21:20 = 0:0 geladen! Seltsam..
Edit2: Ich bin echt aus der Übung:

Sleep(1);
sleeptime++;

So wird sleeptime mit dem Timer syncronisiert. Dann gibt die Formel vielleicht auch Sinn. Die 72 sollte dann wohl 80 sein, /2 kommt noch dazu, weil es sonst nicht passt...

TEL12AT
19.04.2015, 14:37
Hey,

danke für die schnelle Antwort erst einmal :)


Mit den Registern geb ich dir Recht da fehlt was :

TCCR2 = _BV(WGM21) | _BV(CS20)| _BV(COM20); //CTC Mode , no Prescaling



Das mit der veränderlichen Frequenz (OCR2 von 90 bis 110) soll die Messung verbessern da sich zeitgleich eintreffende Echos anscheinend nichtmehr destruktiv überlagern können (S.99 Asuro Buch Band 1)


Die Distanzformel hab ich glaube ich auch entschlüsselt :D

Wenn wir wie du gesagt hast anstatt 72 80 nehmen gibt das Sinn.

Die ursprüngliche Formel ist ja x=1/2 v * t (v=344 m/s)

Jetzt zu unsrer:

distanz = 344 * (sleeptime/80kHz) * 100 [cm]

Ich hab bisschen was rausgekürzt aber so müsste es passen


Ich teste das Ganze jetzt mal aus und hoffe das einfach mal irgendwas funktioniert sonst hab ich vielleicht auch noch nen Hardware-Fehler :D
Ich geb dann Bescheid.

Grüße