- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 10 von 15

Thema: Abfrage Ultraschallsensor HC-SR04 unter BASCOM

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    RN-Premium User Fleißiges Mitglied
    Registriert seit
    19.05.2012
    Ort
    Sigmaringen
    Beiträge
    169

    Abfrage Ultraschallsensor HC-SR04 unter BASCOM

    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.

    Code:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '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

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    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
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  3. #3
    RN-Premium User Fleißiges Mitglied
    Registriert seit
    19.05.2012
    Ort
    Sigmaringen
    Beiträge
    169
    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:

    Code:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '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
    Geändert von JoeM1978 (11.11.2012 um 13:10 Uhr)

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    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/Ti...#Input_Capture

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  5. #5
    RN-Premium User Fleißiges Mitglied
    Registriert seit
    19.05.2012
    Ort
    Sigmaringen
    Beiträge
    169
    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.


    Code:
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '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.

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    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 Bild hier  

    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
    Geändert von Searcher (14.11.2012 um 07:18 Uhr) Grund: Luftdruckabhängigkeit der Schallgeschwindigkeit gelöscht
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

Ähnliche Themen

  1. Ultraschallsensor selbst bauen (Bascom)
    Von Janigut im Forum Elektronik
    Antworten: 5
    Letzter Beitrag: 26.04.2011, 16:58
  2. Ultraschallsensor HC-SR04 Probleme ungenauigkeit
    Von anfaenger201 im Forum Sensoren / Sensorik
    Antworten: 4
    Letzter Beitrag: 04.08.2010, 15:06
  3. pin abfrage mit bascom
    Von Che Guevara im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 6
    Letzter Beitrag: 05.09.2008, 13:59
  4. UART Sendepuffer-Abfrage mit Bascom
    Von Heideltrudel im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 03.08.2007, 22:12
  5. wav out mit PWM unter bascom?
    Von sebastian.heyn im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 18
    Letzter Beitrag: 10.06.2005, 10:02

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen