• Hallo Zusammen, Aufgrund der aktuellen Situation setzten wir die Möglichkeit aus, sich mit Gmail zu registrieren. Wir bitten um Verständnis Das RCMP Team

Praxisbericht Ultraschallsensor HC-SR04 für Entfernungsmessungen mit einem Arduino

BAXL

Admin
Mitarbeiter
Das Ultraschallmodul HC-SR04 eignet sich zur Entfernungsmessung mit einem Arduino. Als Anwendung kommt eine Annäherungswarnung, oder die Füllstandsmessung bei Flüssigkeitsbehältern (z.B. Wasserzisterne im Garten) in Frage. Im Thema Zusatzhardware und Sensoren bin ich etwas tiefer auf die Grundlage der Messung eingegangen, das spare ich mir jetzt und konzentriere mich mehr auf die praktische Anwendung.



Trotzdem kurz zusammengefasst:
Schall breitet sich mit einer bestimmten Geschwindigkeit aus (ca. 343,2 m/s bei 20° C). Trifft der Schall auf ein Hinderniss, wird er reflektiert. Der HC-SR04 sendet einen Schallimpuls aus und empfängt den reflektierten Schall mit einem Mikrofon. Misst man die Zeit vom Aussenden des Schalls, bis das das Echo auf das Mikro trifft, kann man die Entfernung zum Hinderniss mit einer Formel berechnen.

In einer Beispielanwendung habe ich das Modul ausprobiert und seine Stärken und Schwächen untersucht. Für die Anwendung verwende ich einen Arduino UNO, einen HC-SR04 Ultraschallsensor, ein 1602 LCD-Display und ein paar Kabel zum Verbinden. Für eine Variation befindet sich noch der DS18B20 Temperatursensor in der Schaltung, ist aber nicht zwingend erforderlich. Für die dritte Version verwende ich eine Library, die den Messvorgang bereits automatisch mit einem Funktionsaufruf erledigt

Der HC-SR04 wird mit seinen Pins so angeschlossen:
VCC an +5V, Gnd an GND, Trig an D13, Echo an D12.

Das Display schließt man so an:
VCC an +5V, GND an GND, SDA an A4, SCL an A5

Der DS18B20 (optional, nicht zwingend erforderlich):
VCC an +5V, GND an GND, Signalpin an D5 und ein 4k7 Widerstand zwischen +5V und Signalpin



Das Programm funktioniert folgendermaßen:

Über Pin D13, der als Ausgangkonfiguriert wird, legt man eine Spannung für ca 2 Millisekungen an den Trig Pin. Damit wird ein Ultraschallimpuls ausgesendet.

Mit der Arduinofunktion pulseIn(12,HIGH); erhält man eine Zeitangabe in Microsekunden, wie lang ein Puls am Echo-Pin angelegen hat. Bei HIGH eben , wie lang war der High-Puls .

Im Programmablauf sieht das in Worten so aus:
Pin D13 einschalten
2ms warten (über delay(2);)
Pin D13 ausschalten

Zeit in Mikrosekunden über Pin D12 über pulseIn(14,HIGH); abfragen
Entfernung = Pulsdauer / 2 / 29.4 (Ergebnis ist in Zentimeter)

Programmcode:
Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C Bibliothek einbinden
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Variablen für Ultraschallsensor
int trigPin = 13;
int echoPin = 12;
long dauer;   // Variablen für die Messung
float entfernung;

void setup() {
  // Digitalports für den Ultraschallsensor initialisieren
  pinMode(trigPin, OUTPUT); // Der Triggerpin wird als Ausgang gesetzt
  pinMode(echoPin, INPUT);  // Der Echopin wird als Eingang gesetzt


  lcd.init(); //Im Setup wird der LCD gestartet
  lcd.backlight(); //Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus).
  lcd.setCursor(0,0);
  lcd.print("Ultraschall Test");
  delay(1500);
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Entfernung:");
}

void loop() {

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  dauer = pulseIn(echoPin, HIGH);
  entfernung = ((dauer/2) / 28.5); // hier findet man auch Teiler von 25, 28, 29.1,
  lcd.setCursor(0,1);
  lcd.print(entfernung); lcd.print(" cm   ");
  delay(1000);
}
In dem Code habe ich als Teiler 28,5 eingetragen. Diesen Wert habe ich bei mehreren Experimenten immer wieder angepasst, bis die Ultraschalmessung zur Kontrollmessung mit dem Zollstock gepasst hat. Die Messung mit dem HC-SR04 ist leider nur in gewissen Grenzen einigermaßen genau. Bei Abständen unter ca. 5cm wird es sehr ungenau bis unbrauchbar. Nachgeprüft habe ich es bis 30cm, da stimmten die Werte bis auf wenige Millimeter Abweichung.


In einem weiteren Experiment habe ich noch die Raumtemperatur bei der Messung mit eingerechnet, weil sich bei unterschiedlichen Lufttemperaturen die Luftdichte und somit auch die Laufzeit ändern kann. Leider waren die Ergebnisse nicht so zufriedenstellend, sodass ich am Ende wieder mit festen Werten gerechnet habe.

Programmcode mit Temperaturmessung mit einem DS18B20 und Wertekorrektur

Code:
// Entfernungsmessung mit einem HC-SR04 Ultraschallsensor
// und einer Wertekorrektur für die Schallgeschwindigkeit

#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C Bibliothek einbinden
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Einbinden eines Dallas DS18B20 Temperatursensors
#include <DallasTemperature.h>      // Library für Dallas Temperatursensoren
#define ONE_WIRE_BUS 5              // der Eindrahtbus für die DS18B20 liegen auf Digitalport 5
#define DS18B20_Aufloesung 11       // Die Sensoren sollen eine 11 Bit Auflösung liefern

