Tutorial – Raspberry Pi Roboter – Teil 1: Sensoren

Einen Roboter mit dem Raspberry Pi zu bauen, stand schon lange auf meiner Agenda. Allerdings hatten die ersten Raspberry Pi Modelle nur einen Hardware PWM Pin. Eigentlich zu wenig für einen Roboter. Seit dem Raspberry Pi B+ stehen nun 3 PWM Ausgänge zur Verfügung. Nun gibt es keine Ausreden mehr, ein Raspberry Pi gesteuerter Roboter muss her.

Ein einfacher Roboter mit 2 angetriebenen Rädern und einem Stützrad, sollte für den Anfang reichen. Dazu ein Sensor zur Hindernis Erkennung, fertig ist der Starter-Roboter für den Raspberry Pi. Als zusätzliche Option kommt später noch ein Servo und eine Raspberry Pi Kamera dazu. Zunächst ohne Bilderkennung, nur zum Streamen des Livebildes für ein Remote-Programm. Viel später dann auch mit OpenCV zur Bilderkennung.

Die Software für den MuRSCPi Roboter ist in Python geschrieben. Python bietet eine sehr gute Unterstützung an Bibliotheken für alle möglichen Zwecke.

Los geht die Tutorial Reihe mit einem Einblick zur Verwendung von Sensoren zur Hindernis Erkennung.

Sensoren

Sensoren bilden die Sinne des Roboters zum sehen, hören, fühlen, etc. Über die Sensoren nimmt der Roboter seine Umwelt wahr und kann z.B. Hindernisse erkennen und versuchen auszuweichen.

Distanz-Sensoren

Ein Distanz Sensor kann die Entfernung zu einem Hindernis messen und an den Controller zurückliefern. Gängige Sensoren arbeiten mit Ultraschall oder Infrarot Licht. Schauen wir uns zunächst den Infrarot-Sensor genauer an.

Infrarot-Sensor

Während man bei Ultraschall Sensoren anhand der Laufzeit die Entfernung bestimmen kann, funktioniert dieses Verfahren bei Infrarot Sensoren nicht, da hier mit Licht gearbeitet wird. Bekanntermaßen liegt die Lichtgeschwindigkeit bei ca. 300000 m/s. Statt dessen kommt das Triangulationsverfahren zum Einsatz. Dabei wird der Winkel bestimmt, mit der das Licht vom Hindernis reflektiert wird.

Der Sharp GP2Y0A60SZ ist ein Infrarot Sensor, der nach dem Triangulationsverfahren arbeitet. Damit können Hindernisse im Bereich 10..150cm detektiert werden. Den Sensor gibt es fertig mit einem Carrier Board von Pololu. Das besondere an diesem Sensor ist, dass es ihn auch in einer 3V Version gibt. Das spart schon mal zusätzliche Pegelwandler. Das Ausgangssignal ist eine analoge Spannung die je höher ist, desto näher sich das Hindernis vor dem Sensor befindet. Aber Achtung, die Ausgangsspannung ist nicht linear. Befindet sich das Hindernis direkt vor dem Sensor (<10cm) sinkt die Spannung wieder.

[pe2-image src=“http://lh3.googleusercontent.com/-d_QEWNM3uoM/VYXYY3k2fBI/AAAAAAAANgQ/msO7QSvbWJc/s144-c-o/IMG_5511.JPG“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6162569586873367570″ caption=““ type=“image“ alt=“IMG_5511.JPG“ ]

Die Eckdaten des Sharp IR Sensors:

[table id=3 /]

in der Praxis konnte ich nur Entfernungen bis max. 80cm detektieren. Das ist für diese Art Sensor absolut in Ordnung.

A/D Wandler

Was dem Raspberry Pi gegenüber einem Mikrocontroller Board, wie dem Arduino; fehlt sind A/D Wandler. Um den Infrarot Sensor einlesen zu können wird ein A/D Wandler benötigt. Zum Glück gibt es fertige A/D Wandler Module und ICs, die über I2C angeschlossen werden können. Dazu gehört z.B. der 4-fach A/D Wandler ADS1015 von TI, verfügbar als Breakout Modul von Adafruit.

[pe2-image src=“http://lh3.googleusercontent.com/-w-zXIc-kh-o/VYXYm0UST1I/AAAAAAAANgo/LSJrVpp01nk/s144-c-o/IMG_5515.JPG“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6162569826516750162″ caption=““ type=“image“ alt=“IMG_5515.JPG“ ]

Über die I2C Pins und die 3,3V Stromversorgungs Pin wird der A/D Wandler mit dem Raspberry Pi verbunden. Der Sensor wird ebenfalls mit 3,3V versorgt, der Ausgang wird mit einem der 4 A/D Wandler Pins verdrahtet. Der 4. Pin des Sensors, die Enable Leitung bleibt offen,kann aber bei Bedarf an einen freien IO des Raspberry Pi angeschlossen werden. Die Schaltung zum Anschluss des Sensors und A/D Wandlers sieht dann so aus:

raspi-ads1015

[pe2-image src=“http://lh3.googleusercontent.com/-Z4YhYjudcg4/VYat_HkvWsI/AAAAAAAANss/96ngUej-O7A/s144-c-o/SharpIR-ADC-RasPi_Steckplatine.jpg“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6162804439979612866″ caption=““ type=“image“ alt=“SharpIR-ADC-RasPi_Steckplatine.jpg“ ]

Software IR-Sensor Test

Zunächst ein Testprogramm zum Einlesen und auswerten des des Sharp IR Distanz Sensors. Das Testprogramm benutzt die Adafruit ADS1x15 Pi Bibliothek.

Damit das Programm funktioniert, muss zunächst der I2C Treiber auf dem Raspberry Pi eingeschaltet werden.

Mit dem Raspi-Config Programm wird zunächst das I2C-Schnittstelle enabled. Starten Sie das Raspi-Config Programm mit:
sudo raspi-config

Unter ‚8 Advanced Options‘ befindet sich der Eintrag ‚A7 I2C‘. Benatworten sie beide Fragen mit ‚Ja‘ bzw. ‚Yes‘ um das I2C Interface einzuschalten.

Zudem ist noch eine Änderung in der System-Datei/etc/modules.

Zunächst öffnen wir die Datei mit:
sudo nano /etc/modules

Dann fügen wir folgende Zeilen am Ende der Datei ein:

i2c-bcm2708
i2c-dev

Mit ^O speichert man die Änderungen. ^X beendet den Editor. Nach einem Reboot steht der Treiber zur Verfügung
sudo reboot

#!/usr/bin/python

import time, signal, sys
from Adafruit_ADS1x15 import ADS1x15

def signal_handler(signal, frame):
        print 'You pressed Ctrl+C!'
        sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
#print 'Press Ctrl+C to exit'

ADS1015 = 0x00  # 12-bit ADC
ADS1115 = 0x01  # 16-bit ADC

# Select the gain
# gain = 6144  # +/- 6.144V
gain = 4096  # +/- 4.096V
# gain = 2048  # +/- 2.048V
# gain = 1024  # +/- 1.024V
# gain = 512   # +/- 0.512V
# gain = 256   # +/- 0.256V

# Select the sample rate
# sps = 8    # 8 samples per second
# sps = 16   # 16 samples per second
# sps = 32   # 32 samples per second
# sps = 64   # 64 samples per second
# sps = 128  # 128 samples per second
sps = 250  # 250 samples per second
# sps = 475  # 475 samples per second
# sps = 860  # 860 samples per second

# Initialise the ADC using the default mode (use default I2C address)
# Set this to ADS1015 or ADS1115 depending on the ADC you are using!
adc = ADS1x15(ic=ADS1015)

while 1:
    # Read channel 3 in single-ended mode using the settings above
    value = adc.readADCSingleEnded(0, gain, sps)
        distance = 14 / (value/1000 - 0.1)

        print "value: {0:.0f} mV distance: {1:.0f} cm".format(value, distance)
    time.sleep(0.1) 

Gestartet wird das Programm mit:

sudo python irsensor-test.py

Das Programm gibt zyklisch alle 100mS den Spannungspegel und die Distanz zum Hindernis in cm aus. Die nichtlineare Kennlinie des Sensors wird durch die folgende Funktion recht gut nachgebildet:

14/(Sensorspannung in V - 0.1)

So sieht die Ausgabe des Sensor Test Programms aus:


value: 1072 mV distance: 14 cm
value: 1040 mV distance: 15 cm
value: 960 mV distance: 16 cm
value: 886 mV distance: 18 cm
value: 830 mV distance: 19 cm
value: 788 mV distance: 20 cm
value: 754 mV distance: 21 cm
value: 704 mV distance: 23 cm
value: 672 mV distance: 24 cm
value: 664 mV distance: 25 cm

Weblinks

Eine Bezugsquelle für das ADS1015 Modul ist z.B. Watterott. Das Sharp GP2Y0A60SZLF Modul gibt es derzeit nur bei EXP-Tech.

Wie geht es weiter

Im zweiten Teil geht es dann weiter mit dem Antrieb für unseren Raspberry Pi Roboter.

Links

Die weiteren Teile der Serie:

6 Antworten auf „Tutorial – Raspberry Pi Roboter – Teil 1: Sensoren“

  1. Super Tutorial

    Leider habe ich das Problem, das bei mir der Spannungspegel nur minimal schwankt und die Strecke immer 1 ist.
    Ich habe das ganze sowohl mit dem ADS1015 und ADS1115 getestet. Zudem verwende ich die aktuelle Adafruit Bibliothek

    Eine Idee woran es liegen könnte?

      1. Hallo,
        Ich habe einen 2. Sensor vom selben Typ probiert aber das selbe Problem.
        Bekomme immer um die 1300mv egal wie weit entfernt das nächste Objekt ist.

        1. import time
          import Adafruit_ADS1x15

          adc = Adafruit_ADS1x15.ADS1015()

          GAIN = 1

          while 1:
          value = adc.read_adc(0, gain=GAIN)
          distance = 14 / (value/1000 – 0.1)
          print „value: {0:.0f} mV distance: {1:.0f} cm“.format(value, distance)
          time.sleep(1.0)

Schreibe einen Kommentar

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