Grundlagen

Grundlegende Informationen über Ultraschall und Anwendungsbereiche findet ihr hier.

Im folgenden Beispiel benutze ich einen Arduino Leonardo und einen Parallax PING Ultraschall-Sensor.

Natürlich sind auch andere Sensoren einsetzbar. Argumente für den Einsatz des Parallax sind aus meiner Sicht der

  • geringer Stromverbrauch (20 mA)
  • hohe Genauigkeit
  • Einsatzbereich von ca. 2 bis 300 cm
  • es wird nur ein I/O-Pin des Microcontrollers benötigt
  • Pins im 2,54 mm-Raster (wir können also wieder ein Standard-Steckbrett verwenden).

Nachteilig ist nur der vergleichsweise hohe Preis.

Hinweis: Bei senkrechter Montage ist die Genauigkeit bei manchen Anwendungen ein wenig genauer.

Ich empfehle in jedem Fall einen Blick auf die Dokumentation von Parallax.

Und so funktioniert das Ganze:

Funktionsweise der Parallax Ping Ultraschallsensors

Beispiel I

Komponenten und Schaltungsaufbau

Der Schaltungsaufbau ist so einfach, daß wir in diesem Fall auf einen Schaltplan verzichten können.

Schematischer Aufbau

Steckbrett Arduino Due mit Parallax-Ultraschall-Sensor

+5 Volt des Arduino mit "rot", GND mit "schwarz" des Parallax verbinden. Gelb an Digital-7 des Arduino und haben fertig.

Code

Alle 0,2 Sekunden wird ein Ultraschall-Impuls abgegeben und auf das Echo gewartet. Aus der Zeitdifferenz wird die Entfernung errechnet und auf der seriellen Konsole als Wert in Zentimetern ausgegeben. Einer Weiterverarbeitung steht nun nichts mehr im Wege.

Hier das Programm:

/* Parallax Ultraschall-Sensor

   Dieses Programm liest  die Werte des "Parallax PING"
   Ultraschall-Entfernungsmessers aus und gibt die Entfernung des nächstliegenden Objekts
   zurueck. Es wird ein Ultraschall-Impuls ausgesandt, das Echo erfaßt und die Entfernung
   auf Grund der Laufzeit berechnet.

   Die Schaltung:

   * +5V Anschluß des Parallax an +5V des Arduino
   * GND Anschluß des Parallax an GND des Arduino
   * SIG  Anschluß des Parallax an Pin 7 digital

   Angeregt durch http://www.arduino.cc/en/Tutorial/Ping

   created 3 Nov 2008
   by David A. Mellis
   modified 30 Jun 2009
   by Tom Igoe
   modifiziert durch fribbe fuer http://macherzin.net
   2010-05-20
*/

const int PingPin = 7; // Ultraschall-Sensor auf Pin 7 digital

void setup()
{
  Serial.begin(9600); // // starte serielle Kommunikation
  while(!Serial); // fuer Leonardo und Co.
}

void loop()
{
  // Definition der Variablen für Dauer des Pings und für das Ergebnis in cm
  unsigned int dauer, cm;
  // intialisiere den Sensor, indem wir ihm einen kurzen "Low"-Pulse senden,
  // dann einen 5 mS "High-Pulse"
  pinMode(PingPin, OUTPUT);
  digitalWrite(PingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(PingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(PingPin, LOW);

  // wir benutzen denselben Pin als Eingang und berechnen die Dauer des Pulses zwischen
  // ausgehendem und eingehendem Signal
  pinMode(PingPin, INPUT);
  dauer = pulseIn(PingPin, HIGH);
  // berechne die Entfernung aus Zeitdifferenz
  cm = MIKROSEKUNDEN_ZU_CM(dauer);
  // geben die Entfernung auf der seriellen Konsole aus
  Serial.print(cm);
  Serial.print(" cm");
  Serial.println();
  delay(1000); // wegen Lesbarkeit, ggf. anpassen
}

// ##### Funktion MIKROSEKUNDEN_ZU_CM #####
long MIKROSEKUNDEN_ZU_CM(long Mikrosekunden)
{
  //  Die Schallgeschwindigkeit beträgt bummelige 340 m/s bzw. 29 mS pro Zentimeter
  //  Teilen wir durch 2, da der Schall ja hin und zurück muß
  return (Mikrosekunden / 29 / 2);
}

// haben fertig

Der Code zum Herunterladen als.: ping3.pde

Hier noch ein kurzes Video von Make.

Beispiel II (höhere Genauigkeit)

Änderungen

Für eine Reihe von Anwendungen (z.B. Alarmanlagen und Bewegungserkennung) mag der Code aus Beispiel I ausreichend sein. Wenn es allerdings um Genauigkeit geht (vom Zentimeter in den Millimeter-Bereich) müssen allterdings einige weitere Faktoren berücksicht werden.

Zu diesem Abschnitt wurde ich u.a. durch ein Projekt (Kapitel 5) des sehr empfehlenswerten Buches Arduino: A Quick-Start-Guide von Maik Schmidt aus dem O'Reilly-Verlag angeregt. Ich bedanke mich für die freundliche Genehmigung des O'Reilly-Verlags zur Verwendung des Codes, den ich allerdings ein wenig angepaßt habe.

Fließkomma statt Integerfunktionen

Integerfunktionen werden durch Fließkommaoperationen ersetzt. Vorteil ist die höhere Genauigkeit, welche wir uns über einen höheren Speicherbedarf und eine geringere Geschwindigkeit erkaufen.

Lufttemperatur berücksichtigen

Die Schallgeschwindigkeit in Luft beträgt bei einer Temperatur von 20 Grad Celsius 343 m/s. Dies entspricht rund 29.155 Mikrosekunden pro Zentimeter. Bei anderen Lufttemperaturen können die Abweichungen durchaus bis zu 12 Prozent betragen. Eine relevante Abweichung, die wir berücksichtigen bzw. korrigieren sollten.

Hierzu nutzen wir die Näherungsformel

Schallgeschwingigkeit = 331.5 + (0.6 * t)

( t steht für Lufttemperatur), welche wir natürlich einlesen müssen. Welchen Sensor zur Ermittlung der Temperatur ihr einsetzt, ist zweitrangig. In meinem Artikel zur Temperaturmessung stelle ich eine Reihe geeigneter Sensoren vor.

Die Abweichung beträgt ca. 0,2 Prozent. Für die Perfektionisten unter euch: Luftfeuchtigkeit- und Druck spielen auch noch eine Rolle und könnten - entsprechende Sensoren vorausgesetzt - in der Formel berücksichtigt werden.

Einbautiefe (Abstand Kante)

Gemäß der Spezifikation eignet sich der Sensor für die Abstandsmessung zwischen 2 und 300 cm. Dies hat verschiedene Gründe (Laufzeit, Einbautiefe) und wird mittels der Konstante abstandKante berücksichtigt.

Ein abschließender Hinweis:

Sollten die Daten per serieller Schnittstelle an einen anderen Arduino oder PC weitergeleitet werden, empfiehlt sich die Umwandlung der zu übertragenen Fließkommawerte in hochskalierte Integerwerte (Rundung auf 2 Dezimalstellen, Umwandlung in Long und Multiplikation mit 100. Selbstverständlich muß dann beim Empfänger der Wert durch 100 dividiert werden. Spart rund 1000 Bytes.

Code

/* Parallax Ultraschall-Sensor

   Dieses Programm liest  die Werte des "Parallax PING" Ultraschall-Entfernungsmessers
   aus und gibt die Entfernung des nächstliegenden Objekts zurueck. Es wird ein
   Ultraschall-Impuls ausgesandt, das Echo erfaßt und die Entfernung auf Grund der
   Laufzeit berechnet. Ueber einen geeigneten Sensor wird die Lufttemperatur zur 
   Berechnung der Schallgeschwindigkeit herangezogen. 
  
   Getestet auf einem Arduino Leonardo und IDE 1.5.7

   Die Schaltung:

   * +5V des Parallax an +5V des Arduino
   * GND schwarz des Parallax an GND des Arduino
   * SIG Anschluß des Parallax an Pin 7 digital
   * Temperatur-Sensor an A1 (ggf. anpassen
        
    Inspiriert durch Maik Schmidt:
    http://www.oreilly.de/catalog/9781934356661/index.html       

    fribbe fuer http://macherzin.net
    2014-08-04 Rev. 1.1
    
    Unter Public Domain
*/

const float AbstandKante = 0.0; // bauteilabhaengig, ggf. anpassen
const int Messintervall = 1000; // gewuenschtes Messintervall, ggf. anpassen
float schallKompensiert = 29.155; // "Schallgeschwindigkeit" 20 C
const int PingPin = 7; // Ultraschall-Sensor auf Pin 7 digital
float temperaturAktuell = 20; // Stadardeinstellung, Vorgabe ohne Temperatur-Sensor
const int TemperaturPin = A1; // LM35 an Pin 1 analog, ggf. anpassen ...

void setup()
{
  Serial.begin(9600); // starte serielle Konsole
  while(!Serial); // fuer Leonardo und Co.
}

void loop()
{ 
  HOLE_TEMPERATUR(); // rufe Funktion  
  const unsigned long Dauer = MESSE_DISTANZ();
  if (Dauer >= 20000)
  {
     Serial.println("Fehler: Entfernung zu gross ..."); 
  }
  else
  {
     AUSGABE_ENTFERNUNG(Dauer); 
  }
  delay(Messintervall); // ggf. anpassen
}

// ##### Funktion AUSGABE_ENTFERNUNG #####
void AUSGABE_ENTFERNUNG(const unsigned long Dauer)
{
  Serial.print("Entfernung: ");
  Serial.print(MIKROSEKUNDEN_ZU_CM(Dauer));
  Serial.println(" cm"); 
}

// ##### Funktion HOLE_TEMPERATUR #####
const float HOLE_TEMPERATUR()
{
  // #### wenn Temperatursensor vorhanden ...
  // temperaturAktuell = analogRead(TemperaturPin); // lese LM35
  // temperaturAktuell = (5.0 * temperaturAktuell * 100) / 1024;
  // sonst ...
  temperaturAktuell = 20.00; // Standard, kein Temperatursensor vorhanden
}

// ##### Funktion MESSE_DISTANZ #####
const unsigned long MESSE_DISTANZ()
{
   /* intialisiere den Sensor, indem wir ihm einen kurzen Low-Pulse senden,
     gefolgt von 5-ms High-Puls
   */
   pinMode(PingPin, OUTPUT);
   digitalWrite(PingPin, LOW);
   delayMicroseconds(2);
   digitalWrite(PingPin, HIGH);
   delayMicroseconds(5);
   digitalWrite(PingPin, LOW);
   // benutze den selben Pin als Eingang und berechnen die Dauer des Pulses
   // zwischen aus- und eingehendem Signal
   pinMode(PingPin, INPUT);
   return pulseIn(PingPin, HIGH); 
}

// ##### Funktion MIKROSEKUNDEN_ZU_CM #####
const float MIKROSEKUNDEN_ZU_CM(const unsigned long Mikrosekunden)
{ 
  // Näherungsformel ...
  schallKompensiert = (1 / ((331.5 + (0.6 * temperaturAktuell)) / 10000));
  const float EntfernungNetto = (max(0, Mikrosekunden - schallKompensiert));
  return (EntfernungNetto / schallKompensiert / 2) - AbstandKante;
}

// haben fertig

Sketch zum Hochladen: ping_4.ino

Weitere Links