OneWire oneWire(ONE_WIRE_BUS);         // Erstellen einer ONE_Wire Instanz
DallasTemperature myDS18B20(&oneWire); // Erstellen einer DS18B20 Instanz
float Temperatur = 0; // Variable zur Übernahme des Temperaturmesswertes

// Variablen für Ultraschallsensor
int trigPin = 13;
int echoPin = 12;
long dauer;   // Variablen für die Messung
float entfernung;

void setup() {
  // Digitalports für den Ultraschallsensor initialisieren
  pinMode(trigPin, OUTPUT); // Der Triggerpin wird als Ausgang gesetzt
  pinMode(echoPin, INPUT);  // Der Echopin wird als Eingang gesetzt


  lcd.init(); //Im Setup wird der LCD gestartet
  lcd.backlight(); //Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus).
  lcd.setCursor(0,0);
  lcd.print("Ultraschall Test");
  delay(1500);
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Entfernung:");
}

void loop() {

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  dauer = pulseIn(echoPin, HIGH);
  entfernung = dauer*((343+(0.6*temperatur())))/20000; // Diese Formel habe ich mir zusammengebaut aus
  // Ausbreitungsgeschwindigkeit (in Luft) =343,5 + (0,6 * Temp°)
  lcd.setCursor(0,1);
  lcd.print(entfernung); lcd.print(" cm   ");
  delay(1000);
}

float temperatur (){

  myDS18B20.requestTemperatures(); // DS18B20 anweisen eine Temperatur zu messen
  Temperatur = myDS18B20.getTempCByIndex(0); // Messwert des ersten verfügbaren Sensors (Index 0) abrufen
  //lcd.setCursor(0,1);
  //lcd.print(Temperatur); lcd.print("\xDF" "C ");
  //delay(1500);
  return Temperatur;
}
Es gibt noch eine Library, die die Zeitmessung erledigt. Die Library heißt NewPing und kann hier heruntergeladen werden. Die Library bietet ein paar Vereinfachungen, die den Messvorgang mit einem Funktionsaufruf erledigt und ist codeoptimiert geschrieben worden. Man kann den Mittelwert von mehreren aufeinanderfolgenden Messungen abrufen und dabei die Anzahl der Messungen vorgeben. Eine weitere Funktion erledigt auch direkt die Messung mit Umrechnung in ganze cm. Auch mit dieser Library ist die Messgenauigkeit so grob, dass man besser nur in ganzen Zentimetern messen/rechnen sollte. Unter 5cm sind keine sinnvollen Messungen mehr möglich.

In dem nachfolgenden Programmcode kann man die Entfernung entweder direkt abrufen (bereits auskommentiert) oder alternativ selbst berechnen. Dazu muß der Direktabruf als Kommentar gesetzt werden (// vor die Codezeile setzen) und die darüberliegenden zwei Codezeilen auskommentiert werden (die beiden // wegmachen)
Der Programmcode sieht so aus:

Code:
// Einfache Schaltung mit einem HC-SR04 Ultraschallsensor und einem 1602 Display als Entfernungsmesser
// Zur Messung wird die Library NewPing verwendet https://github.com/microflo/NewPing

// Deklaration zur Bedinung eines 1602 LCD Displays
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // LiquidCrystal_I2C Bibliothek einbinden
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Variablen für Ultraschallsensor
#include <NewPing.h>
#define MAX_DISTANCE 200 // Maximum Entfernung die gemessen werden soll (in Zentimeter). Maximale Sensorreichweite ca 400-500cm.
int trigPin = 13;
int echoPin = 12;
unsigned int uS = 0; // Variable für Messwert in Mikrosekunden
float entfernung; // Variable für die berechnete Entfernung

NewPing sonar(trigPin, echoPin, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  lcd.init(); //Im Setup wird der LCD gestartet
  lcd.backlight(); //Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus).
  lcd.setCursor(0,0);
  lcd.print("Ultraschall Test");
  delay(1500);
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Entfernung:");
}

void loop() {

  // uS = sonar.ping(); // Alternativer Abruf wenn man die Entfernung selbst umrechenen möchte
  // entfernung = ((uS/2) / 28.5); // hier findet man auch Teiler von 25, 28, 29.1,

  entfernung = sonar.ping_cm(); // Abruf direkt als Längenangabe in ganzen Zentimetern
  lcd.setCursor(0,1);
  lcd.print(entfernung); lcd.print(" cm   ");
  delay(1000);
}
 
Zuletzt bearbeitet:
D

Deleted member 1492

Gast
Zum HC SR-04: Es gibt deutlich bessere Ultraschallsensoren, die ich immer bevorzugen würde.

Das sind die Typen US-015 / US-016 / US-100

Die Genauigkeit liegt bei 1%, die Entfernungen variieren je nach Modell.

In der Tat eine geniale Idee. Aber dabei nicht die "US-" Ultraschallmodule vergessen, die arbeiten im Millimeterbereich. :thumbsup:
 
D

Deleted member 1492

Gast
Genauigkeit bezieht sich IMMER auf den Endwert.

Bei 1% bedeutet das:

700cm Reichweite = 7mm

300cm Reichweite = 3mm

Usw. usf. ..........

Man sollte also abwägen für was man das Modul benötigt.

Ist irgendwie wie bei Drehmomentschlüsseln.
4% bei einem 200nM Drehmo sind was anderes als 4% bei einem 50nM Drehmo.
 
Top Bottom