PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Abfrage Ultraschallsensor HC-SR04 unter BASCOM



JoeM1978
11.11.2012, 10:18
Hey... ich habe ein MyAVR board und möchte die Werte vom Ultraschallsensor erstmal testweise abfragen.
Bin im Bereich microcontroller eher noch Blutiger Anfänger und versuch durch "Probieren" mir das
eine oder andere Beizubringen.

Dazu hab ich ein kurzes Programm aufgesetzt.
Leider hat sich irgendwo ein Fehler eingeschlichen und ich find den nicht.

Generell ist es so gedacht, das bei steigender Flanke vom Echo in einem Interrupt der Timer gestartet wird
und mir die Länge des Echos als Zeitwert ans Programm übergibt.

Könnt ihr bitte mal durchschauen, was ich da falsch hab.


'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Programmname: Sensorabfrage.bas
'Letzte Änderung: 11.11.2012
'Funktion: Abfrage des Ultraschallsensor HC-SR04
'Mikrocontroller: Mega8
'
'Input: D2 - Echosignal
'
'Output: C0 - Triggersignal
'
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Den Atmega mit den passenden Daten füttern.
'-------------------------------------------------------------------------------
$regfile = "m8def.dat" 'eingesetzter Mikrocontroller
$crystal = 3686400 'eingestellte Taktfrequenz(externes Quarz)
$hwstack = 40 'Standardwert
$swstack = 32 'Standardwert
$framesize = 60 'Standardwert
'-------------------------------------------------------------------------------
'Ports/Pins konfigurieren.
'-------------------------------------------------------------------------------
Config Portc.0 = Output
Config Pind.2 = Input

'-------------------------------------------------------------------------------
'Timer/OCR/PWM usw. setzen
'-------------------------------------------------------------------------------
Config Timer0 = Timer , Prescale = 1024

Config Int1 = Rising
Enable Int1
Enable Interrupts
On Int1 Pulsbeginn

'-------------------------------------------------------------------------------
'Variablen
'-------------------------------------------------------------------------------
Dim Entfernungcm As Long
Dim Zeitecho As Byte

'-------------------------------------------------------------------------------
'Hauptprogramm
'-------------------------------------------------------------------------------

Do

Timer0 = 0
Portc.0 = 0
Delay
Portc.0 = 1
Waitus 15
Portc.0 = 0
Print Zeitecho
Waitms 150

Loop

End

Pulsbeginn:
Timer0 = 0
Start Timer0
Do
Waitms 1
Loop Until Pind.2 = 0
If Timer0 < 200 Then
Zeitecho = Timer0
Else
Zeitecho = 0
End If
Stop Timer0

Return

Searcher
11.11.2012, 11:15
Hallo,
was geht denn nicht?

Folgende Dinge sind mir aufgefallen:
Du konfigurierst INT1 - auf PD2 ist aber INT0
CONFIG TIMER0 startet den Timer schon mit Angabe von Prescale. Wenn er nicht laufen soll, STOP TIMER0 und wenn er wieder laufen soll START TIMER0 (Sollte aber hier keine Rolle spielen)
Mit dem Prescaler 1024 wird der Timer0 mit 3600Hz getaktet, entspricht Periodendauer von ca 280µs. Das wäre dann die Auflösung für die Längenmessung des zurück kommenden Signals. Kommt mir etwas grob vor.
Welche Entfernung möchtest Du messen? Was erwartest Du als Ausgabewert? Mit einem paar Kommentaren zu Deinen Gedanken in den Programmzeilen, würde man sich besser zurechtfinden.

Gruß
Searcher

JoeM1978
11.11.2012, 11:44
Ja, da hast natürlich recht... das mit dem Pin hab ich vermurkst beim hin und hertesten.
Hab das angepasst und auch den Prescale mal auf 1 gesetzt.
Das Programm soll ja erstmal ausser sichtbare Werte abzugeben garnix können.
Ich würde mir wünschen, das zumindest im Controllcenter (also über den Print-Befehl) brauchbare werte
angezeigt werden, über die man dann die Entfernung berechnen kann.

Ich muss mir ausserdem noch recht überlegen, wie ich den Wert umgerechnet bekomm auf ein anständiges ergebniss.
Ich hab den eindruck, das das abarbeiten des Programms irgendwie die werte verfälscht.

ich bekomm zwar werte im bereich von grob 0 bis 200... aber die sind so extrem ungenau bzw wechseln in riesigen schritten(stellenweise 30-40).

Edit: Ich hab noch die Zeitmessung im Interrupt umgestellt vom ms auf us... das sollte sicher auch die Messgenauigkeit erhöhen.
Bin mir nur nicht ganz sicher, wielange das abarbeiten der befehle dauert. Das nehm ich aber erstmal als "Tolleranz" hin.

Hier das Ausgebesserte und dokumentierte Programm:


'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Programmname: Sensorabfrage.bas
'Letzte Änderung: 11.11.2012
'Funktion: Abfrage des Ultraschallsensor HC-SR04
'Mikrocontroller: Mega8
'
'Input: D2 - Echosignal
'
'Output: C0 - Triggersignal
'
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Den Atmega mit den passenden Daten füttern.
'-------------------------------------------------------------------------------
$regfile = "m8def.dat" 'eingesetzter Mikrocontroller
$crystal = 3686400 'eingestellte Taktfrequenz(externes Quarz)
$hwstack = 40 'Standardwert
$swstack = 32 'Standardwert
$framesize = 60 'Standardwert
'-------------------------------------------------------------------------------
'Ports/Pins konfigurieren.
'-------------------------------------------------------------------------------
Config Portc.0 = Output ' Trigger-Signal zum Sensor
Config Pind.2 = Input ' Echo-Signal vom Sensor

'-------------------------------------------------------------------------------
'Timer/OCR/PWM usw. setzen
'-------------------------------------------------------------------------------
Config Timer0 = Timer , Prescale = 1

Config Int0 = Rising
Enable Int0
Enable Interrupts
On Int0 Pulsbeginn ' Wenn auf echo gewartet wird wechselt Echo-Signal auf High für max 200ms

'-------------------------------------------------------------------------------
'Variablen
'-------------------------------------------------------------------------------
Dim Entfernungcm As Long
Dim Zeitecho As Long ' Gemessene dauer bis Echo ankommt

'-------------------------------------------------------------------------------
'Hauptprogramm
'-------------------------------------------------------------------------------

Do

Timer0 = 0 ' Timer und Triggerport kurz auf 0 setzen
Portc.0 = 0
Delay
Portc.0 = 1 ' Triggerport für 10us Highpegel um messung zu starten
Waitus 15
Portc.0 = 0
Print Zeitecho ' Ausgabe der gemessenen Dauer
Zeitecho = 0
Waitms 50 'Messintervall bzw Pause einstellen

Loop

End

Pulsbeginn:
'Timer0 = 0 ' bei Pulsebeginn Timer auf 0 setzen und starten
Start Timer0
Do
Waitus 10
Loop Until Pind.2 = 0 ' warten bis Echo signal ankommt, dann wechselt der Pegel auf Low
'If Timer0 < 200 Then ' wenn kein echo gemessen wird bleibt der pegel 200ms auf High
Zeitecho = Timer0 ' Gemessene Dauer an Variable übergeben
'Else
'Zeitecho = 0 ' wenn kein echosignal gemessen wird Variable auf 0 setzen bzw. lassen
'End If
Stop Timer0

Return

Searcher
11.11.2012, 12:28
Ich hab den eindruck, das das abarbeiten des Programms irgendwie die werte verfälscht.

ich bekomm zwar werte im bereich von grob 0 bis 200... aber die sind so extrem ungenau bzw wechseln in riesigen schritten(stellenweise 30-40).

Du solltest Dir einen idealen Testaufbau machen. zB Abstand vom SR04 bis zur Wand - 50 cm, und für freie Ausbreitung sorgen - keine horizontale Tischplatte dazwischen, und dann anhand des Datenblattes zum SR04 ausrechnen, welche Werte da eigenlich ausgegeben werden müßten. Welche werden dann tatsächlich ausgegeben.

Damit könnte man das Programm dann mal näher unter die Lupe nehmen.

Delay, waitus sind nicht sehr genau in BASCOM - sollten aber immer gleich funktionieren. Der Mega8 hat auch einen ICP. Könntest auch mal über dessen Verwendung nachdenken.
http://www.rn-wissen.de/index.php/Timer/Counter_%28Avr%29#Input_Capture

Gruß
Searcher

JoeM1978
12.11.2012, 19:47
So... nachdem ich bis heute nacht um 2 an dem Problem gesessen bin kam mir die Erleuchtung.
Ich hatte ständig wechselnde werte obwohl sich der Abstand nie geändert hatte.
Das lag daran, das der Timer0 nur bis 255 geht und ich aber das Vielfache an Ticks zu zählen hab.
Der war also ständig am Überlaufen.

Also hab ich versucht den Timerüberlauf abzufragen... das hat allerdings nicht funktioniert, da das programm wohl die routine im Interrupt
bevorzugt abarbeitet und der Überlauf nicht wirklich gerechnet wird.

Also hab ich mir einen "manuellen Timer-Überlauf" gemacht innerhalb der Interrupt-Routine.
Dieser wird einfach um 1 erhöht sobald der Timer bis 50000 gezählt hat. Danach wird der Timer wieder auf 0 gestellt und beginnt von vorne.
Dazu gleich den Timer1 verwendet, der eine viel höhere Zählkapazität hat.

Das Ergebnis liefert jetzt soweit ich das sehe recht genaue Werte proportional zum Abstand Sensor<>Gegenstand.
(Und ist dazu noch recht übersichtlich)

Was mir nun noch fehlt ist die genaue Umrechnung in einen Entfernungswert (cm) mit grrsstmöglicher Genauigkeit.

Leider musste ich dabei feststellen, das dividieren in Bascom (speziell noch mit 2 stellen nach dem Komma)
für meine bisherigen Kenntnisse sehr schwer scheint.

Vieleicht kann mir da noch jemand den passenden Anstoss geben.



'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Programmname: Sensorabfrage.bas
'Letzte Änderung: 11.11.2012
'Funktion: Abfrage des Ultraschallsensor HC-SR04
'Mikrocontroller: Mega8
'
'Input: D2 - Echosignal
'
'Output: C0 - Triggersignal
'
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Den Atmega mit den passenden Daten füttern.
'-------------------------------------------------------------------------------
$regfile = "m8def.dat" 'eingesetzter Mikrocontroller
$crystal = 8000000 'eingestellte Taktfrequenz(externes Quarz)
$hwstack = 100 'Standardwert
$swstack = 100 'Standardwert
$framesize = 100 'Standardwert
'-------------------------------------------------------------------------------
'Ports/Pins konfigurieren.
'-------------------------------------------------------------------------------
Config Portc.0 = Output ' Trigger-Signal zum Sensor
Config Pind.2 = Input ' Echo-Signal vom Sensor

'-------------------------------------------------------------------------------
'Timer/OCR/PWM usw. setzen
'-------------------------------------------------------------------------------
Config Timer1 = Timer , Prescale = 1 'ergibt 8.000.000 ticks ??
Config Int0 = Rising ' Interrupt bei Steigender Flanke am Echosignal starten
On Int0 Pulsbeginn '
Enable Int0 'Wenn auf Echo gewartet wird wechselt Echo-Signal auf High
Enable Interrupts '

'-------------------------------------------------------------------------------
'Variablen
'-------------------------------------------------------------------------------
Dim Zeitecho As Long 'Gemessene dauer bis Echo ankommt
Zeitecho = 0
Dim Entfernungcm As Long
Entfernungcm = 0
Dim Ueberlaufsumme As Long ' Die überläufe und den einzelnen Timerwert addieren
Ueberlaufsumme = 0
Dim Ueberlauf As Long ' Manueller Ueberlauf
Ueberlaufsumme = 0

'-------------------------------------------------------------------------------
'Hauptprogramm
'-------------------------------------------------------------------------------
Do
Ueberlaufsumme = Ueberlauf * 50000 ' Anzahl ticks der Zeitmessung zusammenrechnen
Zeitecho = Ueberlaufsumme + Timer1 '

Print Zeitecho 'Ausgabe des Wertes

Ueberlauf = 0 ' Vor Beginn der Neuen Messung alle
Ueberlaufsumme = 0 ' Variablen auf 0 setzen
Zeitecho = 0 '
Timer1 = 0 '

Portc.0 = 1 ' Triggerport für mind. 10us Highpegel um messung zu starten
Waitus 10 '
Portc.0 = 0 ' Bei wechsel des Triggersignals auf 0 beginnt der sensor die Messung

Waitms 20 ' Messintervall bzw Pause einstellen
Loop

End

'-------------------------------------------------------------------------------
'Interrupt
'-------------------------------------------------------------------------------

Pulsbeginn: ' Starten der Zeitmessung sobald echo auf High wechselt
Start Timer1 ' Zeitmessung, wielange Echosignal dauert
Do
If Timer1 = 50000 Then ' Manueller Timer-Überlauf
Ueberlauf = Ueberlauf + 1 ' Überläufe Zählen
Timer1 = 0 ' nach zählen des Überlaufs Timer wieder reseten
End If
Loop Until Pind.2 = 0 ' Zeit solange messen, bis Echo-Signal wieder zu LOW wechselt
Stop Timer0
Return

Soweit schonmal vielen dank für die Tips... hat mich letztendlich doch auf ne Lösung gebracht, mit der ich gut weiterarbeiten kann.

Searcher
13.11.2012, 12:10
An der Zeitmessung stören mich verschiedene Dinge. Vor allem, daß im Hauptprogramm immer alles gemacht wird bzw stockt und auf die ISR gewartet wird, die wiederum die ganze Pulslänge lang wartet.

Hab mir also zunächst mal ein Datenblatt zum SRF04 gesucht. Es gibt viele davon und es lohnt sich mehrere anzuschauen. Ich hab mir das hier ausgesucht: http://www.roboter-teile.de/datasheets/srf04.pdf
Falls es nicht zu Deinem Sensor paßt, verlinke bitte das passende.

Aus dem Datenblatt entnehme ich:
-daß der Sensor einen maximalen Meßbereich von 3cm bis 300cm haben soll
-daß der Triggerimpuls mindestens 10µs und nicht länger als 200µs lang sein soll
-daß die Länge des Impulses vom Echo Output Pin proportional zur Enfernung ist
-daß die Länge des Impulses von 100µs bis 18ms reichen kann.
-daß die Länge des Impulses, wenn kein Objekt erkannt wurde, ungefähr 36ms ist
-die Formel zum Umrechnen der Zeit in Entfernung - mit Erklärung.

Du möchtest recht genau messen. Was bedeutet das für Dich?

Für mich ist 1mm Auflösung schon sehr genau. Was bedeutet das in Impulslänge?
Nach der Formel im Datenblatt: s = 344m/s * ti / 2 bedeutet 1mm Abstand eine Impulslänge von:
ti = s / 344m/s * 2
ti = (1mm / 344000mm/s) * 2 = 0,000005814s

also etwa 5,814µs, heißt, wenn ich eine Auflösung bei der Zeitmessung von 5µs habe, kann ich theoretisch Abstände mit einer Genauigkeit von weniger als 1mm messen.

Heißt auch, daß nach Beginn des Sendens des Triggerimpulses bei 3cm Abstand das Echosignal frühestens nach
(1000000µs / 344000mm) * 2 * 30mm = 174,4µs erwartet werden kann.

Du nimmst den Timer1 für die Zeitmessung. Wär auch meine Wahl, nur der Prescaler von 1 gefällt mir jetzt nicht.

Mit den 16Bit des Timers kann man von 0 bis 65536 zählen. Die Impulslänge kann von 100µs bis 18000µs (36000µs) reichen.
Das schreit ja fast danach, den Timer so einzustellen, daß ein Schritt um 1µs bedeutet. Geht bei 8MHz Systemtakt auch noch prima.

Prescaler auf 8. Timer läuft mit 1Mhz. 1 / 1000000Hz = 0,000001s = 1µs. Ein Timerschritt also genau 1µs.
Auflösung: s = 344m/s * 1µs / 2 = 0,172mm (noch genauer als ich wollen würde :) )

Das macht das Programm einfacher und man braucht sich nicht mit den Timerüberläufen zu quälen :)

Der Programmablauf in Anlehnung an Dein Konzept könnte dann so aussehen:
Das Programm mißt ständig. Für Meßintervalle könnte man 4.1.2 gesondert behandeln.
Eine Einheit des Meßwertes (Timerstep) entspricht 0,172mm bei 8MHz Systemtakt und Timer1 mit Prescaler = 8
Es wird nicht in der ISR gewartet bis der Echoimpuls vorbei ist, sondern die ISR zweimal für eine Messung aufgerufen.
Sichern des Messergebnisses findet in der ISR statt und nur wenn eins vorhanden ist (Messung beendet), in der Hauptschleife berechnet und ausgegeben.
Das Ergebnis der allerersten Messung ist unsicher, da man nicht weis, ob Timer1 schon durch die steigende Flanke des Echosignals initialisiert war.
Ohne Gewähr und Logikfehler nicht ausgeschlossen https://www.roboternetz.de/phpBB2/images/smiles/eusa_snooty.gif

