Sharp 2Y0A21 Software
Im letzten Teil haben wir den Sharp 2Y0A21 Abstandssensor mit dem Raspberry Pi und der darauf steckenden ADC Platine verkabelt. Mit der Software wollen wir nun den analogen Messwert in eine Entfernung umrechnen und ausgeben. Das ist nicht ganz einfach, ich erkläre euch Schritt für Schritt wie das geht und worauf man achten muss.
Sharp 2Y0A21 Software
Mit nur wenigen Zeilen Code kann man die Messwerte des Sharp 2Y0A21 Sensors auslesen. Dafür verwenden wir eine fertige Bibliothek von ABElectronics, dem Hersteller der ADC Platine. Kompliziert wird danach jedoch die Umrechnung in die Entfernung. Beginnen wir zuerst mit der Theorie.
Theorie
Der Sharp 2Y0A21 Abstandssensor sendet punktförmig Infrarot Licht aus und empfängt dieses mit einem Empfänger. Anhand des Winkels kann auf die Entfernung zum Objekt geschlossen werden, bei dem der Strahl reflektiert wurde. Technisch gesehen resultiert diese Entfernung in einem analogen Signal. Die Signalstärke lässt sich dabei in die tatsächlich gemessene Entfernung umrechnen. Das klingt nun recht kompliziert, für uns bedeutet das aber nur:
Spannung x = Entfernung y
Wäre die Funktion linear, dann könnte man problemlos die Messwerte (Volt) in Abstände (cm, mm, …) umrechnen. Im Datasheet zum Sensor ist jedoch folgende Funktion abgebildet:
Für unseren Roboter spielt die exakte Entfernung keine große Rolle. Er muss nur wissen ob er sich einem Objekt nähert, oder davon weg fährt. Ab einer bestimmten Grenze (zum Beispiel 10 cm Entfernung) soll er das Objekt umfahren. Wir gehen also davon aus, dass wir mit einer Funktion die Messwerte 1:1 einer Entfernung zuordnen können.
Software
Der erste Schritt ist nun den analogen Output des Sensors ins Programm zu bekommen. Glücklicherweise gibt es dafür vom ADC Board Hersteller bereits fertige frei verfügbare Software. Diese ADC Pi Software ist auf GitHub zu finden.
Um mit dem Script zu arbeiten benötigen wir zuerst einen Raspberry Pi auf dem I2C aktiviert ist. Wie das funktioniert habe ich bereits im Artikel I2C aktivieren erläutert. Ist der Sensor wie im letzten Artikel beschrieben angeschlossen, dann zeigt uns das Kommando:
sudo i2cdetect -y 1
dass man den Sensor über die Adressen 0x68 und 0x69 ansprechen kann. Damit die Kommunikation mit der zuvor von GitHub heruntergeladenen Bibliothek funktioniert benötigen wir noch die python-smbus Bibliothek. Diese installiert man mit folgendem Kommando:
sudo apt-get install python-smbus
Messwerte auslesen
Wir können nun bereits die Messwerte mit einem Demoprogramm von ABElectronics auslesen. Dazu finden wir im Ordner ADCPi die Datei demo-readvoltage.py, welche uns die Messwerte auf der Konsole ausgibt. Mit dem Kommando:
python demo-readvoltage.py
solltest du bei korrekt angeschlossenem Sensor bereits den Wert sehen. Dieser ändert sich auch abhängig davon wie weit das Objekt vor dem Sensor entfernt ist.
Messwerte umrechnen
Der komplexe Teil ist nun diese Volt Werte in einen Abstand in Zentimeter umzurechnen. Dafür benötigen wir eine Funktion. Kennt man die Messwerte, dann kann man mithilfe mathematischer Programme wie Matlab diese in eine Funktion umrechnen. Die Erklärung würde die Komplexität des Tutorials sprengen, deshalb sucht man im Internet nach fertigen Lösungen. In diversen Foren wie beispielsweise dem Arduino Forum findet man Informationen wie andere das bereits gelöst haben. Meine Formel basiert darauf. Ich habe sie lediglich an meine Messungen angepasst.
Ich lese die Werte mit folgendem Skript aus:
#!/usr/python from ABE_ADCPi import ADCPi from ABE_helpers import ABEHelpers import time import os i2c_helper = ABEHelpers() bus = i2c_helper.get_smbus() adc = ADCPi(bus, 0x68, 0x69, 12) while (True): volts = adc.read_voltage(1); #distance = 60.495 * pow(volts, -1.1904) distance = 27.242 * pow(volts, -1.1904) print "Distanz: ",distance time.sleep(0.5)
Zuerst werden zwei externe Python Dateien eingebunden. Das sind die Dateien ABE_ADCPi.py und ABE_helpers.py. Die Helpers Datei benötigen wir um den smbus zu bekommen, da dieser für die aus der Datei ADCPi verwendete Funktion mit selben Namen benötigt wird. Neben dem Bus geben wir auch die über i2cdetect ermittelten Adressen des Sensors 0x68 und 0x69 an.
Spannend wird es nun in der Schleife. Über das adc Objekt können wir mit der read_voltage Funktion den Messwert vom Sharp 2Y0A21 Sensor auslesen. Dieser wird mit der im Arduino Forum gefundenen Formel in eine Distanz (distance) umgerechnet. Die auskommentierte Zeile (#) ist die Version aus dem Forum und die darunter stehende die angepasste Funktion, damit die Messwerte zu meinen Messungen passen.
Zuletzt wird die ermittelte Distanz noch ausgegeben und eine halbe Sekunde gewartet, bis der nächste Messwert ausgegeben wird. Führt man das Programm über die Kommandozeile mit angeschlossenem Sensor aus, dann liefert es beispielsweise folgende Ausgabe:
Die Werte stimmen mit meinen Messungen überein. Die Genauigkeit liegt bei ca. einem Zentimeter, das ist für meinen Anwendungsfall genug. Benötigt man genauere Werte, so sollte man in jedem Fall die Formel anpassen.
Probleme
Die Sharp 2Y0A21 Software funktioniert recht gut und liefert plausible Messwerte. Leider besteht aber das grundlegende Problem nach wie vor. Anhand des Diagramms sehen wir, dass für Abstände ab ca. 5 cm die Messwerte kontinuierlich fallen.
- 3 Volt sind umgerechnet ca. 6 cm
- 2,3 Volt sind umgerechnet ca. 10 cm
- 0,9 Volt sind umgerechnet ca. 30 cm
- usw.
Ab einem Abstand des Objekts von 5 cm funktioniert die Umrechnung problemlos. Kommt das Objekt nun jedoch näher, dann liefert die selben Messwerte plötzlich andere Abstände. Beispielsweise sollte 0.9 Volt nun ca. 1 cm entsprechen. Die gesamten Messwerte sind also doppelt vergeben. Dieses Problem kann man durch mehrere Lösungswege umgehen:
- Infrarot Sensor so positionieren, dass Objekt nie näher als 5 cm kommen kann
Ist die Grundfläche des Roboters groß genug, dann kann man den Sensor 5 cm hinter dem vorderen Rand positionieren. - 2. Infrarot Sensor auf gegenüberliegender Seite
Eine sehr gute Lösung sind 2 Sensoren die beide schräg gestellt werden, damit sich deren Sichtfeld überschneidet. Hat man die zwei Sensoren gut positioniert, dann kann man über die Software den Abstand zum Objekt um vieles genauer errechnen und das Problem der doppelten Werte umgehen. - 2. Sensor, beispielsweise ein Ultraschall Sensor
Funktioniert ähnlich wie die Lösung mit 2 Infrarot Sensoren. Nur wird mit einem Ultraschall Sensor der ganz andere Charakteristika hat ein zweiter Wert geliefert. Im Programm entscheidet man nach Plausibilität. - Erfahrungswerte bei nur einem Sensor
Hat man nur einen Infrarot Sensor, so kann man auch Erfahrungswerte vorangegangener Messungen nehmen. Bewegt man sich konstant auf ein Objekt zu, dann kann die Software annehmen, dass trotz steigender errechneter Entfernung ab 5 cm das Objekt weiter näher kommt. Das natürlich nur unter der Voraussetzung, der Roboter hat die Bewegung nicht gestoppt oder die Richtung geändert.
Fazit
Es ist möglich mit dem Sharp 2Y0A21 Sensor die Entfernung recht genau zu bestimmen. Eine qualitativ hochwertige Lösung ist das noch nicht, für einen Roboter reicht dieser Ansatz aber völlig aus. Will man die Entfernung exakt und kontinuierlich protokollieren, dann benötigt die Software noch mehr Komplexität und muss mitunter auch anhand von früheren Messwerten oder Messwerten anderer Sensoren eine Einschätzung der Lage geben.
Habt ihr eine bessere Funktion die genauere Werte liefert?
Teil 1 | Teil 2 | Teil 3 | Teil 4 | Teil 5