Guten Tag,
ich habe ein Problem mit dem SRF05 Ultraschallsensor. Wenn ich diesen an
meinem ATmega2560 anschliesse, braucht eine Messung etwa 20ms (min. 10 /
max. 30). Den Prozessor programmiere ich mit AVR-Studio 4 in c++.
Hier mal der der Code fuer einen Auslesevorgang
1
uint16_treadDistanceSensor(uint8_tnum)
2
{
3
DDRB|=(1<<(num+4));// set pin as output
4
TCNT3=0;
5
PORTB|=(1<<(num+4));// set pin to high
6
while(TCNT3<=100);//wait 50 us
7
PORTB&=((1<<(num+4))xor0xFF);// set pin low
8
DDRB&=((1<<(num+4))xor0xFF);// set pin as input
9
while((PINBbitand(1<<(num+4)))!=0);// wait until pin goes to 0
10
TCNT3=0;// reset timer
11
12
while(((PINBbitand(1<<(num+4)))==0)&&(TCNT3<10000));//wait for signal but not longer than 5ms
13
uint16_timpuls=TCNT3;
14
TCNT3=0;
15
if(impuls<=10000)
16
{
17
while(((PINB&(1<<(num+4)))==(1<<(num+4)))and(TCNT3<60000U));// wait up to 30ms for pin becoming low
18
impuls=TCNT3;//1ms = 2000CT, 1us=2CT
19
if(impuls>=60000U)//more than 30ms: no object in range
20
{
21
return1;
22
impuls=0;}
23
}
24
else
25
{
26
impuls=0;
27
}
28
return1.44*impuls;//????????????? so gehts; so nicht:((impuls/2)/58); //distance in cm =time in us/58
29
}
Nun habe ich mir gedacht, dass das Hauptprogramm mittels einer Interrupt
weiterlaeuft, waehrend der Sensor noch auf das Echo wartet.
Ich bin mir allerdings nicht sicher ob das ueberhaupt funktioniert.
Dazu kommt, dass der Sensor bei jedem Programmdurchlauf ausgelesen
werden soll, also sehr schnell.
Wer auf nur eine Anregung hat, soll diese bitte schreiben.
Danke fue eure Hilfe
atmega2560 und N. G. (Firma: KdS) (newgeneration) schrieben:
> Ich möchte nun, da der Auslesevorgang sehr lange dauern kann, erreichen,> dass das Hauptprogramm weiterläuft und nicht wartet.
Dann muss also sowas loswerden:
> while(TCNT3<=100); //wait 50 us
Und dann solltest du den Ablfu so umstellen, dass du eine Schleife hast,
die dauernd schnellstmöglich durchlaufen wird und die Pins abfragt. Wenn
sich ein Pin geändert hat, sieht die Funktion auf die Uhr und rechnet
sich aus, was da zwischenzeitlich passiert ist, merkt sich dann diese
Uhrzeit und läuft wieder so lange durch die Schleife, bis die nächste
Flanke auftritt...
Es wird also nicht gewartet, sondern auf Änderungen reagiert.
atmega2560 schrieb:
> return 1.44*impuls; //????????????? so gehts;
Für eine so kleine Rechenaufgabe die float-Lib einbinden?
Weißt du eigentlich, was du da gerade machst?
Probiers doch mal ganz ohne Float so: return (144*(short)impuls)/100;
erstmal danke für die schnelle Hilfe.
Hast du dir das Datenblatt angeschaut? Ich versteh zwar, was du mir
sagen willst, aber nicht wie ich das umsetzen soll.
Wärst du so freundlich mir ein Stück code zu schreiben.
das return habe ich schon umgewandelt. Leider keine große
Veränderung(war ja auch klar) xD
Danke
N. G. schrieb:> Hast du dir das Datenblatt angeschaut?
Jetzt, ja.
Das ist ja noch einfacher: du gibst einen Impuls aus und lässt dir dann
2 Pinchange-Interrupts geben. Einen, wenn du die steigende Start-Flanke
am Echo-Pin bekommst. Und einen zweiten, wenn du eine fallende
Ende-Flanke am Echo-Pin bekommst. Beim ersten der beiden Interrupts
merkst du dir den Zählerstand eines Timers, der im Idealfall pro 58us
(oder pro 5,8us) um eins hochzählt. Und beim zweiten Interrupt liest du
wieder den Zählerstand aus, subtrahierst den Anfang vom Ende und hat die
Entfernung in cm oder mm (je nachdem, ob der Timer pro 58us oder 5,8us
um 1 hochzählt).
N. G. schrieb:> Nun habe ich mir gedacht, dass das Hauptprogramm mittels einer Interrupt> weiterlaeuft, waehrend der Sensor noch auf das Echo wartet.
Als Regel sollte gelten: KEIN Hauptprogramm läuft im Interrupt.
Hauptprogramme laufen in der Hauptschleife. Interrupts werde so schnell
wie möglich abgearbeitet und mit der Hautpschleife weitergemacht.
> Wärst du so freundlich mir ein Stück code zu schreiben.
Nein. Die Reihenfolge ist anders: du machst dir Gedanken und probierst
selber mal was aus. Und dabei gibt es evtl. Probleme. Und die können
wir dann gern hier diskutieren...
> Leider keine große Veränderung(war ja auch klar) xD
Logisch, weil du garantiert irgendwo anders nochmal so einen unnötige
float-Operation drin hast...
N. G. schrieb:> nun mein verkürtzter code, allerdings noch ohne Interrupts.> ... // wait until pin goes to 1
Du musst da nicht irgendwie irgendwelche Interrupts einfügen, du musst
das komplette Softwarekonzept ändern, da hilft eine Makulatur wie
"Code verkürzen" nichts...
wie müsste ich die methode denn umschreiben(ich habe von Interrupts
noch nicht so viel Ahnung)
eig. möchte ich mein Programm nicht online stellen, da es konkurrenten
hrunterladen könnten
Also, ich grab diesen Thread noch mal aus;
ich habe mich jz wieder hingesetzt und an dem Problem weitergearbeitet;
nun habe ich auch einen besseren Ansatz:
Der Timer, sowie, die PC-Interrupts werden so konfiguriert:
(16 MHz)
1
TCCR5B=(1<<WGM02)|(1<<CS51);//eneble Timer5(16bit) - CTC; prescaler 8 => every 0,5us
2
OCR5A=116;//every 58us
3
TIMSK5=(1<<OCIE5A);//enable timer 5 overflow
4
TCNT5=0;
5
PCICR=(1<<PCIE0);// enable PCINT7:0
6
PCMSK0=(1<<PCINT1);// enable PCINT 1
Der Rest, der die Ultraschallsensoren betrifft:
1
ISR(PCINT0_vect)
2
{
3
if(PINB&(1<<PB1))//pin changed to high
4
{
5
usVal=TCNT5;
6
}
7
elseif(!(PINB&(1<<PB1)))//pin changed to low
8
{
9
us=TCNT5;
10
}
11
}
12
ISR(TIMER5_COMPA_vect)
13
{
14
TCNT5++;
15
}
Die Variablen usVal(also der Startwert, uint16_t) und us(Endwert, auch
uint16_t) sind volatile.
Eigentlich wurden auch die Interrupts während dem Auslösen des
Messvorgangs(Pin für 50us auf High) gesperrt:
1
PCMSK0&=~(1<<PCINT1);
2
DDRB|=(1<<PB1);
3
PORTB|=(1<<PB1);
4
_delay_us(50);
5
PORTB&=~(1<<PB1);
6
DDRB&=~(1<<PB1);
7
PCMSK0|=(1<<PCINT1);
Aber die Sensoren liefern keine sinnvollen Ergebnisse. Leider habe ich
kein Oszi, nur ein LCD, also keine sehr genauen Zeitangaben.
Hat jemand eine Idee, was ich falsch mache?
Weiter Infos gebe ich natürlich gerne ;)
Okay, hat sich erledigt.
Die Lösung war:
Den Dragon bzw. AVR ISP mkII abstecken. So verrückt es klingt. Die
Clock-Leitung liegt genau auf dem Pin Für den Ultraschall. Leider wurde
dadurch der Wert bis zur unkenntlichkeit verfälscht..