Ultraschall-Entfernungsmesser HC-SR04

Dein Roboter muss nicht immer auf die harte Tour erfahren, dass er gerade auf eine Wand zusteuert. Mit einem Entfernungssensor kann vorher festgestellt werden, ob bald ein Hindernis im Weg ist und wie weit dieses entfernt ist. Gängig sind Sensoren, die mit infrarotem Licht oder Ultraschall arbeiten. Letztere Art beschreibe ich in diesem Beitrag am Beispiel vom HC-SR04 und erkläre dazu wie du diesen mit C# ansteuern kannst.

 

Funktionsweise Ultraschall-Entfernungsmesser

HC-SR04 EntfernungsmesserDer Entfernungsmesser hat einen Lautsprecher und direkt daneben ein Mikrofon. Zuerst wird über den Lautsprecher ein Ultraschall-Ton ausgegeben. Die Schallwellen von diesem Ton werden von einem Objekt reflektiert und kommen wieder am Entfernungsmesser am Mikrofon an. Die Zeitspanne zwischen dem Senden der Schallwellen und dem Empfang muss gemessen werden. Weil bekannt ist, dass der Schall die Strecke mit Schallgeschwindigkeit (343,2 m/s bei 20 °C) zurücklegt, kann daraus die Entfernung zum Objekt berechnet werden.

Beispiel: Der ausgesendete Schall braucht 5 ms um wieder zurückzukommen. Das entspricht 0,005 Sekunden. Das multipliziert mit der Schallgeschwindigkeit 343,2 ergibt 1,716 m. Der Schall hat also 1,716 Meter zurückgelegt. Das ist die Strecke zum Hindernis und wieder zurück. Weil nur die einfache Strecke bis zum Hindernis benötigt wird, muss das Ergebnis noch durch zwei geteilt werden: 1,716 / 2 = 0,858 m. Das Hindernis ist also noch knapp einen Meter entfernt. Kein Grund zu bremsen! 😉

Praktischer Ablauf am HC-SR04: Nachdem am Trigger-Pin ein Signal anlag, wird kurz darauf der Ton ausgesendet. Gleichzeitig wird auf dem Echo-Pin ein HIGH-Signal ausgegeben. Dieses HIGH-Signal wird solange ausgegeben, bis das Mikrofon den zurückkommenden Schall empfangen hat. Es muss also nur die Länge des HIGH-Signals am Echo-Pin gemessen werden.

 

Code

Ich habe den Beispiel-Code so entwickelt, dass durch einen PWM der Ultraschallsensor regelmäßig alle 20 ms angesteuert wird. Die Auswertung des Echo-Signals wird davon unabhängig über einen Interrupt vom InterruptPort ausgelöst. In dieser Routine wird ermittelt ob der Port gerade von LOW auf HIGH wechselte, woraufhin dann die Zeitmessung gestartet wird. Sobald die Routine bei dem Wechsel von HIGH auf LOW wieder aufgerufen wird, wird die Zeit gestoppt, daraus die Entfernung berechnet und ausgegeben.

private static long _startTime = 0;

public static void Main()
{
    // Alle 20 ms einen Trigger-Impuls senden
    PWM pwm = new PWM(Cpu.PWMChannel.PWM_3, 20, 1,
                        PWM.ScaleFactor.Milliseconds, false);
    pwm.Start();

    InterruptPort echo = new InterruptPort(
        FEZCerbuinoBee.Pins.D1,
        false,
        Port.ResistorMode.PullDown,
        Port.InterruptMode.InterruptEdgeBoth);
    echo.OnInterrupt += echo_OnInterrupt;

    // Eine Endlosschleife wird nicht benötigt,
    // weil das Programm ab jetzt Interrupt-
    // gesteuert ist.
    Thread.Sleep(Timeout.Infinite);
}

private static void echo_OnInterrupt(
    uint portNumber,
    uint value,
    DateTime interruptTime)
{
    if (value == 1)
    {
        // Am Echo-Pin wurde eine steigende
        // Flanke (0 auf 1) erkannt:
        // Zeitmessung starten

        _startTime = interruptTime.Ticks;
    }
    else
    {
        // Am Echo-Pin wurde eine fallende
        // Flanke (1 auf 0) erkannt:
        // Zeit stoppen und auswerten

        // Schallgeschwindigkeit: Etwa 343 Meter pro Sekunde bei 20° C
        const int SPEED_OF_SOUND = 343;

        long elapsedTicks = interruptTime.Ticks - _startTime;
        double elapsedSeconds = (double)elapsedTicks / 10000000;
        double sonicDistanceMeters = elapsedSeconds * SPEED_OF_SOUND;
        double objectDistanceMeters = sonicDistanceMeters / 2;
        double objectDistanceMm = objectDistanceMeters * 1000;

        // Die Rechnung kann natürlich auch abgekürzt werden:
        // long objectDistanceMm = elapsedTicks * 1715 / 100000;

        Debug.Print(
            "Objektabstand: " +
            objectDistanceMm.ToString("f0") +
            " mm");
    }
}

Ich habe noch eine Klasse erstellt, die die Benutzung etwas komfortabler macht. Die Klasse habe ich im Beitrag Code: HC-SR04 Ultraschall-Entfernungsmesser näher beschrieben.

 

Elektronischer Aufbau

HC-SR04 Entfernungsmesser Schaltplan
Die Verbindungen vom PWM-Ausgang zum Trigger-Eingang kann direkt angeschlossen werden. Dem Trigger genügen die 3,3 V vom PWM-Ausgang um den HIGH-Wert zu erkennen.

Der Anschluss vom Echo-Pin ist etwas kritischer, weil dort bei Signalabgabe 5 Volt anliegen. Viele 3,3V-Microcontroller tolerieren 5 V an den digitalen Eingängen. Falls nicht, kann beispielsweise ein Spannungsteiler zwischengeschaltet werden, damit der Port nicht beschädigt wird.

HC-SR04 Entfernungsmesser Aufbau

Zusammenfassung

Ultraschall-Entfernungssensoren sind günstig in der Anschaffung und für viele Anwendungen präzise genug. Weil auch die Arbeitsweise des Sensors sehr durchschaubar ist, ist die Ansteuerung und Berechnung mit dem C#-Programm schnell gemacht.

Weiterführende Links

Code: HC-SR04 Ultraschall-Entfernungsmesser: Klasse zur komfortablen Benutzung

Microcontroller.net / KT-Elektronic – HC-SR04 – Detaillierte Beschreibung


Zurück zum NetMf-Tutorial-Index



Disclaimer

Die hier zusammen gestellten Informationen und Anleitungen habe ich mit bestem Wissen und Gewissen erstellt. Falls sich Fehler eingeschlichen haben oder du Verbesserungsvorschläge hast, schicke mir bitte eine Nachricht oder schreibe einen Kommentar unter den jeweiligen Beitrag. Informiere dich selber wie alles funktioniert. Ein Nachbau erfolgt auf eigene Gefahr. Du allein bist dafür verantwortlich, dass das, was du tust, funktioniert und keine Sach- oder Personenschäden verursacht.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.