1. Initialisierung
-Header, Variablen, Timer, Interrupt, usw.
-INT0 mit STATE=CHANGE
2. Hauptschleife Anfang
3. Messung Starten Flag = JA ? Abfrage
3.1. JA
3.1.1. 15µs Triggerimpuls senden
3.1.2. Messung Starten Flag auf NEIN setzten
3.1.3. Messung Beendet Flag auf NEIN setzten
4. Messung beendet = JA ? Abfrage
4.1. JA
4.1.1. PRINT Meßergebnis (hier die Sicherung aus der ISR berechnen bzw direkt ausgeben)
4.1.2. Messung Starten Flag auf JA setzten
5. Hauptschleife Ende

1. INT0 Isr
2. Ist Triggerimpulspin = high?
2.1. Ja
2.1.1. Timer1=0
2.2. NEIN (dann muß der Pin low sein)
2.2.1. Meßergebnis=Timer1 (Meßergebnis sichern)
2.2.2. Messung Beendet Flag auf JA
3. RETURN (INT0 Isr Ende)

Bin gespannt wie es hinhaut. Mit der Formel sollte es doch kein Problem sein, die Anzeige in cm zu machen? Wahrscheinlich muß man noch Kalibrieren, weil die Schallgeschwindigkeit von der Temperatur abhängig ist, auch Toleranzen des SRF04 und Sonstiges.

Gruß
Searcher

JoeM1978
13.11.2012, 20:03
Also... der Sensor ist ein anderer... nicht der srf04 sondern der HC-SR04 http://kt-elektronic.de/wawi11/artikeldaten/sen-hr_sr4-e1/ultraschallmodul_beschreibung_3.pdf

Was mir dabei etwas sorgen macht ist, das er auf dem Echo pin erstmal ein 40khz Signal sendet, bevor er dauernd auf High bleibt bis zum empfang des Echo.
Denke daher wird es nicht richtig sein den Interrupt über Change laufen zu lassen.
Möglich, das der während dem Burst Signal schon den wechsel erkennt und garnicht erst bis zum eigentlichen Echo kommt.

Aber was den Ablauf des Programms betrifft hast schon recht.
Ist an sich schon blöd die ganze Wartezeit in der ISR zu hängen. Das blockiert das Programm komplett.

Überlegung von mir...

---Hauptprogramm--
xxxx
Subroutine (wenn messwert gebraucht wird)
print ergebniss
---Subroutine------
do
if Echopin = 0 then
Triggersignal = 0
waitus 15
Triggersignal = 1
else
waitus 15
endif
loop until echopin = 0
timer1 start
---ISR(Falling)--------------
timer1 stop
Ergebniss= timer1
Return


Bin nur gerade etwas beschaftigt und noch nicht dazu gekommen das zu testen.

Chypsylon
13.11.2012, 20:24
Also... der Sensor ist ein anderer... nicht der srf04 sondern der HC-SR04 http://kt-elektronic.de/wawi11/artikeldaten/sen-hr_sr4-e1/ultraschallmodul_beschreibung_3.pdf

Das ist ziemlich egal, die sind vom Aufbau und Verwendung praktisch identisch.



Was mir dabei etwas sorgen macht ist, das er auf dem Echo pin erstmal ein 40khz Signal sendet, bevor er dauernd auf High bleibt bis zum empfang des Echo.

Tut er nicht, siehe folgende Grafik ;)
23723

Searcher
14.11.2012, 06:56
Hallo JoeM1978,
auch in Deinem letzten Ablauf muß das Hauptprogramm bzw Subroutine warten. Dort gibt es zB "loop until echopin = 0". Ein Taktzyklus ist bei 8Mhz Systemtakt 125ns lang. In der Zeit, in der der Prozessor zB 1ms wartet (und es kann ja auch noch viel länger sein), könnte er mehr als 4000 Maschinenbefehle ausführen (bei ca 2 Zyklen für einen Maschinenbefehl). Wenn das Programm mit anderen Funktionen erweitert wird, wird es also vermutlich hakeln, vor allem wenn da noch andere zeitkritische Aufgaben zu erledigen sind.

Hab mir das Datenblatt angesehen. Chypsylon hat schon geschrieben, daß Du da keine Sorgen haben brauchst. Außerdem kannst Du ja beides ausprobieren.

Der Sensor ist ja im Prinzip recht einfach. Man schickt auf der Triggerleitung ein Signal hin und erwartet auf der Echoleitung einen Impuls, dessen Länge man dann mißt.
Das sind getrennte Leitungen. Auf dieser Echo-Leitung ist immer nur das Echo Signal vom HC-SR04 zu sehen. Das soll man nicht verwechseln mit dem Ultraschallecho, das zurückkommt, wenn der Sensor den 40kHz Ton gesendet hat. Das Ultraschallecho vearbeitet der Sensor und gibt daraufhin auf der Echoleitung den Gleichspannungsimpuls raus. Im Oszillogramm im Datenblatt unter "Single Shot Modus" gut zu sehen. Mit 40kHz hat man nichts zu tun. Das bearbeitet der HC-SR04 allein.

Meinen Pseudocode kannst Du also trotzdem verwenden, gilt auch für den HC-SR04.

Edit: Hab Dir Code angehangen, wie ich es mir bisher gedacht hatte. Nur probekompiliert, nicht getestet. Das "waitms 20" versuchen wir im nächsten Schritt wegzukriegen, wenn Du Dich für diese Variante entscheidest. Kann man auch über Timer machen.

Mit welchem Takt läuft der Mega8 tatsächlich?
In Deinem ersten Posting ist $crystal = 3686400 . Im zweiten ist $crystal = 8000000

Gruß
Searcher

Chypsylon
14.11.2012, 11:00
Hier nochmal ein Auschnitt aus einer Arbeit von mir, wo die Pegel der Pins beschrieben werden:
23728

Oben siehst du auch die Formel zur Berechnung der tatsächlichen Entfernung.

JoeM1978
14.11.2012, 19:26
So... da ich dann gestern abend in der Wanne den kopf nicht frei bekommen hab
bin ich noch dazu gekommen den Programmansatz von Searcher umzuwandeln in ein Laufendes Programm.

Sieht jetzt so aus:

'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Programmname: Sensorabfrage.bas
'Letzte Änderung: 13.11.2012
'Funktion: Abfrage des Ultraschallsensor HC-SR04
' und Ausgabe über "Print"
'Mikrocontroller: Mega8
'
'Input: D2 - Echosignal
'
'Output: C0 - Triggersignal
'
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'Den Atmega mit den passenden Daten füttern.
'-------------------------------------------------------------------------------
$regfile = "m8def.dat" 'eingesetzter Mikrocontroller
$crystal = 8000000 'eingestellte Taktfrequenz (8MHz)
$hwstack = 100 'Standardwert
$swstack = 100 'Standardwert
$framesize = 100 'Standardwert
'-------------------------------------------------------------------------------
'Ports/Pins konfigurieren.
'-------------------------------------------------------------------------------
Config Portc.0 = Output ' Trigger-Signal zum Sensor
Config Pind.2 = Input ' Echo-Signal vom Sensor

'-------------------------------------------------------------------------------
'Timer/OCR/PWM/INT usw. setzen
'-------------------------------------------------------------------------------
Config Timer1 = Timer , Prescale = 8 ' ergibt 1.000.000 ticks/sekunde
Config Int0 = Change ' Interrupt bei wechselnder Flanke am Echosignal starten
On Int0 Echowechsel '
Enable Int0 ' Wenn auf Echo gewartet wird wechselt Echo-Signal auf High
Enable Interrupts '

'-------------------------------------------------------------------------------
'Variablen
'-------------------------------------------------------------------------------
Dim Messungstarten As Bit ' Zeigt an, ob Messung gestartet werden soll
Messungstarten = 1
Dim Messergebniss As Long ' Ergebniss der Messung in us
Messergebniss = 0
Dim Messungbeendet As Bit ' Zeigt an, ob Messung beendet ist
Messungbeendet = 0
Dim Entfernung As Long ' Entfernung in mm
Entfernung = 0
Dim Kalibrierwert As Integer ' Zum genauen einstellen
Kalibrierwert = 0

'-------------------------------------------------------------------------------
'Hauptprogramm
'-------------------------------------------------------------------------------
Do
If Messungstarten = 1 Then ' Abfrage, ob Messung gestartet werden soll
Waitms 20
Portc.0 = 1 ' Impuls von 10us an Triggerport senden
Waitus 10
Portc.0 = 0
Messungbeendet = 0
Messungstarten = 0
End If

If Messungbeendet = 1 Then ' Berechnung des Ergebniss, wenn Messung beendet ist
Entfernung = Messergebniss + Kalibrierwert
Entfernung = Entfernung * 172
Entfernung = Entfernung / 1000 ' Ergebniss in mm

Print Entfernung ' Ausgabe des Ergebniss
Waitms 300 ' Pause zwischen Messungen (bessere lesbarkeit)

Messungstarten = 1 ' neue Messung starten
End If


Loop

End

'-------------------------------------------------------------------------------
'Interrupt
'-------------------------------------------------------------------------------

Echowechsel: ' Interrupt startet bei Signalwechsel am Echopin
If Pind.2 = 1 Then ' Wenn Pin zu High wechselt soll Timer1 Zeit zu messen
Timer1 = 0
Start Timer1
Else ' wenn Pin zu LOW wechselt, messung beendet und Wert in Variable speichern
Messergebniss = Timer1 ' Wert in Variable speichern
Messungbeendet = 1 ' Anzeigen, das Messung beendet ist
End If

Return

Direkt zum Ergebniss des Timers hab ich noch einen Kalibrierwert gesetzt und der scheint soweit auch schon zu passen.
Ich hab 2 identische Sensoren hier und beide liefern mir exakt die selben werte.
Wie es sich bei entfernungen grösser als 1m verhält muss ich noch testen.

Und ja... der Atmega8 läuft jetzt mit 8MHz... und ich hab auch die fusebits so gestellt. ;)

Späther soll das ganze mal mit 2-3 sensoren auf ein Fahr-Chassis kommen.
Da werd ich vermutlich (um Pins zu sparen) die sensoren abwechselnd messen lassen.
Das sollte von der Geschwindigkeit gut ausreichen. Soll ja kein Rennwagen sein. :D

Was mir in deinem Code aufgefallen ist:

Der Timer wird nur auf 0 gesetzt... Startet der automatisch wieder ?
und die Flags hab ich als normale Variablen gemacht... so kann ich sie schnell ändern und
im Zweifelsfall mehrere verschiedene Zustände übergeben.

Vielen Dank für eure Tips und Hilfestellung.

Gruss,... JoeM

Searcher
15.11.2012, 07:33
Hi JoeM,

Der Timer wird nur auf 0 gesetzt... Startet der automatisch wieder ?
Der Timer wird mit "Config Timer", genauer mit der Angabe von Prescaler gestartet. Ich lasse den einfach immer durchlaufen und stoppe den nicht. Nur wenn die Messung beginnt, muß er natürlich initialisiert werden, weil man in dem Augenblick nicht weis, wo er gerade ist. Wenn dann die fallende Flanke kommt, wird einfach der augenblickliche Wert gesichert. Timer kann ruhig weiterlaufen. Um den auf 0 zu setzten muß er nicht stehen.

Bei dem Sensor habe ich noch Unklarheiten. In dem von Dir verlinkten Datenblatt steht, daß wenn kein Objekt erkannt wurde, der Echoimpuls 200ms lang sein würde, man aber schon nach 20ms eine neue Messung starten kann. In anderen Datenblättern zum HC-SR04 findet man die Angabe von 38ms.
Wie verhält er sich tatsächlich?

Außerdem ist mir nicht klar, warum man nur 50 Messungen pro Sekunde machen können soll. Plausibler erscheint mir da, daß man nach Ende des Echoimpulses noch ca. 10µs warten soll, bevor man eine neue Messung starten kann.

Also vor dem "perfekten" Programm sind noch ein paar Fragen zu klären. Zunächst aber erstmal überhaupt was sinnvolles, reproduzierbares messen. Falls Du was hast, poste mal ein paar Werte mit den dazugehörenden, per Zentimetermaß gemessenen Entfernungen.

Gruß
Searcher

JoeM1978
15.11.2012, 15:24
Was diese Werte angeht hat mich das auch verwirrt was im Datenblatt steht... Scheint mir teilweise recht wiedersprüchlich zu sein.
Ich hab mal Probemessungen gemacht mit

Do
If Messungstarten = 1 Then ' Abfrage, ob Messung gestartet werden soll
Waitms 20
Portc.0 = 1 ' Impuls von 10us an Triggerport senden
Waitus 10
Portc.0 = 0
Messungbeendet = 0
Messungstarten = 0
End If

If Messungbeendet = 1 Then ' Berechnung des Ergebniss, wenn Messung beendet ist

Entfernung = Messergebniss + Kalibrierwert
Entfernung = Entfernung * 172
Entfernung = Entfernung / 1000 ' Ergebniss in mm
Print Messergebniss ; "=" ; Entfernung ' Ausgabe des Ergebniss

Messungstarten = 1 ' neue Messung starten
End If


Loop

Also nur 20ms pause bis zum nächsten Triggerimpuls.
Als Messtolleranz (Meterstab) würd ich mal 1-2mm angeben. :)
(Timerwert = Entfernung in mm)

Abstand 100cm:

5996=1031
5997=1031
6019=1035
5995=1031
5995=1031
6021=1035
6018=1035
5995=1031
5994=1030
5996=1031
6019=1035
5995=1031
5994=1030
5995=1031
6018=1035
6018=1035
6018=1035
5995=1031
6020=1035
6017=1034

Abstand 50cm:

3156=542
2973=511
2973=511
2972=511
2974=511
2972=511
2972=511
2973=511
2971=511
2974=511
2973=511
2973=511
2972=511
2973=511
2973=511
2972=511
2973=511
2973=511
2972=511
2972=511

Abstand 10cm:

736=126
557=95
557=95
557=95
556=95
556=95
556=95
556=95
557=95
557=95
556=95
556=95
557=95
557=95
557=95
557=95
557=95
556=95
557=95
557=95

Der Messbereich, den ich späther brauche wird vermutlich kleiner als 1m bleiben.

Als nächstes stell ich das Objekt in 100cm und versuche mit unterschiedlichen Pausenzeiten (vor dem nächsten Triggersignal).
Mal sehen, ob sich dabei überhaupt etwas verändert bzw. wo hier die schnellstmögliche Zeit liegt.

Gruss,... JoeM

- - - Aktualisiert - - -

Ich hab vergessen zu erwähnen, das der "Kalibrierwert" dazu auf 0 steht.

Bei den Tests ist mir aufgefallen, das unterhalb einer Pausenzeit von 20ms die Werte um etwa +- 5mm abweichen...
(Beispiel 10ms)

5871=1009
5847=1005
5875=1010
5872=1009
5872=1009
5873=1010
5849=1006
5872=1009
5871=1009
5873=1010
5873=1010
5872=1009
5826=1002
5849=1006

bei 20ms liegt sie extrem drüber. nämlich bei + 30mm (und zusätzlich viele Fehlmessungen)

6025=1036
6004=1032
6027=1036
6029=1036
6003=1032
6029=1036
3589=617
3592=617
3846=661
6028=1036
6027=1036
4490=772
4683=805
5095=876
5024=864
5313=913
5540=952
5790=995
6031=1037
6032=1037
6024=1036
5916=1017
5938=1021
5917=1017
6030=1037
6051=1040
5941=1021
6030=1037
5918=1017
5940=1021

und bei über 20ms ist die Messdifferenzen sehr genau
(Beispiel 25ms)

5848=1005
5848=1005
5847=1005
5848=1005
5826=1002
5848=1005
5847=1005
5848=1005
5848=1005
5848=1005
5847=1005
5848=1005
5847=1005
5849=1006
5848=1005

- - - Aktualisiert - - -

Da man hier den Datenblättern wohl nicht ganz exakt vertrauen kann...
vieleicht hat
@ Chypsylon
da schon etwas mehr Erfahrungen gesammelt.

Searcher
15.11.2012, 16:38
Danke für die Info - Interessant. Sieht aber doch sehr brauchbar aus?
Hab selber keine praktische Erfahrung mit Ultraschallsensoren. Zu den festgestellten Testergebnissen fällt mir jetzt auch nichts weiter ein.

Hatte nach den 200ms gefragt, da bei einer so langen Zeit der Timer doch wieder überlaufen würde.

Werde weiterschauen und falls mir noch was auffällt, melde ich mich wieder.

Gruß
Searcher

JoeM1978
15.11.2012, 17:04
...Sieht aber doch sehr brauchbar aus?
Ja. Das würde ich auch sagen... was Abstände kleiner 1m angeht werd ich wohl in der Praxis
mit Pausenzeiten von 25ms arbeiten. Das ist für eine Auswertung absolut genug.
Alles an Entfernungen über 1m interessiert für mich momentan eh nicht. Ich möcht ja nicht die ganze Wohnung ausmessen. :)
Jetzt werd ich mich weiter mit der umsetzung des Programms für 2 solcher Sensoren beschäftigen...
und auch mit der Auswertung der verschiedenen Situationen/Zustände. (Und die To-Do-Liste ist sehr lang *lach)

Ich denke fürs erste Kann man das jetzt so stehen lassen.
Ist sicher auch interessant für andere, die mit diesem Sensor arbeiten möchten.