如何使用树莓派制作避障机器人

学习Arduino或者树莓派的过程中,如果仅仅看代码或者做简单实验,那么常常会虎头蛇尾,所以我们建议还是尝试一些简单的机器人项目,这样既有趣也能不断学习提高。本文将向大家展示如何使用树莓派制作简单的避障机器人。

如何使用树莓派制作避障机器人_第1张图片

树莓派避障机器人各功能组件

众所周知,树莓派可以通过GPIO 接口、USB接口、以太网接口、HDMI接口、LCD和摄像头接口与诸多的外设进行通信。这个项目中我们使用的是Raspberry Pi 3B,3B有一个64位的ARMv7四核处理器,内存为1GB,还内置了Wi-Fi和蓝牙。详情可阅读: 树莓派3的外围I/O数据接口

如何使用树莓派制作避障机器人_第2张图片

项目中采用HC-SR04超声波测距模块作为避障探头,HC-SR04超声波测距模块具有2cm-400cm非接触式测量范围,测距精度可达3mm。模块包含了超声波发射器、接收器和控制电路。HC-SR04的介绍以前做过一些,可查阅: HC-SR04超声波测距模块的测试和 树莓派3 超声波测距代码这两篇文章。

如何使用树莓派制作避障机器人_第3张图片

同时,项目中还用到了GP2Y0A21红外传感器,它通过发射和检测红外辐射来感知周围环境的某些特征。红外传感器能够测量物体发出的热量并探测运动。它的距离测量范围是10cm~80cm。关于红外线传感器模块,可查阅: 夏普GP2Y0A21红外测距传感器接口定义

如何使用树莓派制作避障机器人_第4张图片

避障机器人的动力驱动,我们采用了L298N电机驱动模块,L298N驱动模块可以控制直流电机正转和反转,一块L298N驱动模块可以同时控制两个直流电机。L298N电机驱动模块接收来自树莓派的控制信号,并将信号传送给电动机,以此来控制电机的运动。关于L298N的接口定义,可阅读: 电机驱动板L298N的接口定义

如何使用树莓派制作避障机器人_第5张图片

其次,项目中还会用到电压调节器IC LM7805 ,它的作用是保持输出电压在一个恒定值。78xx系列IC中的xx表示它可以提供的稳定输出电压。如7805 IC可提供+5伏的稳定电压。下图是LM7805稳压IC的针脚定义图

如何使用树莓派制作避障机器人_第6张图片

项目中,避障机器人采用两个200 rpm的12v直流减速电机作为动力源。

避障机器人的电路图

如何使用树莓派制作避障机器人_第7张图片

在电路图中,实线表示电源线Vcc,长虚线表示接地线GND,短虚线表示控制信号线。

避障机器人的Python代码

手动控制代码

import curses

import RPi.GPIO as GPIO

class MotorControler(object):

def __init__(self, parent=None):

self._data = {'name': 'MOTOR', 'delay': 0.01, 'LD': 3, 'LU': 5, 'RD': 7, 'RU': 8}

self.init_pin()

def init_pin(self):

self.GPIO_LD_PIN = self._data.get('LD', -1)

self.GPIO_LU_PIN = self._data.get('LU', -1)

self.GPIO_RD_PIN = self._data.get('RD', -1)

self.GPIO_RU_PIN = self._data.get('RU', -1)

if self.GPIO_LD_PIN == -1 or self.GPIO_LU_PIN == -1 or self.GPIO_RD_PIN == -1 or self.GPIO_RU_PIN == -1:

print('message', 'FATAL ERROR : INVALID PIN ENCOUNTER # ' + str(self.GPIO_LD_PIN) + ', ' + + str(

self.GPIO_LU_PIN) + ', ' + + str(self.GPIO_RD_PIN) + ', ' + + str(self.GPIO_RU_PIN))

# pin setup

# set GPIO numbering mode and define output pins

