Arduino für Fledermäuse
Fledermäuse sind bekanntlich blind. Objekte erkennen sie stattdessen mit Echolot (Sonar). Bewegliche Dinge im Internet der Dinge wie Roboter oder Drohnen können daher von Fledermäusen lernen.
- Dr. Michael Stal
Fledermäuse sind bekanntlich blind. Objekte erkennen sie stattdessen mit Echolot (Sonar). Bewegliche Dinge im Internet der Dinge wie Roboter oder Drohnen können daher von Fledermäusen lernen.
In der letzten Folge hatten wir uns mit Infrarotsensoren für Bewegungserkennung beschäftigt. Der dafür verwendete PIR-Sensor ist in der Regel stationär und erkennt Bewegungen in einem bestimmten Radius. Nun kehren wir das Szenario um: Unser System ist beweglich und soll stationäre (und natürlich auch bewegliche) Objekte in seiner näheren Umgebung nicht nur erkennen, sondern auch deren Abstand bestimmen. Dadurch lassen sich beispielsweise Kollisionen vermeiden. Abstandssensoren im PKW sind ein verbreitetes Beispiel für die Anwendung dieses Konzepts. Ebenso natürlich mobile Roboter.
Was bisher geschah:
- Bewegungserkennung durch Infrarot-Strahlung
- Anschluss von LCD-Displays über den IIC-Bus
- Lauschen mit Sensoren
- JavaScript an Arduino: Es werde Licht
- Anschluss vieler LEDs an wenige Ausgänge
- Do-it-Yourself-Projekt: iXduino – Arduino on a Breadboard
- Crashkurs "Elektronik für IoT-Anwendungen" (Teil 3 von 3)
- Crashkurs "Elektronik für IoT-Anwendungen" (Teil 2 von 3)
- Crashkurs "Elektronik für IoT-Anwendungen" (Teil 1 von 3)
Funktionsprinzip
Für den genannten Zweck benötigen wir Ultraschallsensoren (englisch: Ultrasonic Sensors). Die prinzipielle Funktion eines solchen Sensors finden Sie in folgender Illustration:
- Der Sensor verschickt einen Puls von Ultraschallwellen.
- Ist ein Objekt in Reichweite, reflektiert es die Wellen.
- Ein Empfänger im Sensor erkennt dieses Echo.
- Aus der Zeit tDelta von Versenden des Pulses bis zum Eintreffen beim Empfänger und der Ultraschallgeschwindigkeit cUS (340 m/sec) ergibt sich Distanz d = 0.5 * (cUS / tDelta). Der Faktor 0.5 berücksichtigt, dass in Wirklichkeit die gemessene Zeit sowohl den Hinweg (roter Pfeil) als auch den Rückweg (grüner Pfeil) umfasst.
Der Sensor HC-SR04 und seine Verwandten
Für den Arduino (und andere Boards) ist der Baustein HC-SR04 das Mittel der Wahl. Die Preise dafür bewegen sich auf eBay zwischen 2 und 5 Euro. Chinesische Anbieter haben den Sensor auch schon für 1 Euro im Angebot. Dieser Baustein hat 4 Pins: Vcc, GND, Echo, Trig. Deren Bedeutung lernen wir weiter unten kennen.
Es gibt auch einen preisgünstigen Sensor mit der Bezeichnung HY-SRF05, der dem HC-SR04 nachfolgt, und einen fünften Pin mit der Bezeichnung OUT besitzt. Wenn Sie diesen OUT-Pin ignorieren, können Sie den Sensor HY-SRF05 statt des HC-SR04 in den nachfolgenden Beispielen verwenden, ohne dass eine Änderung in den Programmen notwendig wäre. Wenn Sie aber den OUT-Pin auf GND legen, kann der Echo-Pin unverbunden bleiben, da der Trig-Pin dann alle Aufgaben (Puls auslösen + Echo empfangen) übernimmt, und sich wie ein Parallax Ping verhält.
Der Parallax Ping schlägt mit über 20 bis 30 Euro zu Buche. Er besitzt drei Pins Vcc, Ping, und Gnd. Wegen seines teuren Preises verwende ich den HC-SR04, der sich auch noch als Ping ausgeben kann. Wie, erläutere ich weiter unten.
Auf dem Foto sind die Pins des HC-SR04 gut zu erkennen. Links die Spannungsversorgung (Vcc), rechts Erde (GND), halb links der Trigger zur Steuerung des Signals (Trig), halb rechts der Pin für die empfangenen Echos (Echo).
Die Schaltung
Der Schaltungsaufwand hält sich in Grenzen. Neben einen Arduino Uno benötigen wir Verbindungsdrähte, einen HC-SR04, und ein Breadboard, das aber nur als "Stativ" für den Sensor fungiert.
In unserer Schaltung verbinden wir:
- Roter Draht: 5V (Arduino) mit Vcc (HC-SR04)
- Schwarzer Draht: GND (Arduino) mit GND (HC-SR04)
- Gelber Draht: Arduino Digitalpin 12 mit Trig (HC-SR04)
- Grüner Draht: Arduino Digitalpin 13 mit Echo (HC-SR04)
All you need is Code
Der nachfolgende Sketch
- setzt zunächst den Trigger auf LOW: digitalWrite(trigPin, LOW)
- wartet 2 Mikrosekunden
- setzt den Trigger dann auf HIGH: digitalWrite(trigPin, HIGH)
- wartet 10 Mikrosekunden, denn erst nach dieser Zeit sendet der Sensor Ultraschallwellen, im Detail ein über 8 Zyklen abgefeuertes 40-KHz-Burst-Signal
- liest daraufhin die Dauer bis zum Empfang des Echos: duration = pulseIn(echoPin, HIGH)
- errechnet daraus die Distanz in cm
Die Konstante 29 in der Distanzberechnung
distance = (duration / 2) / 29 = duration / 58
ist der Schallgeschwindigkeit in Höhe von 340 m/sec geschuldet. Für die Distanz von 1 cm benötigt der Ultraschall rund 29 Mikrosekunden. Die vom HC-SR04 zurückgelieferte Zeitdauer ist in der Einheit Mikrosekunden angegeben.
Die Methode
pulseIn(pin, value)
misst die Dauer zwischen einem Puls und dem Empfang des Echos.
Ist value = HIGH, wartet die Funktion am spezifizierten Pin bis das Signal auf HIGH wechselt, um dann die Zeit zu messen bis das Signal wieder auf LOW zurückfällt.
Ist value = LOW, startet die Messung, sobald der Pin aus LOW geht, und misst die Zeit bis zum nächsten Signalwechsel nach HIGH.
#define trigPin 12 // über diesen Pin senden wir Ultraschall-Pulse
#define echoPin 13 // über diesen Pin empfangen wir das Echo
const int SENSORRANGE = 300; // Reichweite
void setup() {
Serial.begin (9600);
pinMode(trigPin, OUTPUT); // Zum Auslösen des Ultraschalls-Puls
pinMode(echoPin, INPUT); // Zum Einlesen der Dauer
}
void loop() {
long duration, distance;
digitalWrite(trigPin, LOW); // Signal auf LOW setzen
delayMicroseconds(2); // Kleine Wartezeit
digitalWrite(trigPin, HIGH); // Signal auf HIGH setzen
delayMicroseconds(10); // Kleine Wartezeit
duration = pulseIn(echoPin, HIGH); // Zeitdauer bis Empfang des Echo
distance = duration/58; // Distanz berechnen
Serial.print("Gemessene Distanz = ");
Serial.println(distance);
if (distance >= SENSORRANGE || distance <= 0){
Serial.println("Außerhalb der Reichweite");
}
else {
Serial.print(distance);
Serial.println(" cm");
}
delay(500); // Zeit für eine kleine Verschnaufpause
}
Bewegen Sie einfach Ihre Hand vor dem Ultraschallsensor vor und zurück. Oder bewegen Sie den Sensor auf Gegenstände zu, und beobachten Sie die am seriellen Monitor ausgegebenen Messwerte.
NewPing
Bislang haben wir die Standardfunktionalität der Arduino IDE benutzt, um den Ultraschallsensor anzusteuern. Tim Eckel hat sich mit der Thematik intensiv beschäftigt und dabei einige Unzulänglichkeiten entdeckt. Als Ergebnis entstand die Bibliothek NewPing. Hier finden Sie die betreffende NewPing-Webseite. Weiter unten auf der Webseite finden Sie den Downloadlink für die gezippte Bibliothek.
Wer sich genauer dafür interessiert, welche Unzulänglichkeiten NewPing behebt, für den möchte ich ein paar Angaben aus Tims Webseite aufzählen. Beispielsweise
- brauchen manche Ultraschall-Sensoren Zeit zum "Aufwachen", falls Sie eine Sekunde lang kein Signal mehr empfangen,
- implementiert NewPing eine genauere Distanzberechnung,
- benutzt es nicht das fehlerträchtige und ungenaue pulseIn(),
- nutzt es aus Performanzgründen interne Register um Werte an Ports auszulesen,
- unterstützt die Bibliothek eine ganze Reihe von Sensortypen.
Ein Sketch mit NewPing könnte nachfolgende Gestalt haben.
Hinweise:
- Wie immer müssen Sie in der Arduino IDE unter Menüpunkt Sketch/Include Library/Add .ZIP Library die gezippte NewPing-Bibliothek inkludieren.
- Erhalten Sie nach dem Upload auf den Arduino "Zeichenmüll" am seriellen Monitor angezeigt, stimmt die Empfangs-Baudrate des seriellen Monitors nicht. Wählen Sie rechts unten im Fenster des seriellen Monitors die Baudrate 115200 synchron zur Senderate des Sketches. Dann sollten Sie wieder vernünftige Ausgaben erhalten.
include <NewPing.h>
#define trigPin 12 // Trigger Pin an Arduino Pin 12
#define echoPin 13 // Echo Pin an Arduino Pin 13
#define SENSORRANGE 200 // Reichweite für den Sketch < maximale Reichweite
NewPing sonar(trigPin, echoPin, SENSORRANGE); // NewPing-Instanz kreieren
void setup() {
Serial.begin(115200); // Ausgabe über seriellen Monitor: 115200 Baud
}
void loop() {
delay(50); // 50 msecs zwischen Pings. Muss > 29 sein
// Ping senden, Echo empfangen, Distanz zurückerhalten:
unsigned int result = sonar.ping();
Serial.print("Echo empfangen: ");
Serial.print(sonar.convert_cm(result)); // Entfernung in cm
// Rückgabe von 0 => außerhalb Reichweite
Serial.println("cm");
}
Aus HC-SR04 einen Parallax Ping machen
Sie haben eventuell festgestellt, dass die Arduino IDE unter dem Menü File | Examples | Sensors | Ping einen Sketch mitbringt, der den teureren Parallax Ping verwendet, aber nicht mit dem HC-SR04 zurechtkommt. Der Parallax Ping hat 3 Pins, einen Vcc-, einen GND- und einen Ping-Anschluss. Es gibt also keine Trennung in Trig und Echo wie beim HC-SR04.
Im Internet finden Sie verschiedene Vorschläge, wie der HC-SR04 sich als Parallax Ping ausgeben kann. Manche Beispiele verbinden einfach den Trig- und den Echo-Anschluss miteinander und schließen beide gemeinsam an einen digitalen Pin des Arduino: Trig + Echo = Ping.
Wer auf Nummer sicher gehen und Störungen vermeiden will, entfernt zusätzlich beim HC-SR04 den 10k-Ohm-Pull-up-Widerstand am Trig-Eingang und verbindet stattdessen Trig und Echo des HC-SR04 mit einem 10-k-Ohm-Widerstand. Fertig ist der Ping-Clone mit 3 Pins.
Beim eingangs erwähnten HY-SRF05 ist das alles nicht nötig. Sie müssen nur den OUT-Pin mit GND verbinden, sodass der Trig-Pin wie der Ping-Pin des Parallax Ping agiert.
One More Thing
Wie immer wollen wir auch diesmal JavaScript zum Ansteuern des Distanzmessers auf Basis HC-SR04 verwenden. Unsere Partner sind wieder einmal Node.js und johnny-five. Johnny-five enthält folgende Dokumentation zu seiner Proximity-API. Auch eine ganze Reihe weiterer Ultraschallsensoren, Infrarot-basierter Sensoren u.v.a.m. finden dort Unterstützung.
Um JavaScript nutzen zu können, brauchen wir eine Firmata-Firmware für den Arduino, die das beschriebene Ping-Verhalten unterstützt. Leider reicht es diesmal nicht aus, den Firmata Builder zusammen mit der ConfigurableFirmata-Bibliothek einzusetzen.
Stattdessen müssen wir den umständlichen Weg über PingFirmata gehen. Dazu ist die Installation von interchange auf Node.js notwendig.
npm install nodebots-interchange
Danach suchen Sie, wo genau sich interchange im Dateisystem versteckt (auf OS X ist die Installation unter ./node_modules/.bin zu finden).
Und anschließend rufen Sie auf:
interchange install hc-sr04 -a uno -p <port>
<port> meint die Bezeichnung des USB-Ausgangs, an dem Sie auf Ihrem Mac, PC, Linux-PC das Arduino-Board angeschlossen haben. Den Namen finden Sie, indem Sie in der Arduino IDE unter dem Menü Tools/Port den entsprechenden Port-Namen identifizieren. Lesen Sie weitere Details auf folgender Seite.
Ultima-Ratio ist der direkte Upload des Firmata-Sketches auf Ihr Board unter Nutzung der Arduino IDE. Schnuppern Sie ruhig in den Code des Sketches hinein.
Für das Nutzen von johnny-five müssen Sie des Weiteren die Pins Trig und Echo des HC-SR04 erst miteinander, und dann beide gemeinsam mit Digital-Pin 13 des Arduino verbinden.
Hier das j5-Beispiel:
var five = require("johnny-five");
var board = new five.Board();
board.on("ready", function() {
var proximity = new five.Proximity({
controller: "HCSR04",
pin: 13
});
proximity.on("data", function() {
console.log("cm: ", this.cm);
});
});
Sie können statt des digitalen Eingangs 13 auch einen analogen verwenden, müssen dann aber im Code für den Pin beispielsweise 13 durch "A0" ersetzen.
Backpacker
Wenn Sie einen HC-SR04-Sensor über ein sogenanntes I2C-Backpack anschließen, entfällt die Notwendigkeit für eine spezialisierte Version von Firmata. Ein I2C-Backpack ist ein Extra-Arduino {Nano, Uno, Pro Mini}, den Sie mit PingFirmata bespielen, und an dem sie den HC-SR04 Sensor anschließen. Das eigentliche Arduino-Host-Board verbinden Sie anschließend mit dem Backpack. Nähere Information dazu finden Sie hier: I2C-Backpack. Sie nutzen also einen zusätzlichen Arduino als Bindeglied zwischen Sensor und Ihrem Arduino, und können den Ultraschall-Sensor dadurch über das I2C-Protokoll ansprechen.
Im obigen Code würde sich nur die Vereinbarung der Variablen proximity ändern in:
var proximity = new five.Proximity({
controller: ""HCSR04I2CBACKPACK"
});
Zusammenfassung
In diesem Teil haben wir den Umgang mit dem Distanzmesser HC-SR04 in aller Ausführlichkeit kennengelernt. Experimentieren Sie ruhig etwas mit den Schaltungen und dem Code. In den drei kommenden Folgen beschäftigen wir uns mit Motoren. Ich wünsche Ihnen bis dahin viel Spaß beim Experimentieren. ()