... und weiter geht's.
Wie man das Ultraschallmodul SRF04 anhängt, habe ich hier beschrieben:
https://www.roboternetz.de/community...ernungsmessung
Wenn man das Modul mit 3,3 Volt betreibt, benötigt man noch immer kein Steckbrett - allerdings ist damit eine zuverlässige Messung nur bis Entfernungen bis ca. 50 cm möglich.
Wenn man nun Antrieb und Entfernungsmessung nach meinen Vorgaben aufgebaut hat, müsste folgender Code schon funktionieren - der Bot fährt nun autonom durch die Gegend und weicht Hindernissen aus:
- - - Aktualisiert - - -Code:import time import RPi.GPIO as GPIO GPIO.setwarnings(False) def ControlAPairOfPins(FirstPin,FirstState,SecondPin,SecondState): if FirstState == "1": GPIO.output(int(FirstPin),True) else: GPIO.output(int(FirstPin),False) if SecondState == "1": GPIO.output(int(SecondPin),True) else: GPIO.output(int(SecondPin),False) return print "Ultraschallmessung mit SRF04" while True: #Messung Start GPIO.setmode(GPIO.BCM) GPIO.setup(14,GPIO.OUT) GPIO.setup(15,GPIO.IN) GPIO.output(14, False) time.sleep(0.5) GPIO.output(14, True) time.sleep(0.00001) start = time.time() GPIO.output(14, False) while GPIO.input(15)==0: pass start = time.time() while GPIO.input(15)==1: pass stop = time.time() elapsed = stop-start distance = elapsed * 17000 print "Abstand: %.1f cm" % distance #Messung Ende if distance < 20: #Motor stop GPIO.setmode(GPIO.BOARD) GPIO.setup(19,GPIO.OUT) GPIO.setup(21,GPIO.OUT) GPIO.setup(23,GPIO.OUT) GPIO.setup(24,GPIO.OUT) ControlAPairOfPins("19","0","21","0") ControlAPairOfPins("23","0","24","0") print "Stop" time.sleep(1) #Stop Ende #Drehung rechts GPIO.setmode(GPIO.BOARD) GPIO.setup(19,GPIO.OUT) GPIO.setup(21,GPIO.OUT) GPIO.setup(23,GPIO.OUT) GPIO.setup(24,GPIO.OUT) ControlAPairOfPins("19","1","21","0") ControlAPairOfPins("23","1","24","0") print "Drehung nach rechts" time.sleep(1) else: #Motor vorwaerts GPIO.setmode(GPIO.BOARD) GPIO.setup(19,GPIO.OUT) GPIO.setup(21,GPIO.OUT) GPIO.setup(23,GPIO.OUT) GPIO.setup(24,GPIO.OUT) ControlAPairOfPins("19","1","21","0") ControlAPairOfPins("23","0","24","1") print "Geradeaus vorwaerts" #Vorwaerts Ende
Kommen wir nun zum LCD-Display:
Nicht unbedingt notwendig, macht aber schon was her...
Benötigt wird:
- Mini Steckbrett, meins hat unten ein Doppelklebeband
- LCD, möglich sind 16x1 oder 16x2 oder 16x4 (braucht viel Platz) Zeichen
- Stiftleiste zum Auflöten
- Timmerpoti 10kOhm
- Male to Female Kabel
- Male to Male Kabel
Der Aufbau ist sehr gut hier beschrieben, hat mir auch geholfen:
http://learn.adafruit.com/drive-a-16...ry-pi/overview
Testcode von Adafruit:
Wenn "Pinsels's RPi Bot" auf dem Diplay steht, ist alles richtig aufgebaut.Code:#!/usr/bin/python # # based on code from lrvick and LiquidCrystal # lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py # LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp # from time import sleep class Adafruit_CharLCD: # commands LCD_CLEARDISPLAY = 0x01 LCD_RETURNHOME = 0x02 LCD_ENTRYMODESET = 0x04 LCD_DISPLAYCONTROL = 0x08 LCD_CURSORSHIFT = 0x10 LCD_FUNCTIONSET = 0x20 LCD_SETCGRAMADDR = 0x40 LCD_SETDDRAMADDR = 0x80 # flags for display entry mode LCD_ENTRYRIGHT = 0x00 LCD_ENTRYLEFT = 0x02 LCD_ENTRYSHIFTINCREMENT = 0x01 LCD_ENTRYSHIFTDECREMENT = 0x00 # flags for display on/off control LCD_DISPLAYON = 0x04 LCD_DISPLAYOFF = 0x00 LCD_CURSORON = 0x02 LCD_CURSOROFF = 0x00 LCD_BLINKON = 0x01 LCD_BLINKOFF = 0x00 # flags for display/cursor shift LCD_DISPLAYMOVE = 0x08 LCD_CURSORMOVE = 0x00 # flags for display/cursor shift LCD_DISPLAYMOVE = 0x08 LCD_CURSORMOVE = 0x00 LCD_MOVERIGHT = 0x04 LCD_MOVELEFT = 0x00 # flags for function set LCD_8BITMODE = 0x10 LCD_4BITMODE = 0x00 LCD_2LINE = 0x08 LCD_1LINE = 0x00 LCD_5x10DOTS = 0x04 LCD_5x8DOTS = 0x00 def __init__(self, pin_rs=25, pin_e=24, pins_db=[23, 17, 21, 22], GPIO = None): # Emulate the old behavior of using RPi.GPIO if we haven't been given # an explicit GPIO interface to use if not GPIO: import RPi.GPIO as GPIO self.GPIO = GPIO self.pin_rs = pin_rs self.pin_e = pin_e self.pins_db = pins_db self.GPIO.setmode(GPIO.BCM) self.GPIO.setup(self.pin_e, GPIO.OUT) self.GPIO.setup(self.pin_rs, GPIO.OUT) for pin in self.pins_db: self.GPIO.setup(pin, GPIO.OUT) self.write4bits(0x33) # initialization self.write4bits(0x32) # initialization self.write4bits(0x28) # 2 line 5x7 matrix self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor self.write4bits(0x06) # shift cursor right self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS self.displayfunction |= self.LCD_2LINE """ Initialize to default text direction (for romance languages) """ self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode self.clear() def begin(self, cols, lines): if (lines > 1): self.numlines = lines self.displayfunction |= self.LCD_2LINE self.currline = 0 def home(self): self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero self.delayMicroseconds(3000) # this command takes a long time! def clear(self): self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display self.delayMicroseconds(3000) # 3000 microsecond sleep, clearing the display takes a long time def setCursor(self, col, row): self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] if ( row > self.numlines ): row = self.numlines - 1 # we count rows starting w/0 self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) def noDisplay(self): """ Turn the display off (quickly) """ self.displaycontrol &= ~self.LCD_DISPLAYON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def display(self): """ Turn the display on (quickly) """ self.displaycontrol |= self.LCD_DISPLAYON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noCursor(self): """ Turns the underline cursor on/off """ self.displaycontrol &= ~self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def cursor(self): """ Cursor On """ self.displaycontrol |= self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noBlink(self): """ Turn on and off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noBlink(self): """ Turn on and off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def DisplayLeft(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) def scrollDisplayRight(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); def leftToRight(self): """ This is for text that flows Left to Right """ self.displaymode |= self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); def rightToLeft(self): """ This is for text that flows Right to Left """ self.displaymode &= ~self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def autoscroll(self): """ This will 'right justify' text from the cursor """ self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def noAutoscroll(self): """ This will 'left justify' text from the cursor """ self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def write4bits(self, bits, char_mode=False): """ Send command to LCD """ self.delayMicroseconds(1000) # 1000 microsecond sleep bits=bin(bits)[2:].zfill(8) self.GPIO.output(self.pin_rs, char_mode) for pin in self.pins_db: self.GPIO.output(pin, False) for i in range(4): if bits[i] == "1": self.GPIO.output(self.pins_db[::-1][i], True) self.pulseEnable() for pin in self.pins_db: self.GPIO.output(pin, False) for i in range(4,8): if bits[i] == "1": self.GPIO.output(self.pins_db[::-1][i-4], True) self.pulseEnable() def delayMicroseconds(self, microseconds): seconds = microseconds / float(1000000) # divide microseconds by 1 million for seconds sleep(seconds) def pulseEnable(self): self.GPIO.output(self.pin_e, False) self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns self.GPIO.output(self.pin_e, True) self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns self.GPIO.output(self.pin_e, False) self.delayMicroseconds(1) # commands need > 37us to settle def message(self, text): """ Send string to LCD. Newline wraps to second line""" for char in text: if char == '\n': self.write4bits(0xC0) # next line else: self.write4bits(ord(char),True) if __name__ == '__main__': lcd = Adafruit_CharLCD() lcd.clear() lcd.message("Pinsel's\n RPi Bot")
Als Goody noch ein Programm, das die US-Messwerte im Display ausgibt:
- - - Aktualisiert - - -Code:from time import sleep class Adafruit_CharLCD: # commands LCD_CLEARDISPLAY = 0x01 LCD_RETURNHOME = 0x02 LCD_ENTRYMODESET = 0x04 LCD_DISPLAYCONTROL = 0x08 LCD_CURSORSHIFT = 0x10 LCD_FUNCTIONSET = 0x20 LCD_SETCGRAMADDR = 0x40 LCD_SETDDRAMADDR = 0x80 # flags for display entry mode LCD_ENTRYRIGHT = 0x00 LCD_ENTRYLEFT = 0x02 LCD_ENTRYSHIFTINCREMENT = 0x01 LCD_ENTRYSHIFTDECREMENT = 0x00 # flags for display on/off control LCD_DISPLAYON = 0x04 LCD_DISPLAYOFF = 0x00 LCD_CURSORON = 0x02 LCD_CURSOROFF = 0x00 LCD_BLINKON = 0x01 LCD_BLINKOFF = 0x00 # flags for display/cursor shift LCD_DISPLAYMOVE = 0x08 LCD_CURSORMOVE = 0x00 # flags for display/cursor shift LCD_DISPLAYMOVE = 0x08 LCD_CURSORMOVE = 0x00 LCD_MOVERIGHT = 0x04 LCD_MOVELEFT = 0x00 # flags for function set LCD_8BITMODE = 0x10 LCD_4BITMODE = 0x00 LCD_2LINE = 0x08 LCD_1LINE = 0x00 LCD_5x10DOTS = 0x04 LCD_5x8DOTS = 0x00 def __init__(self, pin_rs=25, pin_e=24, pins_db=[23, 17, 21, 22], GPIO = None): # Emulate the old behavior of using RPi.GPIO if we haven't been given # an explicit GPIO interface to use if not GPIO: import RPi.GPIO as GPIO self.GPIO = GPIO self.pin_rs = pin_rs self.pin_e = pin_e self.pins_db = pins_db self.GPIO.setmode(GPIO.BCM) self.GPIO.setup(self.pin_e, GPIO.OUT) self.GPIO.setup(self.pin_rs, GPIO.OUT) for pin in self.pins_db: self.GPIO.setup(pin, GPIO.OUT) self.write4bits(0x33) # initialization self.write4bits(0x32) # initialization self.write4bits(0x28) # 2 line 5x7 matrix self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor self.write4bits(0x06) # shift cursor right self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS self.displayfunction |= self.LCD_2LINE """ Initialize to default text direction (for romance languages) """ self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode self.clear() def begin(self, cols, lines): if (lines > 1): self.numlines = lines self.displayfunction |= self.LCD_2LINE self.currline = 0 def home(self): self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero self.delayMicroseconds(3000) # this command takes a long time! def clear(self): self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display self.delayMicroseconds(3000) # 3000 microsecond sleep, clearing the display takes a long time def setCursor(self, col, row): self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] if ( row > self.numlines ): row = self.numlines - 1 # we count rows starting w/0 self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) def noDisplay(self): """ Turn the display off (quickly) """ self.displaycontrol &= ~self.LCD_DISPLAYON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def display(self): """ Turn the display on (quickly) """ self.displaycontrol |= self.LCD_DISPLAYON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noCursor(self): """ Turns the underline cursor on/off """ self.displaycontrol &= ~self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def cursor(self): """ Cursor On """ self.displaycontrol |= self.LCD_CURSORON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noBlink(self): """ Turn on and off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def noBlink(self): """ Turn on and off the blinking cursor """ self.displaycontrol &= ~self.LCD_BLINKON self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) def DisplayLeft(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) def scrollDisplayRight(self): """ These commands scroll the display without changing the RAM """ self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); def leftToRight(self): """ This is for text that flows Left to Right """ self.displaymode |= self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); def rightToLeft(self): """ This is for text that flows Right to Left """ self.displaymode &= ~self.LCD_ENTRYLEFT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def autoscroll(self): """ This will 'right justify' text from the cursor """ self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def noAutoscroll(self): """ This will 'left justify' text from the cursor """ self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) def write4bits(self, bits, char_mode=False): """ Send command to LCD """ self.delayMicroseconds(1000) # 1000 microsecond sleep bits=bin(bits)[2:].zfill(8) self.GPIO.output(self.pin_rs, char_mode) for pin in self.pins_db: self.GPIO.output(pin, False) for i in range(4): if bits[i] == "1": self.GPIO.output(self.pins_db[::-1][i], True) self.pulseEnable() for pin in self.pins_db: self.GPIO.output(pin, False) for i in range(4,8): if bits[i] == "1": self.GPIO.output(self.pins_db[::-1][i-4], True) self.pulseEnable() def delayMicroseconds(self, microseconds): seconds = microseconds / float(1000000) # divide microseconds by 1 million for seconds sleep(seconds) def pulseEnable(self): self.GPIO.output(self.pin_e, False) self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns self.GPIO.output(self.pin_e, True) self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns self.GPIO.output(self.pin_e, False) self.delayMicroseconds(1) # commands need > 37us to settle def message(self, text): """ Send string to LCD. Newline wraps to second line""" for char in text: if char == '\n': self.write4bits(0xC0) # next line else: self.write4bits(ord(char),True) if __name__ == '__main__': lcd = Adafruit_CharLCD() GPIO_TRIGGER = 14 GPIO_ECHO = 15 adjustment = 7 print "Ultraschallmessung mit SRF04" while True: GPIO.setup(GPIO_TRIGGER,GPIO.OUT) GPIO.setup(GPIO_ECHO,GPIO.IN) GPIO.output(GPIO_TRIGGER, False) time.sleep(0.5) GPIO.output(GPIO_TRIGGER, True) time.sleep(0.00001) start = time.time() GPIO.output(GPIO_TRIGGER, False) while GPIO.input(GPIO_ECHO)==0: pass start = time.time() while GPIO.input(GPIO_ECHO)==1: pass stop = time.time() elapsed = stop-start distance = elapsed * 17000 + 8 distance = distance - adjustment print "Abstand: %.1f cm" % distance time.sleep(1) GPIO.cleanup() lcd.clear() # lcd.message(" Adafruit 16x2\n Standard LCD") lcd.message("Pinsel's\n RPi Bot")
Dann noch das vorerst letzte und schwierigste Modul: Der Mini Servo
Hier ist ein klein wendig Bastelarbeit notwendig um das US-Modul auf dem Servoarm zu befestigen. Aus Sperrholz oder Kunststoff habe ich mir ein passendes "U" ausgeschnitten und mit dem Servoarm verschraubt - siehe Fotos. Neben diesem Teil benötigt man noch ein
- Mini Servo
- BC548 NPN Transistor
- 2 Stk. Kohlewiderstand 1K
Die Widerstände verwendet man als Spannungsteiler, weil der Servo nur mit 5 Volt betrieben werden kann. Die Verkabelung ist in der Anlage ersichtlich - hier möchte ich mich für die Handskizzen entschuldigen, ich denke dass sie ihren Zweck trotzdem erfüllen.
Hier ein Programm, um den Servo zu testen:
Der Ablauf dieses Programms ist hier ersichtlich: http://www.youtube.com/watch?v=VA_2pQ9W4g4Code:import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BOARD) GPIO.setwarnings(False) GPIO.setup(26, GPIO.OUT) GPIO.output(26, True) while True: for i in range(1, 100): GPIO.output(26, False) time.sleep(0.001) GPIO.output(26, True) time.sleep(0.02) for i in range(1, 100): GPIO.output(26, False) time.sleep(0.0015) GPIO.output(26, True) time.sleep(0.02) for i in range(1, 100): GPIO.output(26, False) time.sleep(0.002) GPIO.output(26, True) time.sleep(0.02)
Wenn der Servo etwas zuckt ist dies normal, ich habe keinen Weg gefunden dieses zu beseitigen. Hier wäre schon ein Ansatz mein Projekt zu verbessern.
Sind alle Komponenten und Sensoren aufgebaut, steht einem Probelauf nichts mehr im Weg.
Program dazu kann ich nicht hochladen, *.py ist eine nicht erlaubte Datei - sollte jemand den Code wollen, einfach PN mit der Emailadresse an mich senden.
Das war's vorerst, sollte jemand Anregungen, Kritik oder Verbesserungsvorschläge haben - einfach posten. Ich wünsche viel Erfolg beim Nachbau![]()






Zitieren

Lesezeichen