GPIO.setup(self.GPIO_LD_PIN, GPIO.OUT)

GPIO.setup(self.GPIO_LU_PIN, GPIO.OUT)

GPIO.setup(self.GPIO_RD_PIN, GPIO.OUT)

GPIO.setup(self.GPIO_RU_PIN, GPIO.OUT)

time.sleep(0.5) # warmup time

self.stop()

def stop(self):

GPIO.output(self.GPIO_LD_PIN, False)

GPIO.output(self.GPIO_LU_PIN, False)

GPIO.output(self.GPIO_RD_PIN, False)

GPIO.output(self.GPIO_RU_PIN, False)

def step_forward(self):

GPIO.output(self.GPIO_LD_PIN, False)

GPIO.output(self.GPIO_LU_PIN, True)

GPIO.output(self.GPIO_RD_PIN, False)

GPIO.output(self.GPIO_RU_PIN, True)

print('Move Forward')

def step_backward(self):

GPIO.output(self.GPIO_LD_PIN, True)

GPIO.output(self.GPIO_LU_PIN, False)

GPIO.output(self.GPIO_RD_PIN, True)

GPIO.output(self.GPIO_RU_PIN, False)

print('Move Backward')

def step_right(self):

GPIO.output(self.GPIO_LD_PIN, True)

GPIO.output(self.GPIO_LU_PIN, False)

GPIO.output(self.GPIO_RD_PIN, False)

GPIO.output(self.GPIO_RU_PIN, True)

print('Move Right')

def step_left(self):

GPIO.output(self.GPIO_LD_PIN, False)

GPIO.output(self.GPIO_LU_PIN, True)

GPIO.output(self.GPIO_RD_PIN, True)

GPIO.output(self.GPIO_RU_PIN, False)

print('Move Left')

def move_forward(self, count=15):

for i in range(count):

self.step_forward()

self.stop()

def move_backward(self, count=15):

for i in range(count):

self.step_backward()

self.stop()

def move_right(self, count=15):

for i in range(count):

self.step_right()

self.stop()

def move_left(self, count=15):

for i in range(count):

self.step_left()

self.stop()

#set GPIO numbering mode and define output pins

GPIO.setmode(GPIO.BOARD)

# Get the curses window, turn off echoing of keyboard to screen, turn on

# instant (no waiting) key response, and use special values for cursor keys

screen = curses.initscr()

curses.noecho()

curses.cbreak()

screen.keypad(True)

motor = MotorControler()

try:

while True:

char = screen.getch()

if char == ord('q'):

break

elif char == curses.KEY_UP:

motor.move_forward(count=15)

elif char == curses.KEY_DOWN:

motor.move_backward(count=15)

elif char == curses.KEY_RIGHT:

motor.move_right(count=15)

elif char == curses.KEY_LEFT:

motor.move_left(count=15)

elif char == 10:

motor.stop()

finally:

#Close down curses properly, inc turn echo back on!

curses.nocbreak(); screen.keypad(0); curses.echo()

curses.endwin()

GPIO.cleanup()

自动控制代码
import RPi.GPIO as GPIO import time import numpy as np

GPIO.setmode(GPIO.BOARD) GPIO.setwarnings(False)

class MotorControler(object):

def __init__(self, parent=None):

self._data = {'name': 'MOTOR', 'delay': 0.01, 'LD': 14 'LU': 15, 'RD': 18, 'RU': 23}

self.init_pin()

def init_pin(self):

self.GPIO_LD_PIN = self._data.get('LD', -1) self.GPIO_LU_PIN = self._data.get('LU', -1)

self.GPIO_RD_PIN = self._data.get('RD', -1) self.GPIO_RU_PIN = self._data.get('RU', -1)

if self.GPIO_LD_PIN == -1 or self.GPIO_LU_PIN == -1 or self.GPIO_RD_PIN == -1 or self.GPIO_RU_PIN == -1:

print('message', 'FATAL ERROR : INVALID PIN ENCOUNTER # ' + str(self.GPIO_LD_PIN) + ', ' + + str(

self.GPIO_LU_PIN) + ', ' + + str(self.GPIO_RD_PIN) + ', ' + + str(self.GPIO_RU_PIN))

# pin setup

# set GPIO numbering mode and define output pins

GPIO.setup(self.GPIO_LD_PIN, GPIO.OUT) GPIO.setup(self.GPIO_LU_PIN, GPIO.OUT) GPIO.setup(self.GPIO_RD_PIN, GPIO.OUT) GPIO.setup(self.GPIO_RU_PIN, GPIO.OUT) time.sleep(0.5) # warmup time self.stop()

def stop(self):

GPIO.output(self.GPIO_LD_PIN, False) GPIO.output(self.GPIO_LU_PIN, False)

GPIO.output(self.GPIO_RD_PIN, False) GPIO.output(self.GPIO_RU_PIN, False)

def step_forward(self):

GPIO.output(self.GPIO_LD_PIN, False) GPIO.output(self.GPIO_LU_PIN, True)

GPIO.output(self.GPIO_RD_PIN, False) GPIO.output(self.GPIO_RU_PIN, True) print('Move Forward')

def step_backward(self):

GPIO.output(self.GPIO_LD_PIN, True) GPIO.output(self.GPIO_LU_PIN, False)

GPIO.output(self.GPIO_RD_PIN, True) GPIO.output(self.GPIO_RU_PIN, False) print('Move Backward')

def step_right(self):

GPIO.output(self.GPIO_LD_PIN, True) GPIO.output(self.GPIO_LU_PIN, False)

GPIO.output(self.GPIO_RD_PIN, False) GPIO.output(self.GPIO_RU_PIN, True) print('Move Right')

def step_left(self):

GPIO.output(self.GPIO_LD_PIN, False) GPIO.output(self.GPIO_LU_PIN, True)

GPIO.output(self.GPIO_RD_PIN, True) GPIO.output(self.GPIO_RU_PIN, False) print('Move Left')

def move_forward(self, count=15):

for i in range(count):

self.step_forward() self.stop()

def move_backward(self, count=15):

for i in range(count):

self.step_backward() self.stop()

def move_right(self, count=15):

for i in range(count):

self.step_right() self.stop()

def move_left(self, count=15): for i in range(count):

self.step_left() self.stop()

def readings():

IR_SENSOR_A = 2 IR_SENSOR_B = 3 IR_SENSOR_C = 6 IR_SENSOR_D = 4

GPIO.setup(IR_SENSOR_A, GPIO.IN) GPIO.setup(IR_SENSOR_B, GPIO.IN) GPIO.setup(IR_SENSOR_C, GPIO.IN) GPIO.setup(IR_SENSOR_D, GPIO.IN)

time.sleep(0.5) # warmup time

ir_measure_a = GPIO.input(IR_SENSOR_A) ir_measure_b = GPIO.input(IR_SENSOR_B) ir_measure_c = GPIO.input(IR_SENSOR_C) ir_measure_d = GPIO.input(IR_SENSOR_D)

print(ir_measure_a, ir_measure_b, ir_measure_c, ir_measure_d)

return [ir_measure_a, ir_measure_b, ir_measure_c, ir_measure_d]

# FOR DEMO def run():

motor = MotorControler()

while True:

sensor = readings()

if sensor[1] == 0 and sensor[2] == 0:

motor.move_forward(count=15) elif sensor[1] == 1 and sensor[2] == 1:

if np.random.ranf() > 0.5 :

motor.move_left(count=15) else:

motor.move_left(count=15) # provide more condotion for better maneuvering

run()

现在大家可以尽情去尝试避障机器人的控制和修改了。由于网页编码问题,如果代码运行出行报错,尝试按Python规范修改代码缩进。

你可能感兴趣的:(树莓派,机器人)