Im vierten Teil unserer MuRCSPI Raspberry Pi Roboter Reihe geht es darum die Elektronik für den Roboter auf einer Erweiterungsplatine (Hat) unterzubringen und den Roboter fahrbereit zusammenzubauen.
In einem ersten Beispiel Programm soll der Roboter autonom fahren und Hindernissen ausweichen.
Roboter Hat
Die gesamte Elektronik für den Roboter passt auf ein Rasperry Pi Proto Hat. Darauf ist auch noch genug Platz für spätere Erweiterungen. Da nur Fertigmodule zum Einsatz kommen, sind nur Steckverbinder und Drahtverbindungen auf dem Proto-Hat zu verlöten.
Benötigt werden:
- Raspberry Pi Proto Hat
- Stiftleisten
- Buchsenleisten
- Silberdraht und isolierte Litze
- Batteriefach 6xAA (MURCS v2) bzw. zwei 3xAA (Dagu Magician)
- USB Powerpack 5V/1A mit Micro USB Kabel
- Kabelbinder, Klettband
- 4 M2.5×30 Schrauben, 8 Muttern M2.5
- 4 M3x10mm Distanzbolzen (nur Dagu Magician)
Entsprechend einfach ist der Aufbau. So sieht das zusammengelötete Proto-Hat aus:
[pe2-image src=“http://lh3.googleusercontent.com/-uCQJIBp-ues/VYXYxcO5IrI/AAAAAAAANhA/SoyIMNBl6pk/s144-c-o/IMG_5518.JPG“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6162570009030238898″ caption=““ type=“image“ alt=“IMG_5518.JPG“ ]
Die Rückseite zeigt die Verdrahtung des Proto-Hat. Bei dem verwendeten Adafruit Proto-Hat gibt es eine extra Reihe, auf der die Raspberry Pi IOs herausgeführt sind. Das macht die Verdrahtung wesentlich einfacher.
[pe2-image src=“http://lh3.googleusercontent.com/-OgqYEx1c3m4/VYXYjM05nWI/AAAAAAAANgg/CJx-6jiNdac/s144-c-o/IMG_5514.JPG“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6162569764376517986″ caption=““ type=“image“ alt=“IMG_5514.JPG“ ]
Das bestückte Proto-Hat mit dem A/D Wandler Modul, Motor-Treiber und Anschlüssen für Sensoren etc.
[pe2-image src=“http://lh3.googleusercontent.com/-eQBoaY8duPc/VZ2Bf-n-9aI/AAAAAAAANv4/zKwjeU15XEc/s144-c-o/robo-hat.jpg“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6169229450954077602″ caption=““ type=“image“ alt=“robo-hat.jpg“ ]
Der Schaltplan sieht dann so aus:
Zusammenbau
Das Proto-Hat wird einfach auf das Raspberry Pi Board gesteckt. Die Verdrahtung von Sensor, Motoren und Motor Spannungsversorgung entnimmt man der folgenden Abbildung. Das Raspberry Pi Board wird hier über ein USB Powerpack versorgt. Die Motorspannungsversorgung besteht aus einem 6xAA Akkupack.
[pe2-image src=“http://lh3.googleusercontent.com/-dpdkKpoyT1Y/VZ2BiqC-BEI/AAAAAAAANwA/3YufM069ApI/s144-c-o/robo-hat-motors-ir-sensor.jpg“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6169229496969724994″ caption=““ type=“image“ alt=“robo-hat-motors-ir-sensor.jpg“ ]
So sieht dann der fertige Roboter auf dem MURCS v2 Chassis aus.
[pe2-image src=“http://lh3.googleusercontent.com/-DZ4_P4-f84k/VYXZGHs1JxI/AAAAAAAANho/TmO7_aBm5kA/s144-c-o/IMG_5524.JPG“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6162570364295915282″ caption=““ type=“image“ alt=“IMG_5524.JPG“ ]
Beim Dagu Magician Chassis ist die untere Ebene mit dem USB Powerpack und zwei in Reihe geschaltete 3xAA Akkupacks belegt. Das besondere bei dem USB Powerpack: Darin befindet sich ein Audioverstärker und ein kleiner Lautsprecher.
[pe2-image src=“http://lh3.googleusercontent.com/-d8ESEe8LFAQ/VZ2BdfunuLI/AAAAAAAANvw/6g1YWZnu3lU/s144-c-o/IMG_5544.JPG“ href=“https://picasaweb.google.com/100614490999857774768/MURCSPi#6169229408300677298″ caption=““ type=“image“ alt=“IMG_5544.JPG“ ]
Die obere Ebene bleibt komplett frei für die Elektronik.
Software Kollisionsvermeider
Den Raspberry Pi betreibe ich normalerweise „headless“ ohne Tastatur und Bildschirm. Über SSH (Putty untet Windows) kann man vom PC aus mit dem Raspberry Pi kommunizieren. Der Datenaustausch erfolgt über SCP (WinSCP bei Windows). Hilfreich ist ein WLAN USB Dongle, dann funktioniert das ganze sogar drahtlos.
Nun kann der Roboter in Betrieb gehen. Fehlt nur noch das passende Programm. Los geht es mit einem Python Sketch für einen Kollisionsvermeider. Es baut auf den beiden Test-Programmen für die Sensorabfrage und die Motoransteuerung.
#!/usr/bin/python from __future__ import print_function import time, signal, sys from pololu_drv8835_rpi import motors, MAX_SPEED 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' OBSTACLE_FAR = 30 # 30cm OBSTACLE_NEAR = 20 # 20cm OBSTACLE_CLOSE = 10 # 10cm class ADS1015(object): 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 adc = ADS1x15(ic=ADS1015) def __init__(self): self.gain = 2048 # +/- 2.048V self.sps = 250 # 250 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! def read(self, port): value = self.adc.readADCSingleEnded(port, self.gain, self.sps) return value class Motor(object): speedL = 0 speedR = 0 actSpeedL = 0 actSpeedR = 0 SPEED_STEP = 10 def __init__(self): self.speedL = 0 self.speedR = 0 self.actSpeedL = 0 self.actSpeedR = 0 def setSpeed(self, sr, sl): self.speedL = sr self.speedR = sl print ("speed", self.speedR, self.speedL) def updateMotors(self): if self.speedL == 0: self.actSpeedL = 0 elif self.actSpeedL < self.speedL: self.actSpeedL += self.SPEED_STEP elif self.actSpeedL > self.speedL: self.actSpeedL -= self.SPEED_STEP if self.speedR == 0: self.actSpeedR = 0 elif self.actSpeedR < self.speedR: self.actSpeedR += self.SPEED_STEP elif self.actSpeedR > self.speedR: self.actSpeedR -= self.SPEED_STEP print ("motor lt, rt", self.actSpeedR, self.actSpeedL) motors.setSpeeds(self.actSpeedR, self.actSpeedL) time.sleep(0.100) if __name__ == "__main__": print ('roboPi obstacle avoider') ads1015 = ADS1015() motor = Motor() motors.setSpeeds(0, 0) while 1: # Read channel 3 in single-ended mode using the settings above value = ads1015.read(0) distance = 14 / (value/1000 - 0.1) print "value: {0:.0f} mV distance: {1:.0f} cm".format(value, distance) if value > OBSTACLE_CLOSE: motor.setSpeed(0, 0) motor.updateMotors() print ('stop') time.sleep(0.5) while distance > OBSTACLE_NEAR: value = ads1015.read(0) distance = 14 / (value/1000 - 0.1) motor.setSpeed(-MAX_SPEED/4, MAX_SPEED/4) motor.updateMotors() elif distance > OBSTACLE_NEAR: motor.setSpeed(MAX_SPEED/4, MAX_SPEED/4) print ('slow') elif distance > OBSTACLE_FAR: motor.setSpeed(MAX_SPEED/2, MAX_SPEED/2) print ('half speed') else: motor.setSpeed(MAX_SPEED, MAX_SPEED) print ('max speed') motor.updateMotors()
Gestartet wird das Programm mit:
sudo python collision-avoider.py
Links
Die weiteren Teile der Serie: