0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

手把手教你如何自制輪式機(jī)器人

GReq_mcu168 ? 來源:博客 ? 作者:繆宇飏,myyerrol ? 2021-06-07 15:36 ? 次閱讀

擊上方“果果小師弟”,選擇“置頂/星標(biāo)公眾號”

摘要:制作這個(gè)項(xiàng)目的起因是大一下學(xué)期那會(huì)兒我通過學(xué)校圖書館里的《無線電》雜志開始接觸Raspberry Pi卡片式計(jì)算機(jī)和Arduino微控制器,其中Raspberry Pi給當(dāng)初什么都不懂的我留下了非常深刻的印象:一個(gè)信用卡大小的板子竟然可以跑帶有圖形界面的GNU/Linux操作系統(tǒng)。

在強(qiáng)烈探索欲的驅(qū)使下,我從網(wǎng)上購買了兩塊Element14的Raspberry Pi一代Model B(現(xiàn)在早已經(jīng)絕版了)板子以及其他相關(guān)配件,開始在Raspbian系統(tǒng)上自學(xué)Python和各種傳感器的使用方法,后來為了檢驗(yàn)一下自己的學(xué)習(xí)成果,于是我便花費(fèi)幾周的時(shí)間做了這個(gè)簡單的輪式機(jī)器人。雖然它涉及的原理并不復(fù)雜,但是對于那會(huì)兒剛開始接觸嵌入式的我來說,能成功搭建一個(gè)完整的機(jī)器人系統(tǒng)還是挺有挑戰(zhàn)性的。

概述簡單輪式機(jī)器人其實(shí)是一個(gè)比較傳統(tǒng)的入門級智能小車,它擁有藍(lán)牙遠(yuǎn)程遙控、超聲波避障、紅外邊緣檢測和紅外巡線(未完成)等功能,可以完成一些有趣的小實(shí)驗(yàn)。此外,簡單輪式機(jī)器人的軟件是開源的,具體代碼可以從我的GitHub倉庫上獲得。

原理硬件以下是該簡單輪式機(jī)器人的硬件系統(tǒng)連接圖:

085fd136-c655-11eb-9e57-12bb97331649.png

核心主控

系統(tǒng)的硬件核心主控分別為Arduino和Raspberry Pi。其中Arduino主要負(fù)責(zé)接收紅外光電測距模塊的數(shù)據(jù),并控制裝有超聲波模塊的單軸舵機(jī)云臺(tái)的旋轉(zhuǎn);而Raspberry Pi則可通過電機(jī)驅(qū)動(dòng)模塊來完成對四個(gè)直流減速電機(jī)轉(zhuǎn)向和轉(zhuǎn)速的控制,此外它還能接收超聲波模塊和從Arduino串口發(fā)送上來的紅外光電測距模塊的數(shù)據(jù)來判斷當(dāng)前機(jī)器人的前方和兩側(cè)是否遇到障礙物,若機(jī)器人與障礙物之間的距離小于一個(gè)特定的閾值,則Arduino和Raspberry Pi會(huì)分別改變LED的顏色并啟動(dòng)蜂鳴器來發(fā)出警報(bào)。

當(dāng)然,肯定會(huì)有人問:為什么我不能僅用Raspberry Pi來作為機(jī)器人的核心主控,非要再用一個(gè)Arduino呢?其實(shí)根據(jù)本項(xiàng)目的實(shí)際需求,確實(shí)只用一個(gè)Raspberry Pi就夠了,不過對于我來說使用Arduino主要出于以下三個(gè)原因的考慮:

Raspberry Pi一代Model B板子的GPIO引腳數(shù)量只有26個(gè),就算復(fù)用一些帶有特殊功能的引腳,引腳資源依舊比較緊張。

Raspberry Pi官方提供的GPIO庫雖然含有PWM函數(shù),但是實(shí)際在控制舵機(jī)的時(shí)候可能是由于軟件模擬的PWM方波還不夠穩(wěn)定,導(dǎo)致舵機(jī)抖動(dòng)得比較厲害。

可以學(xué)習(xí)Python的串口編程。

因此,綜合以上三個(gè)方面我選擇了Arduino和Raspberry Pi雙核心主控的系統(tǒng)架構(gòu)。

外部電源

因?yàn)闀r(shí)間比較緊張,所以我沒有在電源管理上花費(fèi)太多的功夫。對于Arduino,我使用的是能裝下6個(gè)1.5V干電池的的電池盒給其供電,而對于Raspberry Pi耗電量較大的需求,我是從大學(xué)舍友那借了一個(gè)充電寶來解決問題的,不過雖然供電可以了,但是由于充電寶的重量比較大,導(dǎo)致四個(gè)輪子受壓偏大,使得遙控的精準(zhǔn)度受到了一定的影響。

電機(jī)驅(qū)動(dòng)

機(jī)器人的電機(jī)驅(qū)動(dòng)部分采用傳統(tǒng)的L293D芯片,它是一款單片集成的高電壓、高電流、四通道電機(jī)驅(qū)動(dòng)芯片,其內(nèi)部包含有兩個(gè)雙極型H橋電路,可通過設(shè)置IN1和IN2輸入引腳的邏輯電平來控制電機(jī)的旋轉(zhuǎn)方向,而EN使能引腳可連接到一路PWM上,通過調(diào)整PWM方波的占空比便可調(diào)整電機(jī)的轉(zhuǎn)速。

數(shù)據(jù)感知

為了能實(shí)現(xiàn)最基本的避障功能,我們需要為機(jī)器人配備有一些傳感器。這里我使用的傳感器為HC-SR04超聲波測距模塊和紅外光電避障模塊,其中紅外光電避障模塊具有一對紅外線發(fā)射與接收管,運(yùn)行時(shí)發(fā)射管會(huì)發(fā)射出一定頻率的紅外線,當(dāng)檢測方向遇到障礙物后,紅外線會(huì)反射回來被接收管接收,經(jīng)過比較電路處理之后,信號輸出接口會(huì)輸出一個(gè)低電平信號,這樣只要在程序中對該接口的電平進(jìn)行判斷便能得知機(jī)器人是否距離障礙物比較近。

與紅外光電避障模塊的工作原理類似,超聲波模塊能夠向空中發(fā)射超聲波信號,當(dāng)其檢測到反射回來的信號后,只需將超聲波從發(fā)射到接收所用的時(shí)間乘上聲速再除以二便能得到機(jī)器人和障礙物之間的距離,從而為之后的機(jī)器人避障做好準(zhǔn)備。

軟件Raspberry Pi庫代碼

simple_wheeled_robot_lib.py

該庫代碼實(shí)現(xiàn)了GPIO引腳初始化函數(shù)、LED燈設(shè)置函數(shù)、蜂鳴器設(shè)置函數(shù)、電機(jī)控制函數(shù)、超聲波測距函數(shù)和LCD1602顯示函數(shù),其中LCD1602顯示函數(shù)調(diào)用了Python的SMBUS庫來完成IIC數(shù)據(jù)通信,從而能將字符串顯示在屏幕上(注意:SMBUS和IIC協(xié)議之間是存在區(qū)別的,但在Raspberry Pi上兩者概念基本等同)。

import time

import smbus

import RPi.GPIO as gpio

motor_run_left = 17

motor_run_right = 10

motor_direction_left = 4

motor_direction_right = 25

led_left = 7

led_right = 8

ultrasonic_trig = 23

ultrasonic_echo = 24

servo = 11

buzzer = 18

lcd_address = 0x27

data_bus = smbus.SMBus(1)

class SimpleWheeledRobot:

def __init__(self):

gpio.setmode(gpio.BCM)

gpio.setup(motor_run_left, gpio.OUT)

gpio.setup(motor_run_right, gpio.OUT)

gpio.setup(motor_direction_left, gpio.OUT)

gpio.setup(motor_direction_right, gpio.OUT)

gpio.setup(led_left, gpio.OUT)

gpio.setup(led_right, gpio.OUT)

def set_motors(self, run_left, direction_left, run_right, direction_right):

gpio.output(motor_run_left, run_left)

gpio.output(motor_run_right, run_right)

gpio.output(motor_direction_left, direction_left)

gpio.output(motor_direction_right, direction_right)

def set_led_left(self, state):

gpio.output(led_left, state)

def set_led_right(self, state):

gpio.output(led_right, state)

def go_forward(self, seconds):

if seconds == 0:

self.set_motors(1, 1, 1, 1)

self.set_led_left(1)

self.set_led_right(1)

else:

self.set_motors(1, 1, 1, 1)

time.sleep(seconds)

gpio.cleanup()

def go_reverse(self, seconds):

if seconds == 0:

self.set_motors(1, 0, 1, 0)

self.set_led_left(0)

self.set_led_right(0)

else:

self.set_motors(1, 0, 1, 0)

time.sleep(seconds)

gpio.cleanup()

def go_left(self, seconds):

if seconds == 0:

self.set_motors(0, 0, 1, 1)

self.set_led_left(1)

self.set_led_right(0)

else:

self.set_motors(0, 0, 1, 1)

time.sleep(seconds)

gpio.cleanup()

def go_right(self, seconds):

if seconds == 0:

self.set_motors(1, 1, 0, 0)

self.set_led_left(0)

self.set_led_right(1)

else:

self.set_motors(1, 1, 0, 0)

time.sleep(seconds)

gpio.cleanup()

def go_pivot_left(self, seconds):

if seconds == 0:

self.set_motors(1, 0, 1, 1)

self.set_led_left(1)

self.set_led_right(0)

else:

self.set_motors(1, 0, 1, 1)

time.sleep(seconds)

gpio.cleanup()

def go_pivot_right(self, seconds):

if seconds == 0:

self.set_motors(1, 1, 1, 0)

self.set_led_left(0)

self.set_led_right(1)

else:

self.set_motors(1, 1, 1, 0)

time.sleep(seconds)

gpio.cleanup()

def stop(self):

self.set_motors(0, 0, 0, 0)

self.set_led_left(0)

self.set_led_right(0)

def buzzing(self):

gpio.setup(buzzer, gpio.OUT)

gpio.output(buzzer, True)

for x in range(5):

gpio.output(buzzer, False)

time.sleep(0.1)

gpio.output(buzzer, True)

time.sleep(0.1)

def get_distance(self):

gpio.setmode(gpio.BCM)

gpio.setup(ultrasonic_trig, gpio.OUT)

gpio.setup(ultrasonic_echo, gpio.IN)

gpio.output(ultrasonic_trig, False)

while gpio.input(ultrasonic_echo) == 0:

start_time = time.time()

while gpio.input(ultrasonic_echo) == 1:

stop_time = time.time()

duration = stop_time - start_time

distance = (duration * 34300) / 2

gpio.cleanup()

return distance

def send_command(self, command):

buf = command & 0xF0

buf |= 0x04

data_bus.write_byte(lcd_address, buf)

time.sleep(0.002)

buf &= 0xFB

data_bus.write_byte(lcd_address, buf)

buf = (command & 0x0F) 《《 4

buf |= 0x04

data_bus.write_byte(lcd_address, buf)

time.sleep(0.002)

buf &= 0xFB

data_bus.write_byte(lcd_address, buf)

def send_data(self, data):

buf = data & 0xF0

buf |= 0x05

data_bus.write_byte(lcd_address, buf)

time.sleep(0.002)

buf &= 0xFB

data_bus.write_byte(lcd_address, buf)

buf = (data & 0x0F) 《《 4

buf |= 0x05

data_bus.write_byte(lcd_address, buf)

time.sleep(0.002)

buf &= 0xFB

data_bus.write_byte(lcd_address, buf)

def initialize_lcd(self):

try:

self.send_command(0x33)

time.sleep(0.005)

self.send_command(0x32)

time.sleep(0.005)

self.send_command(0x28)

time.sleep(0.005)

self.send_command(0x0C)

time.sleep(0.005)

self.send_command(0x01)

except:

return False

else:

return True

def clear_lcd(self):

self.send_command(0x01)

def print_lcd(self, x, y, lcd_string):

if x 《 0:

x = 0

if x 》 15:

x = 15

if y 《 0:

y = 0

if y 》 1:

y = 1

address = 0x80 + 0x40 * y + x

self.send_command(address)

for lcd_char in lcd_string:

self.send_data(ord(lcd_char))

def move_servo_left(self):

servo_range = 13

gpio.setmode(gpio.BCM)

gpio.setup(servo, gpio.OUT)

pwm = gpio.PWM(servo, 100)

pwm.start(0)

while servo_range 《= 23:

pwm.ChangeDutyCycle(servo_range)

servo_range += 1

time.sleep(0.5)

pwm.stop()

def move_servo_right(self):

servo_range = 13

gpio.setmode(gpio.BCM)

gpio.setup(servo, gpio.OUT)

pwm = gpio.PWM(servo, 100)

pwm.start(0)

while servo_range 》= 0:

pwm.ChangeDutyCycle(servo_range)

servo_range -= 1

time.sleep(0.5)

pwm.stop()

Raspberry Pi測試代碼1

simple_wheeled_robot_run_1.py

該代碼調(diào)用了上面自己編寫的機(jī)器人代碼庫,主要實(shí)現(xiàn)了超聲波距離檢測函數(shù)和鍵盤遙控函數(shù),其中鍵盤遙控函數(shù)里面又根據(jù)所按按鍵的不同調(diào)用并組合上面代碼庫中的不同函數(shù)來完成某些特定的功能(比如機(jī)器人遇到障礙物后首先會(huì)發(fā)出警報(bào),然后再進(jìn)行相應(yīng)的規(guī)避運(yùn)動(dòng)等)。

import time

import serial

import random

import Tkinter as tk

import RPi.gpio as gpio

from simple_wheeled_robot_lib import SimpleWheeledRobot

simple_wheeled_robot = SimpleWheeledRobot()

simple_wheeled_robot.initialize_lcd()

port = “/dev/ttyUSB0”

serial_to_arduino = serial.Serial(port, 9600)

serial_from_arduino = serial.Serial(port, 9600)

serial_from_arduino.flushInput()

serial_to_arduino.write(‘n’)

def detecte_distance():

distance = simple_wheeled_robot.get_distance()

if distance 》= 20:

# Light up the green led.

serial_to_arduino.write(‘g’)

elif distance 》= 10:

# Light up the yellow led.

serial_to_arduino.write(‘y’)

elif distance 《 10:

# Light up the red led.

serial_to_arduino.write(‘r’)

simple_wheeled_robot.buzzing()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_reverse(2)

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_pivot_right(2)

# Check the distance between wall and car‘s both sides.

serial_to_arduino.write(’k‘)

data_from_arduino = serial_from_arduino.readline()

data_from_arduino_int = int(data_from_arduino)

# Car is too close to the left wall.

if data_from_arduino_int == 01:

simple_wheeled_robot.buzzing()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_right(2)

# Car is too close to the right wall.

elif data_from_arduino_int == 10:

simple_wheeled_robot.buzzing()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_left(2)

def input_key(event):

simple_wheeled_robot.__init__()

print ’Key‘, event.char

key_press = event.char

seconds = 0.05

if key_press.lower() == ’w‘:

simple_wheeled_robot.go_forward(seconds)

elif key_press.lower() == ’s‘:

simple_wheeled_robot.go_reverse(seconds)

elif key_press.lower() == ’a‘:

simple_wheeled_robot.go_left(seconds)

elif key_press.lower() == ’d‘:

simple_wheeled_robot.go_right(seconds)

elif key_press.lower() == ’q‘:

simple_wheeled_robot.go_pivot_left(seconds)

elif key_press.lower() == ’e‘:

simple_wheeled_robot.go_pivot_right(seconds)

elif key_press.lower() == ’o‘:

gpio.cleanup()

# Move the servo in forward directory.

serial_to_arduino.write(’o‘)

time.sleep(0.05)

elif key_press.lower() == ’h‘:

gpio.cleanup()

# Light up the logo.

serial_to_arduino.write(’h‘)

elif key_press.lower() == ’j‘:

gpio.cleanup()

# Turn off the logo.

serial_to_arduino.write(’j‘)

elif key_press.lower() == ’p‘:

gpio.cleanup()

# Move the servo in reverse directory.

serial_to_arduino.write(’p‘)

time.sleep(0.05)

elif key_press.lower() == ’i‘:

gpio.cleanup()

serial_to_arduino.write(’m‘)

# Enter the random run mode.

serial_to_arduino.write(’i‘)

for z in range(20):

x = random.randrange(0, 5)

if x == 0:

for y in range(30):

detecte_distance()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_forward(0.05)

elif x == 1:

for y in range(30):

detecte_distance()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_left(0.05)

elif x == 2:

for y in range(30):

detecte_distance()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_right(0.05)

elif x == 3:

for y in range(30):

detecte_distance()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_pivot_left(0.05)

elif x == 4:

for y in range(30):

detecte_distance()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_pivot_right(0.05)

data_from_arduino = serial_from_arduino.readline()

data_from_arduino_int = int(data_from_arduino)

if data_from_arduino_int == 1111:

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_forward(0.05)

if data_from_arduino_int == 1111:

simple_wheeled_robot.__init__()

simple_wheeled_robot.stop()

elif data_from_arduino_int == 0000:

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_forward(0.05)

elif data_from_arduino_int == 0100:

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_left(0.05)

elif data_from_arduino_int == 1000 or

data_from_arduino_int == 1100:

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_left(0.08)

elif data_from_arduino_int == 0010:

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_right(0.05)

elif data_from_arduino_int == 0001 or

data_from_arduino_int == 0011:

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_right(0.08)

serial_to_arduino.write(’l‘)

elif key_press.lower() == ’u‘:

gpio.cleanup()

simple_wheeled_robot.print_lcd(1, 0, ’UltrasonicWare‘)

simple_wheeled_robot.print_lcd(1, 1, ’Distance:%.lf CM‘ %

simple_wheeled_robot.get_distance())

else:

pass

distance = simple_wheeled_robot.get_distance()

if distance 》= 20:

serial_to_arduino.write(’g‘)

elif distance 》= 10:

serial_to_arduino.write(’y‘)

elif distance 《 10:

serial_to_arduino.write(’r‘)

simple_wheeled_robot.buzzing()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_reverse(2)

serial_to_arduino.write(’k‘)

data_from_arduino = serial_from_arduino.readline()

data_from_arduino_int = int(data_from_arduino)

if data_from_arduino_int == 1:

simple_wheeled_robot.buzzing()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_right(2)

elif data_from_arduino_int == 10:

simple_wheeled_robot.buzzing()

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_left(2)

try:

command = tk.Tk()

command.bind(’《KeyPress》‘, input_key)

command.mainloop()

except KeyboardInterrupt:

gpio.cleanup()

Raspberry Pi測試代碼2

simple_wheeled_robot_run_2.py

該代碼實(shí)現(xiàn)的功能比較簡單,僅測試了機(jī)器人的電機(jī)遙控和超聲波避障兩個(gè)功能。

import Tkinter as tk

import RPi.GPIO as gpio

from simple_wheeled_robot_lib import SimpleWheeledRobot

simple_wheeled_robot = SimpleWheeledRobot()

simple_wheeled_robot.initialize_lcd()

def input_key(event):

print ’Key‘, event.char

key_press = event.char

seconds = 0.05

if key_press.lower() == ’w‘:

simple_wheeled_robot.go_forward(seconds)

elif key_press.lower() == ’s‘:

simple_wheeled_robot.go_reverse(seconds)

elif key_press.lower() == ’a‘:

simple_wheeled_robot.go_left(seconds)

elif key_press.lower() == ’d‘:

simple_wheeled_robot.go_right(seconds)

elif key_press.lower() == ’q‘:

simple_wheeled_robot.go_pivot_left(seconds)

elif key_press.lower() == ’e‘:

simple_wheeled_robot.go_pivot_right(seconds)

elif key_press.lower() == ’o‘:

simple_wheeled_robot.move_servo_left()

elif key_press.lower() == ’p‘:

simple_wheeled_robot.move_servo_right()

else:

pass

distance = simple_wheeled_robot.get_distance()

simple_wheeled_robot.print_lcd(1, 0, ’UltrasonicWare‘)

simple_wheeled_robot.print_lcd(1, 1, ’Distance:%.lf CM‘ % distance)

print “Distance: %.1f CM” % distance

if distance 《 10:

simple_wheeled_robot.__init__()

simple_wheeled_robot.go_reverse(2)

try:

command = tk.Tk()

command.bind(’《KeyPress》‘, input_key)

command.mainloop()

except KeyboardInterrupt:

gpio.cleanup()

Raspberry Pi測試代碼3

simple_wheeled_robot_run_3.py

該代碼實(shí)現(xiàn)的功能與上面的測試代碼2類似,只不過圖形界面本代碼里使用的是Pygame而不是之前的Tkinter。

import sys

import pygame

from pygame.locals import *

import RPi.GPIO as gpio

from simple_wheeled_robot_lib import SimpleWheeledRobot

simple_wheeled_robot = SimpleWheeledRobot()

pygame.init()

screen = pygame.display.set_mode((800, 800))

font = pygame.font.SysFont(“arial”, 64)

pygame.display.set_caption(’SimpleWheeledRobot‘)

pygame.mouse.set_visible(0)

while True:

gpio.cleanup()

for event in pygame.event.get():

if event.type == QUIT:

sys.exit()

if event.type == KEYDOWN:

time = 0.03

if event.key == K_UP or event.key == ord(’w‘):

simple_wheeled_robot.go_forward(time)

elif event.key == K_DOWN or event.key == ord(’s‘):

simple_wheeled_robot.go_reverse(time)

elif event.key == K_LEFT or event.key == ord(’a‘):

simple_wheeled_robot.go_left(time)

elif event.key == K_RIGHT or event.key == ord(’d‘):

simple_wheeled_robot.go_right(time)

elif event.key == ord(’q‘):

simple_wheeled_robot.go_pivot_left(time)

elif event.key == ord(’e‘):

simple_wheeled_robot.go_pivot_right(time)

Arduino測試代碼

simple_wheeled_robot.ino

該代碼從邏輯上比較好理解,在setup()函數(shù)初始化引腳的模式和串口波特率后,主函數(shù)loop()會(huì)不斷地從串口中讀取字符數(shù)據(jù),并根據(jù)字符的不同進(jìn)行不同的處理工作。

int distance;

int distance_left;

int distance_right;

int motor_value;

int motor_value_a;

int motor_value_b;

int motor_value_c;

int motor_value_d;

int motor_a = 6;

int motor_b = 7;

int motor_c = 8;

int motor_d = 9;

int servo = 5;

int led = 2;

int led_red = 13;

int led_yellow = 12;

int led_green = 11;

int distance_sensor_left = 3;

int distance_sensor_right = 4;

char data;

uint16_t angle = 1500;

void setup()

{

// Set serial’s baud rate.

Serial.begin(9600);

pinMode(motor_a, INPUT);

pinMode(motor_b, INPUT);

pinMode(motor_c, INPUT);

pinMode(motor_d, INPUT);

pinMode(servo, OUTPUT);

pinMode(led , OUTPUT);

pinMode(led_red, OUTPUT);

pinMode(led_yellow, OUTPUT);

pinMode(led_green, OUTPUT);

pinMode(distance_sensor_left, INPUT);

pinMode(distance_sensor_right, INPUT);

pinMode(A0, OUTPUT);

pinMode(A1, OUTPUT);

pinMode(A2, OUTPUT);

pinMode(A3, OUTPUT);

pinMode(A4, OUTPUT);

pinMode(A5, OUTPUT);

}

void loop()

{

if (Serial.available()) {

switch(Serial.read()) {

// Light up the logo.

case ‘h’: {

digitalWrite(A0, HIGH);

digitalWrite(A1, HIGH);

digitalWrite(A2, HIGH);

digitalWrite(A3, HIGH);

digitalWrite(A4, HIGH);

digitalWrite(A5, HIGH);

break;

}

// Turn off the logo.

case ‘j’: {

digitalWrite(A0, LOW);

digitalWrite(A1, LOW);

digitalWrite(A2, LOW);

digitalWrite(A3, LOW);

digitalWrite(A4, LOW);

digitalWrite(A5, LOW);

break;

}

// Move the servo in forward directory.

case ‘o’ : {

angle += 50;

if (angle 》 2500) {

angle = 2500;

}

break;

}

// Move the servo in reverse directory.

case ‘p’ : {

angle -= 50;

if (angle 《 500) {

angle = 500;

}

break;

}

case ‘n’: {

digitalWrite(led, HIGH);

break;

}

case ‘m’: {

digitalWrite(led, LOW);

break;

}

case ‘g’: {

// When the distance between objects and car is far enough,

// light the green led.

digitalWrite(led_green, HIGH);

digitalWrite(led_yellow, LOW);

digitalWrite(led_red, LOW);

break;

}

case ‘y’: {

// When the distance between objects and car is near enough,

// light the yellow led.

digitalWrite(led_yellow, HIGH);

digitalWrite(led_green, LOW);

digitalWrite(led_red, LOW);

break;

}

case ‘r’: {

// When the distance between objects and car is very near,

// light the red led.

digitalWrite(led_red, HIGH);

digitalWrite(led_yellow, LOW);

digitalWrite(led_green, LOW);

break;

}

case ‘k’: {

// Return distance sensor‘s state between objects and car.

distance_left = digitalRead(distance_sensor_left);

distance_right = digitalRead(distance_sensor_right);

distance = distance_left * 10 + distance_right ;

Serial.println(distance, DEC);

break;

}

case ’i‘: {

while (1) {

// Return motor’s state to raspberry pi.

motor_value_a = digitalRead(motor_a);

motor_value_b = digitalRead(motor_b);

motor_value_c = digitalRead(motor_c);

motor_value_d = digitalRead(motor_d);

motor_value = motor_value_a * 1000 + motor_value_b * 100 +

motor_value_c * 10 + motor_value_d;

Serial.println(motor_value, DEC);

delay(1000);

data = Serial.read();

if (data == ‘l’) {

break;

}

}

}

default:

break;

}

}

// Delay enough time for servo to move position.

digitalWrite(servo, HIGH);

delayMicroseconds(angle);

digitalWrite(servo, LOW);

delay(15);

}

總結(jié)這個(gè)簡單輪式機(jī)器人是大一那會(huì)兒我對自己課外所學(xué)知識的一個(gè)應(yīng)用。雖然現(xiàn)在回過頭再來看自己當(dāng)初做的項(xiàng)目,感覺技術(shù)原理非常簡單,遠(yuǎn)沒有我之后研究的ROS和MoveIt!那么復(fù)雜,但是通過整個(gè)制作過程,我學(xué)會(huì)了如何根據(jù)項(xiàng)目需求去網(wǎng)上購買相關(guān)的材料。

如何將主控等硬件設(shè)備安裝在機(jī)器人機(jī)械結(jié)構(gòu)最合理的位置上,如何使用IDE編寫Arduino程序,如何在Raspberry Pi上使用Python語言來讀取硬件數(shù)據(jù)并控制硬件,如何實(shí)現(xiàn)簡單的串口通信等等。我一直認(rèn)為興趣是最好的老師。

當(dāng)你開始接觸一個(gè)全新的領(lǐng)域時(shí),興趣可以成為你克服各種困難并鼓舞你前進(jìn)的強(qiáng)大動(dòng)力。當(dāng)然,除了興趣,更重要的是親自動(dòng)手實(shí)踐,書上的東西講得再好也是別人的,不是你的,就算重復(fù)造輪子也有著其無法替代的重要意義,因?yàn)椴⒉皇敲總€(gè)人都能造得出輪子,通過學(xué)習(xí)并實(shí)踐前人所學(xué)習(xí)過的知識,你會(huì)收獲別人不會(huì)有的寶貴經(jīng)驗(yàn)!

最后,個(gè)人認(rèn)為智能小車對于廣大剛開始接觸機(jī)器人的初學(xué)者來說確實(shí)是一個(gè)非常好的練手項(xiàng)目,你可以根據(jù)自己的喜好和技術(shù)水平的高低來定制屬于你自己的智能小車,實(shí)現(xiàn)你想要的各種功能??傊?,對于我來說。

通過本次項(xiàng)目我開始真正喜歡上了嵌入式開發(fā)并逐漸走上了專業(yè)化的道路,每個(gè)人都應(yīng)該有自己的夢想,那這個(gè)簡單輪式機(jī)器人就是我夢想的起點(diǎn),激勵(lì)著我不斷向前!當(dāng)然,也希望大家能在制作機(jī)器人的道路上玩得開心并有所收獲!

