Grundlagen

Grundlegende Informationen über Ultraschall und Anwendungsbereiche findet ihr hier.

Im folgenden Beispiel benutze ich einen Arduino Uno 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

  • geringe Stromverbrauch (20 mA)
  • die Genauigkeit
  • Einsatzbereich von 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.

Wen es interessiert: Hier ein kleines Video zum Sensor.

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

Ich empfehle in jedem Fall einen Blick auf die sehr informative 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 aus. Es wird ein
   Ultraschall-Impuls ausgesandt, das Echo erfaßt und die Entfernung auf Grund der
   Laufzeit berechnet.

   Die Schaltung:

        * +5V Anschluß (rot) des Parallax an +5V des Arduino
        * GND Anschluß (schwarz) des Parallax an GND des Arduino
        * SIG  Anschluß (gelb) des Parallax an Digital Pin 7

   Die Schaltung beruht auf:

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

   created 3 Nov 2008
   by David A. Mellis
   modified 30 Jun 2009
   by Tom Igoe
   modified 2010-05-20
   by fribbe/macherzin

 */

// wir definieren die Pin-Nummer für den Ausgang des Parallax

const int pingPin = 7;

//jetzt geht's los

void setup()

{

  // Start serielle Kommunikation
  Serial.begin(9600);

}

void loop()

{

  // Definition der Variablen für die Dauer des Pings und für das Ergebnis in cm

  long dauer, cm;

  // wir intialisieren 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);

  // wir berechnen die Entfernung aus der Zeitdifferenz

  cm = mikrosekundenZuZentimeter(dauer);

  // wir geben die Entfernung auf der seriellen Konsole aus

  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

  // wir warten 200 mS, Wert beliebig

  delay(200);

}

long mikrosekundenZuZentimeter(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.

Und ein weiterer interessanter Beitrag auf Nekos Blog.

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 durchaus relevante Abweichung, die wir berücksichtigen bzw. korrigieren sollten.

Hierzu nutzen wir die Näherungsformel

C = 331.5 + (0.6 * t)

wobei wir natürlich die aktuelle Lufttemperatur 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

Der Code ist Arduino-IDE 1.0 kompatibel

/* Parallax Ultraschall-Sensor

   fribbe fuer http://macherzin.net
   2012-05-19 Rev. 1.0

   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. 
  
   IDE 1.0 getestet

   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
        
        Inspiriert durch Maik Schmidt:
        http://www.oreilly.de/catalog/9781934356661/index.html       
*/

const int temperaturPin = 1; // LM35 an Pin 1 analog
const int pingPin = 7; // Ultraschall-Sensor auf Pin 7 digital
const float microsekundenPerCm20 = 29.155; // Schallgeschwindigkeit 20 C
const float abstandKante = 0.2; // bauteilabhaengig
const float sensorRechenwert = (abstandKante * microsekundenPerCm20 * 2);
const int messintervall = 1000; // gewuenschtes Messintervall
float temperaturAktuell = 20;

void setup()
{
  delay(2000); // nur bei Uno Rev. 1 und 2
  Serial.begin(9600);
}

void loop()
{ 
  HoleTemperatur(); // rufe Funktion
  
  const unsigned long dauer = MesseDistanz();
  if (dauer == 20000)
  {
     Serial.println("Fehler: Entfernung zu gross ..."); 
  }
  else
  {
     AusgabeEntfernung(dauer); 
  }
  delay(messintervall);
}

const float MikrosekundenZuZentimeter(const unsigned long Mikrosekunden)
{
   const float entfernungNetto = max(0, Mikrosekunden - sensorRechenwert);
   return (entfernungNetto / microsekundenPerCm20 / 2);
}

const unsigned long MesseDistanz()
{
   // intialisieren den Sensor, indem wir ihm einen kurzen Low-Pulse senden,
   //  gefolgt von 5-ms High-Pulse
   pinMode(pingPin, OUTPUT);
   digitalWrite(pingPin, LOW);
   delayMicroseconds(2);
   digitalWrite(pingPin, HIGH);
   delayMicroseconds(5);
   digitalWrite(pingPin, LOW);

   // benutzen denselben Pin als Eingang und berechnen die Dauer des Pulses
   // zwischen aus- und eingehendem Signal
   pinMode(pingPin, INPUT);
   return pulseIn(pingPin, HIGH); 
}

void AusgabeEntfernung(const unsigned long dauer)
{
  Serial.print("   Entfernung: ");
  Serial.print(MikrosekundenZuZentimeter(dauer));
  Serial.println(" cm");  
}

const float MicrosekundenPerCm()
{
  return (1 / ((331.5 + (0.6 * temperaturAktuell)) / 10000));
}

const float HoleTemperatur()
{
  temperaturAktuell = analogRead(temperaturPin); // lese LM35
  temperaturAktuell = (5.0 * temperaturAktuell * 100) / 1024;
}

// haben fertig

Sketch zum Hochladen: ping_4.ino

Weitere Links