Saturday, June 11, 2016

Remote controlled car with Raspberry Pi (piborg) and HC-SR04 ultrasonic sensor (to detect walls and stop car)

I this post I will show how to build a remote controlled car with your Raspberry Pi that will stop whenever it encounters a wall at a predefined distance. The result will look like this:

The car looks like this in detail:

Components


Smart buggy 16 euro.

Two additional wheels, that I glued to the plastic board.
PIBORG - PICOBORG V2 - MOTOR CONTROLLER, 13 euro.

Triborg, 9 euro.

The ultra sonic distance sensor, HCSR04, 2,50 euro.

Wiring was done as described on the internet. The car is remote controlled via telnet using Putty.

Code

The code below is executed. This was tricky because the key listener needs to be non blocking. Once I found one that is non blocking. Its just a matter of using keys, I, J, K, L for steering the car. The distance sensor checks for distances less than 30 CM. The motor is turned off when this happens.
import sys
import select
import tty
import termios
import contextlib
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)


#used by the distance meter
TRIG = 23
ECHO = 24

GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)

#used by the piborg
# Set which GPIO pins the drive outputs are connected to
DRIVE_1 = 4
DRIVE_2 = 18
DRIVE_3 = 8
DRIVE_4 = 7

# Set all of the drive pins as output pins
GPIO.setup(DRIVE_1, GPIO.OUT)
GPIO.setup(DRIVE_2, GPIO.OUT)
GPIO.setup(DRIVE_3, GPIO.OUT)
GPIO.setup(DRIVE_4, GPIO.OUT)

# Map current on/off state to command state
dInvert = {}
dInvert[True] = GPIO.LOW
dInvert[False] = GPIO.HIGH

# Map the on/off state to nicer names for display
dName = {}
dName[True] = 'ON '
dName[False] = 'OFF'

# Function to set all drives off
def MotorOff():
    GPIO.output(DRIVE_1, GPIO.LOW)
    GPIO.output(DRIVE_2, GPIO.LOW)
    GPIO.output(DRIVE_3, GPIO.LOW)
    GPIO.output(DRIVE_4, GPIO.LOW)

def MotorOn():
    GPIO.output(DRIVE_1, GPIO.HIGH)
    GPIO.output(DRIVE_2, GPIO.HIGH)
    GPIO.output(DRIVE_3, GPIO.HIGH)
    GPIO.output(DRIVE_4, GPIO.HIGH)


def afstand():
        time.sleep(0.2)
        GPIO.output(TRIG, False)
        GPIO.output(TRIG, True)
        time.sleep(0.00001)
        GPIO.output(TRIG, False)
        while GPIO.input(ECHO)==0:
            pulse_start = time.time()

        while GPIO.input(ECHO)==1:
            pulse_end = time.time()

        pulse_duration = pulse_end - pulse_start
        distance = pulse_duration * 17150
        distance = round(distance, 2)

        return distance
  #distance

def isData():
    return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], [])


old_settings = termios.tcgetattr(sys.stdin)
try:
    tty.setcbreak(sys.stdin.fileno())


    while 1:
        if (afstand() < 50):
            MotorOff()


        if isData():
            c = sys.stdin.read(1)
            print str((c))
            if c == '\x1b':  # x1b is ESC
                break
            elif c == 'i': #Vooruit
                MotorOn()
            elif c == 'k': #Stop
                MotorOff()
            elif c == 'j': #Links
                print 'links'
                if ((GPIO.input(DRIVE_1)) & (GPIO.input(DRIVE_4))):
                    print 'aan het rijden'
                    GPIO.output(DRIVE_1, GPIO.LOW)
                    GPIO.output(DRIVE_2, GPIO.LOW)

                    time.sleep(0.1)
                    GPIO.output(DRIVE_1, GPIO.HIGH)
                    GPIO.output(DRIVE_2, GPIO.HIGH)
                else:
                    GPIO.output(DRIVE_3, dInvert[GPIO.input(DRIVE_3)])
                    GPIO.output(DRIVE_4, dInvert[GPIO.input(DRIVE_4)])
            elif c == 'l': #Rechts
                print 'rechts'
                if ((GPIO.input(DRIVE_1)) & (GPIO.input(DRIVE_4))):
                    print 'aan het rijden'
                    GPIO.output(DRIVE_4, GPIO.LOW)
                    GPIO.output(DRIVE_3, GPIO.LOW)

                    time.sleep(0.1)
                    GPIO.output(DRIVE_4, GPIO.HIGH)
                    GPIO.output(DRIVE_3, GPIO.HIGH)
                else:
                    GPIO.output(DRIVE_1, dInvert[GPIO.input(DRIVE_1)])
                    GPIO.output(DRIVE_2, dInvert[GPIO.input(DRIVE_2)])
finally:
    print("stop")
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)

No comments: