HC-SR04 und JSN-SR04T-2.0 Abstandssensoren

Über den Beitrag

In meiner Reihe über Licht-, Gestik-, Bewegungs- und Abstandssensoren möchte ich diesmal den Klassiker der Abstandssensoren, nämlich den HC-SR04, vorstellen. Ich werde darauf eingehen wie er prinzipiell funktioniert, wie ihr ihn an einen Arduino anschließt und wie ein geeigneter Sketch dazu aussieht. Dann werde ich noch den wasserdichten Verwandten des HC-SR04, den JSN-SR04T-2.0, vorstellen.

Wenn diese Beitragsreihe komplett ist, findet ihr hier einen Link zur Zusammenfassung. 

Basisdaten

Die wichtigsten Eckdaten des HC-SR04 sind:

  • Reichweite: 2 cm bis ~400 cm
  • Spannung: 5 V
  • Stromverbrauch: ca. 3.5 mA (schnelle Dauermessung, selbst ermittelt) 
  • Erfassungswinkel: 15°
  • Signallevel: TTL
  • Genauigkeit: 0.3 cm (theoretisch, dazu später mehr)
  • Messungen pro Sekunde: max. 50

Die maximale Reichweite hängt unter anderem von der Größe des Objekts, dem Einfallswinkel des Signals und der Oberflächenbeschaffenheit ab. 

Ihr bekommt den HC-SR04 im Einzelpack ab ca. vier Euro zum Beispiel hier bei Amazon. Meist wird er in Mehrfachpacks angeboten und ist dann noch einmal deutlich günstiger. 

Das hilfreichste Datenblatt habe ich hier gefunden.

Funktionsweise des HC-SR04

Der HC-SR04 macht es wie die Fledermaus: er sendet ein Ultraschallsignal und wertet das Echo aus. Über die Flugzeit des Signals und die Schallgeschwindigkeit lässt sich dann die Distanz berechnen.

Dazu besitzt das Modul einen Ultraschallsender, der auf dem Modul mit einem „T“ (Transmitter) gekennzeichnet ist. Daneben, mit „R“ (Receiver) gekennzeichnet, sitzt der Receiver. 

Pinout des HC-SR04

HC-SR04 Ultraschallmodul
HC-SR04 Ultraschallmodul

Das Modul hat vier Pins:

  • VCC / GND: hier werden 5 V angeschlossen
  • Trigger: ein Wechsel von HIGH auf LOW löst eine Messung aus
  • Echo: ist HIGH solange das Ultraschallsignal unterwegs ist

Genauer Ablauf einer Messung

Schematischer, zeitleicher Ablauf einer Messung mit dem HC-SR04
Schematischer Verlauf einer Messung (Zeitachse ist nicht maßstabsgetreu)

Der Triggereingang benötigt zunächst ein HIGH – Signal mit einer Länge von mindestens 10 µs. Die abfallende Flanke des Triggersignals ist der „Startschuss“ für die Messung. Nach ca. 250 µs sendet der HC-SR04 das Ultraschallsignal in Form von acht 40 kHz Pulsen. Dieser Vorgang benötigt ca. 200 µs. Unmittelbar nach Senden des Signals geht der Echo Pin auf HIGH. Dort bleibt er bis das Modul das reflektierte Signal empfängt. Nach einer Maximalzeit von – so meine Messung – circa 170 ms geht der Echo Pin aber auch ohne empfangenes Echo auf LOW. Das entspräche übrigens einer Distanz von ~29 m. Messwerte in dieser Region können deshalb als „Kein Objekt in Reichweite“ gewertet werden.

Eigentlich muss der Echo Pin so lange auf HIGH bleiben, bis das Echo Signal vollständig zurückgekommen ist, da dieses ja immerhin 200µs lang ist, was einer Distanz von ungefähr 3.5 cm entspricht. Über dieses Detail habe ich keine Information finden können, aber die Resultate stimmen und das ist ja die Hauptsache. 

Auswertung der HC-SR04 Messung

Die Dauer des HIGH Zustandes am Echo Pin könnt ihr bei Verwendung des Arduinos am besten mit der pulseIn() Funktion erfassen. Der Rückgabewert ist die Zeit in Mikrosekunden. 

Bleibt noch die Umrechnung der Zeit in die Distanz. In erster Näherung beträgt die Schallgeschwindigkeit in trockener Luft bei Raumtemperatur 343,2 m/s. An den Randbedingungen seht ihr schon, dass verschiedene Faktoren die Schallgeschwindigkeit beeinflussen, vor allem die Temperatur. Die folgende Formel beschreibt die Temperaturabhängigkeit in dem Bereich von -20 °C bis +40 °C mit einer Genauigkeit von > 99.8%.

cLuft ≈ 331.5 + 0.6 ⋅ T[°C]  [m/s]

Setzt ihr in diese Formel einmal 0 °C und einmal 20 °C ein, könnt ihr ausrechnen, dass es einen Unterschied von immerhin ~3.5 % ausmacht. Das ist das Zehnfache der im Datenblatt angegebenen Genauigkeit des HC-SR04. Auch die Luftfeuchte hat einen Einfluss. Bei 20° C ist die Schallgeschwindigkeit bei 100 % Luftfeuchte um 0.375 % höher als bei 0% Luftfeuchte. Weitere Parameter, wie z.B. den Luftdruck, könnt ihr vernachlässigen. Wenn ihr wissen wollt warum das so ist oder wenn ihr auch generell noch mehr zu dem Thema Schallgeschwindigkeit wissen möchtet, dann schaut hier auf Wikipedia.  

Die einfache Umrechnungsformel ohne Temperaturkorrektur lautet nach Berücksichtigung der Einheiten:

Distanz [cm] = Messzeit [µs] * 0.03432 [cm/µs] / 2

Der Faktor 1/2 kommt natürlich daher, dass das Signal die Strecke zweimal zurücklegen muss.  

Der HC-SR04 am Arduino

Sketch für die Abstandsmessung

Der Sketch für die Abstandsmessung ist aufgrund der vorhergehenden Erklärungen keine große Überraschung mehr. Im Vergleich zu den Abstandsmessungen mit dem VL53L0X und VL53L1X aus meinem letzten Beitrag ist das alles erstaunlich simpel.

Wenn ihr die Temperatur berücksichtigen wollt, dann entkommentiert die entsprechenden Zeilen.  

int triggerPin = 12;
int echoPin = 11;

int cmDistance, tCorrectedCmDistance;
//int temperature = 0;
unsigned long duration;


void setup(){
  pinMode(triggerPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(9600);
  delay(10);
}

void loop(){
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);
  duration = pulseIn(echoPin, HIGH);
 
  // Schallgeschwindigkeit in Luft: 343m/S (bei 20°C)
  // 343,2 m/S --> 34,32cm / ms --> 0,03432cm / µs
  // durch 2 wg. Echo
  cmDistance = duration * 0.03432 / 2; 
//  tCorrectedCmDistance = duration *(0.03315 + 0.00006 * temperature)/2;
  Serial.print("Distanz [cm]: ");
  Serial.println(cmDistance);
//  Serial.print("T-korrigierte Distanz [cm]: ");
//  Serial.println(tCorrectedCmDistance);
  delay(500);
}

 

Zugehörige Schaltung

Auch die Schaltung ist sehr einfach. Die LED an Pin 13 benötige ich für den Bewegungsmeldersketch. 

Schaltung: der HC-SR04 am Arduino
HC-SR04 am Arduino

Ansteuerung per NewPing Bibliothek

Der Vollständigkeit halber möchte ich erwähnen, dass es eine Bibliothek namens NewPing gibt mit der sich der HC-SR04 ansteuern lässt. Diese findet ihr z.B. hier auf Github. Ich bin allerdings kein Freund davon, bei solch simplen Ansteuerungen Bibliotheken zu verwenden.

Bewegungsmeldersketch

Jeden Abstandssensor könnt ihr natürlich auch als Bewegungsmelder einsetzen. Und genau das macht der nächste Sketch. Eine Bewegung liegt vor, wenn der aktuelle Abstandswert um einen gewissen Wert vom vorherigen Wert abweicht. 

int triggerPin = 12;
int echoPin = 11;
int ledPin = 13;
int cmDistancePrevious, cmDistanceCurrent;
const int sensitivity = 20; 

void setup(){
  pinMode(triggerPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(echoPin, INPUT);
  cmDistancePrevious = measureDistance();
}

void loop(){
  cmDistanceCurrent = measureDistance();
  
  if (abs(cmDistanceCurrent - cmDistancePrevious) > sensitivity){
    digitalWrite(ledPin, HIGH);
    delay(1000);
    digitalWrite(ledPin,LOW);
    cmDistanceCurrent = measureDistance();
  }
  cmDistancePrevious = cmDistanceCurrent;
  delay(50);
}

int measureDistance(){
  unsigned long duration = 0;
  
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);
  duration = pulseIn(echoPin, HIGH);
 
  int cmDis = duration * 0.03432 / 2; 

  if(cmDis>400){
    cmDis = 400;
  }

  return cmDis;
}

 

JSN-SR04T-2.0 – die wasserdichte Alternative

Der JSN-SR04T (Version 2.0)
Der JSN-SR04T

Als nächstes möchte ich auf eine ganz interessante Alternative zum HC-SR04 eingehen und zwar den JSN-SR04T-2.0. Bei diesem ist die Sende-/Empfängereinheit sehr kompakt, wasserdicht und über ein 2,5 m Verlängerungskabel mit dem Modul verbunden. Zum einen sind dadurch z.B. Outdoor Anwendungen möglich, zum anderen lässt sich die Messeinheit viel unauffälliger verbauen. Ein Nachteil an dieser Version ist, dass sie einen Mindestabstand von 25 cm benötigt.  

Man bekommt den JSN-SR04T-2.0 für  ca. 10 – 12 Euro bei Amazon oder eBay. Wenn man über diese Plattformen bei chinesischen Shops bestellt, wird es wieder günstiger, aber man muss evtl. ein bisschen Geduld mit der Lieferung haben.

JSN-SR04T vs. JSN-SR04T-2.0 / Probleme mit JSN-SR04T

Neben dem JSN-SR04T-2.0 gibt es auch die Version JSN-SR04T, also ohne „2.0“. Diese sieht auf den ersten Blick sehr ähnlich aus, hat aber ein paar deutliche Unterschiede. Vor allem fehlt dem JSN-SR04T der Jumper R27, auf den ich noch zu sprechen komme.

Teilweise haben JSN-SR04T-2.0 Modelle Probleme mit Fehlmessungen. Dabei werden sporadisch Abstandswerte von um die 20 cm ermittelt obwohl sich nichts in diesem Bereich befindet. Ich selbst habe das bei einem von den drei Modulen, die ich mir gekauft habe, festgestellt. Die anderen beiden zeigten das Problem hingegen nicht. Da der Fehler aber auch von anderen beschrieben wird (z.B. hier) scheint es sich nicht um die absolute Ausnahme zu handeln. 

Man könnte versucht sein, sich wg. der Probleme gezielt einen JSN-SR04T zu kaufen. Aber auch wenn Shops Produktbilder vom JSN-SR04T haben und auch wenn nichts anderes in der Produktbeschreibung auf die Version 2.0 hinweist, erhält man mit hoher Wahrscheinlichkeit trotzdem die Version 2.0. Jedenfalls ist mir das bei zwei von zwei Versuchen passiert. Dann habe ich die Lust verloren und auf den Test eines JSN-SR04T verzichtet. 

Auch in diesem Shop hier bekam ich die Version 2.0, obwohl die andere abgebildet war. Allerdings habe ich diesen Vertreter am intensivsten getestet und er funktionierte ohne irgendwelche Probleme. Für diese Quelle spricht auch, das sich dort (Stand August 2019) keine Negativbewertungen finden. 

HC-SR04 vs. JSN-SR04T-2.0

Abgesehen von den schon genannten Unterschieden hat der JSN-SR04T folgende Besonderheiten:

  • Spannungsversorgung: 3 – 5.5 V
  • Stromverbrauch: ca. 8 mA
  • Reichweite: angeblich bis zu 6 Meter
  • Erfassungswinkel: 45° – 75°; auch hier finden sich unterschiedliche Angaben – auf jeden Fall ist der Erfassungswinkel breiter als der des HC-SR04
  • Kommunikation: wie HC-SR04 über Trigger / Echo oder seriell (RX / TX)
  • Baudrate: 9600, n, 8, 1 

Die maximale Reichweite hängt von der Größe des Objekts, seiner Oberflächenbeschaffenheit und dem Einfallswinkel des Signals ab. Ich würde sagen, dass die Grenze wie beim HC-SR04 eher bei 4 Metern liegt. Bei großen, glatten Wänden zum Beispiel kommt man etwas darüber hinaus. 

Datenblätter zum JSN-SR04T-2.0 findet man kaum. Hier noch das Beste, auf das ich gestoßen bin. 

Die drei Betriebsmodi des JSN-SR04T-2.0

R27 Jumper zum Einstellen der Betriebsmodi des JSN-SR04T-2.0
R27 Jumper zum Einstellen der Betriebsmodi

Auf dem Modul befindet sich neben den Pins der Jumper R27. Diesen könnt ihr offen lassen, ihr könnt einen 47 kOhm Widerstand dazwischen löten oder einen 120 kOhm Widerstand nehmen. Mit dieser Maßnahme legt ihr den Betriebsmodus fest.  

Modus 1: R27 offen

In diesem Modus verhält sich der JSN-SR04T-2.0 wie der HC-SR04, d. h. ihr steuert ihn über den Trigger und den Echo Pin an. Ihr könnt denselben Arduino Sketch wie für den HC-SR04 verwenden, jedoch ggf. mit einer kleinen Änderung. Bei jeder fünften bis zehnten Messung erhielt ich als Ergebnis eine Null. Habt ihr dasselbe Problem, dann erhöht die „HIGH-Zeit“ am Trigger Pin von 10 auf 20 Mikrosekunden (Zeile 18 in HC_SR04_Proximity.ino). Mit dieser Maßnahme trat der Fehler bei mir nicht mehr auf. 

Modus 2: 47 kOhm Widerstand an R27

47 kOhm an R27 des JSN-SR04T-2.0 für Modus 2
47 kOhm an R27 – Modus 2 (stabiler wäre natürlich ein SMD Widerstand, hatte ich aber nicht)

Mit einem 47 kOhm Widerstand an R27 wechselt der JSN-SR04T-2.0 in einen kontinuierlichen Betriebsmodus. In diesem Modus erfolgt alle 100 ms eine Messung. Das Ergebnis dieser Messung ist die Distanz in Millimetern, die als 16 Bit Wert seriell übermittelt wird. Der Trigger Pin wird dabei zu RX, der Echo Pin wird zu TX. Der JSN-SR04T-2.0 überträgt 4 Bytes pro Messung:

  1. Startbyte: 0xFF 
  2. Oberes Byte der Distanz (h_data)
  3. Unteres Byte der Distanz (l_data)
  4. Checksumme: unteres Byte der Summe aus Startbyte + h_data + l_data

In meinem Sketch dazu (JSN_SR04T_Serial_continous.ino) erfolgt die Kommunikation über SoftwareSerial. Die Arduino Pins 10 und 11 habe ich als RX Pin bzw. TX Pin definiert. Der RX des Arduino kommt an TX des Moduls, TX des Arduino an RX des Moduls. Ich denke, dass ich mir ein Schaltschema dazu sparen kann. 

Sind Daten am seriellen Eingang vorhanden, prüft der Sketch, ob es sich um das Startbyte handelt. Ist das der Fall, werden die nächsten 3 Bytes gelesen und in einem Array („buf“) gespeichert. Die Distanz wird dann aus h_data und l_data berechnet. Zum Schluss prüft der Sketch noch die Checksumme. Dazu muss das obere Byte maskiert werden. Ist die Checksumme OK, so erfolgt die Ausgabe des Ergebnisses. 

Die Variablen h_data, l_data und sum habe ich nur aus didaktischen Gründen definiert. Ihr könnt auch direkt mit buf[0], buf[1] und buf[2] arbeiten. 

#include <SoftwareSerial.h>
#define rxPin 10
#define txPin 11
 
SoftwareSerial jsnSerial(rxPin, txPin);
 
void setup() {
  jsnSerial.begin(9600);
  Serial.begin(9600);
}
 
void loop() {
  if(jsnSerial.available()){
    getDistance();
  }
}

void getDistance(){
  unsigned int distance;
  byte startByte, h_data, l_data, sum = 0;
  byte buf[3];
  
  startByte = (byte)jsnSerial.read();
  if(startByte == 255){
    jsnSerial.readBytes(buf, 3);

    h_data = buf[0];
    l_data = buf[1];
    sum = buf[2];
    distance = (h_data<<8) + l_data;

    if(((startByte + h_data + l_data)&0xFF) != sum){
      Serial.println("Invalid result");
    }
    else{
      Serial.print("Distance [mm]: "); 
      Serial.println(distance);
    } 
  } 
  else return;
}

 

Modus 3: 120 kOhm Widerstand an R27

Im Gegensatz zum Modus 2 ist der Modus 3 ein Polling Verfahren, d. h. eine Messung wird auf Anfrage ausgeführt. Die Kommunikation erfolgt wieder seriell. Eine Messung wird dabei durch Senden einer 0x55 gestartet. Im nachfolgenden Sketch löst ein Tasterdruck dieses Startsignal aus. Das „Abholen“ des Ergebnisses wiederum unterscheidet sich nicht vom vorherigen Sketch.

#include <SoftwareSerial.h>
#define rxPin 10
#define txPin 11
#define switchPin 9
 
SoftwareSerial jsnSerial(rxPin, txPin);
 
void setup() {
  jsnSerial.begin(9600);
  Serial.begin(9600);
  pinMode(switchPin, INPUT);
}
 
void loop() {
  if(digitalRead(switchPin) == HIGH){
    jsnSerial.write(0x55);
    delay(50);
    if(jsnSerial.available()){
      getDistance();
    }
    delay(1000);
  }
}

void getDistance(){
  unsigned int distance;
  byte startByte, h_data, l_data, sum = 0;
  byte buf[3];
  
  startByte = (byte)jsnSerial.read();
  if(startByte == 255){
    jsnSerial.readBytes(buf, 3);

    h_data = buf[0];
    l_data = buf[1];
    sum = buf[2];
    distance = (h_data<<8) + l_data;

    if(((startByte + h_data + l_data)&0xFF) != sum){
      Serial.println("Invalid result");
    }
    else{
      Serial.print("Distance [mm]: "); 
      Serial.println(distance);
    } 
  } 
  else return;
}

 

Danksagung

Die Fledermaus im Beitragsbild stammt von Schmidsi auf Pixabay.

2 thoughts on “HC-SR04 und JSN-SR04T-2.0 Abstandssensoren

  1. Herzlichen Dank für Deine tolle Anleitung! Absolut exzellent!
    Habe gerade ein JSN-SR04T-2.0 wie von Dir beschrieben getestet. Hat auf Anhieb funktioniert :-))

Schreibe einen Kommentar

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