文章作者:繆宇飏,myyerrol 轉(zhuǎn)載于:https://myyerrol.io/zh-cn/2018/05/15/diy_robots_1_simple_wheeled_robot/

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • PWM
    PWM
    +關(guān)注

    關(guān)注

    114

    文章

    5196

    瀏覽量

    214371
  • 電機(jī)
    +關(guān)注

    關(guān)注

    142

    文章

    9053

    瀏覽量

    145924
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4344

    瀏覽量

    62809
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4809

    瀏覽量

    68817
  • GPIO
    +關(guān)注

    關(guān)注

    16

    文章

    1215

    瀏覽量

    52230

原文標(biāo)題:干貨|手把手教你自制輪式機(jī)器人

文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    手把手教你做星閃無人機(jī)》即將開播,鎖定15日晚七點(diǎn)!

    ”再次聯(lián)合推出《手把手教你做星閃無人機(jī)—KaihongOS星閃無人機(jī)開發(fā)實(shí)戰(zhàn)》系列課程,該課程與《手把手教你做PC—KaihongOS筆記本電腦開發(fā)實(shí)戰(zhàn)》同步并行,
    的頭像 發(fā)表于 01-13 19:42 ?49次閱讀
    《<b class='flag-5'>手把手</b><b class='flag-5'>教你</b>做星閃無人機(jī)》即將開播,鎖定15日晚七點(diǎn)!

    手把手教你做PC》課程即將啟動(dòng)!深開鴻引領(lǐng)探索KaihongOS筆記本電腦開發(fā)實(shí)戰(zhàn)

    ”攜手“電子發(fā)燒友”聯(lián)合推出了《KaihongOS手把手系列直播課程》,該系列課程以實(shí)際產(chǎn)品為案例,詳細(xì)講解每個(gè)產(chǎn)品的開發(fā)全流程。此次首發(fā)內(nèi)容是《手把手教你做PC-
    的頭像 發(fā)表于 01-06 20:46 ?94次閱讀
    《<b class='flag-5'>手把手</b><b class='flag-5'>教你</b>做PC》課程即將啟動(dòng)!深開鴻引領(lǐng)探索KaihongOS筆記本電腦開發(fā)實(shí)戰(zhàn)

    【「具身智能機(jī)器人系統(tǒng)」閱讀體驗(yàn)】2.具身智能機(jī)器人的基礎(chǔ)模塊

    具身智能機(jī)器人的基礎(chǔ)模塊,這個(gè)是本書的第二部分內(nèi)容,主要分為四個(gè)部分:機(jī)器人計(jì)算系統(tǒng),自主機(jī)器人的感知系統(tǒng),自主機(jī)器人的定位系統(tǒng),自主機(jī)器人
    發(fā)表于 01-04 19:22

    源碼開放 智能監(jiān)測電源管理教程寶典!

    源碼開放,今天我們學(xué)習(xí)的是電源管理系統(tǒng)的核心功能模塊,手把手教你如何通過不同的技術(shù)手段實(shí)現(xiàn)有效的電源管理。
    的頭像 發(fā)表于 12-11 09:26 ?305次閱讀
    源碼開放  智能監(jiān)測電源管理教程寶典!

    Air780E模組LuatOS開發(fā)實(shí)戰(zhàn) —— 手把手教你搞定數(shù)據(jù)打包解包

    本文要說的是低功耗4G模組Air780E的LuatOS開發(fā)實(shí)戰(zhàn),我將手把手教你搞定數(shù)據(jù)打包解包。
    的頭像 發(fā)表于 12-03 11:17 ?228次閱讀
    Air780E模組LuatOS開發(fā)實(shí)戰(zhàn) —— <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>搞定數(shù)據(jù)打包解包

    鴻蒙機(jī)器人與鴻蒙開發(fā)板聯(lián)動(dòng)演示

    鴻蒙機(jī)器人與鴻蒙開發(fā)板聯(lián)動(dòng)演示,機(jī)器人的角色為迎賓機(jī)器人,開發(fā)板負(fù)責(zé)人賓客出現(xiàn)監(jiān)聽
    發(fā)表于 12-02 14:55

    手把手教你如何自制目標(biāo)檢測框架

    今天,給大家分享一篇來自知乎的一篇關(guān)于目標(biāo)檢測相關(guān)的一些內(nèi)容, 本文基于Pytorch進(jìn)行編寫。
    的頭像 發(fā)表于 11-14 16:39 ?244次閱讀
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>如何<b class='flag-5'>自制</b>目標(biāo)檢測框架

    七騰機(jī)器人:防爆輪式機(jī)器人-四輪八驅(qū)全新上線

    今日,七騰機(jī)器人有限公司(以下簡稱“七騰機(jī)器人”)推出全新產(chǎn)品:防爆輪式機(jī)器人-四輪八驅(qū)。該款產(chǎn)品是七騰輪式巡檢
    的頭像 發(fā)表于 10-21 16:32 ?210次閱讀
    七騰<b class='flag-5'>機(jī)器人</b>:防爆<b class='flag-5'>輪式</b><b class='flag-5'>機(jī)器人</b>-四輪八驅(qū)全新上線

    手把手教你通過宏集物聯(lián)網(wǎng)工控屏&amp;網(wǎng)關(guān)進(jìn)行協(xié)議轉(zhuǎn)換,將底層PLC/傳感器的數(shù)據(jù)轉(zhuǎn)換為TCP協(xié)議并傳輸?shù)接脩?/a>

    手把手教你通過宏集物聯(lián)網(wǎng)工控屏&網(wǎng)關(guān)進(jìn)行協(xié)議轉(zhuǎn)換,將底層PLC/傳感器的數(shù)據(jù)轉(zhuǎn)換為TCP協(xié)議并傳輸?shù)接脩艚K端
    的頭像 發(fā)表于 08-15 13:29 ?566次閱讀
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>通過宏集物聯(lián)網(wǎng)工控屏&amp;網(wǎng)關(guān)進(jìn)行協(xié)議轉(zhuǎn)換,將底層PLC/傳感器的數(shù)據(jù)轉(zhuǎn)換為TCP協(xié)議并傳輸?shù)接脩? />    </a>
</div>                            <div   id=

    Al大模型機(jī)器人

    金航標(biāo)kinghelm薩科微slkor總經(jīng)理宋仕強(qiáng)介紹說,薩科微Al大模型機(jī)器人有哪些的優(yōu)勢?薩科微AI大模型機(jī)器人由清華大學(xué)畢業(yè)的天才少年N博士和王博士團(tuán)隊(duì)開發(fā),與同行相比具有許多優(yōu)勢:語言
    發(fā)表于 07-05 08:52

    手把手教你在orcad中設(shè)置CIS元器件數(shù)據(jù)庫,提高工作效率

    元器件數(shù)據(jù)庫,就是實(shí)現(xiàn)上述查找元件、放置元件時(shí)所需要調(diào)用的數(shù)據(jù)庫。本文將手把手教你如何在orcad中配置CIS元器件數(shù)據(jù)庫。
    的頭像 發(fā)表于 06-15 17:27 ?6451次閱讀
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>在orcad中設(shè)置CIS元器件數(shù)據(jù)庫,提高工作效率

    手把手教你排序算法怎么寫

    今天以直接插入排序算法,給大家分享一下排序算法的實(shí)現(xiàn)思路,主要包含以下部分內(nèi)容:插入排序介紹插入排序算法實(shí)現(xiàn)手把手教你排序算法怎么寫在添加新的記錄時(shí),使用順序查找的方式找到其要插入的位置,然后將
    的頭像 發(fā)表于 06-04 08:03 ?739次閱讀
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>排序算法怎么寫

    手把手帶你移植HAL庫函數(shù)

    開發(fā)者更高效地進(jìn)行嵌入式開發(fā)。手把手帶你移植HAL庫函數(shù)HAL庫提供了一套抽象接口,使開發(fā)者無需直接操作底層硬件寄存器,就能實(shí)現(xiàn)對硬件的控制。這種抽象使得代碼能夠更
    的頭像 發(fā)表于 05-18 08:04 ?2033次閱讀
    <b class='flag-5'>手把手</b>帶你移植HAL庫函數(shù)

    防爆輪式巡檢機(jī)器人作用和優(yōu)勢?

    在當(dāng)今的工業(yè)領(lǐng)域,安全生產(chǎn)始終是至關(guān)重要的議題。而在一些具有爆炸風(fēng)險(xiǎn)的環(huán)境中,如石油、化工、燃?xì)獾刃袠I(yè),傳統(tǒng)的人工巡檢方式面臨著諸多挑戰(zhàn)。然而,隨著科技的飛速發(fā)展,防爆輪式巡檢機(jī)器人應(yīng)運(yùn)而生,為這些
    的頭像 發(fā)表于 04-23 17:17 ?676次閱讀
    防爆<b class='flag-5'>輪式</b>巡檢<b class='flag-5'>機(jī)器人</b>作用和優(yōu)勢?

    農(nóng)業(yè)輪式機(jī)器人三維環(huán)境感知技術(shù)研究進(jìn)展

    子科技集團(tuán)公司第五十四研究所等多家科研機(jī)構(gòu),開展了針對農(nóng)業(yè)輪式機(jī)器人三維環(huán)境感知技術(shù)的研究。 作為未來農(nóng)機(jī)裝備的研究重點(diǎn),農(nóng)業(yè)輪式機(jī)器人正向著智能化與多功能化的方向發(fā)展。三維環(huán)境感知技
    的頭像 發(fā)表于 02-22 17:05 ?422次閱讀