树莓派小车参考方案,了解一下
摘要:制作這個項目的起因是大一下學期那會兒我通過學校圖書館里的《無線電》雜志開始接觸Raspberry Pi卡片式計算機和Arduino微控制器,其中Raspberry Pi給當初什么都不懂的我留下了非常深刻的印象:一個信用卡大小的板子竟然可以跑帶有圖形界面的GNU/Linux操作系統。
在強烈探索欲的驅使下,我從網上購買了兩塊Element14的Raspberry Pi一代Model B(現在早已經絕版了)板子以及其他相關配件,開始在Raspbian系統上自學Python和各種傳感器的使用方法,后來為了檢驗一下自己的學習成果,于是我便花費幾周的時間做了這個簡單的輪式機器人。雖然它涉及的原理并不復雜,但是對于那會兒剛開始接觸嵌入式的我來說,能成功搭建一個完整的機器人系統還是挺有挑戰性的。
概述
簡單輪式機器人其實是一個比較傳統的入門級智能小車,它擁有藍牙遠程遙控、超聲波避障、紅外邊緣檢測和紅外巡線(未完成)等功能,可以完成一些有趣的小實驗。此外,簡單輪式機器人的軟件是開源的,具體代碼可以從我的GitHub倉庫上獲得。
原理
硬件
以下是該簡單輪式機器人的硬件系統連接圖:
核心主控
系統的硬件核心主控分別為Arduino和Raspberry Pi。其中Arduino主要負責接收紅外光電測距模塊的數據,并控制裝有超聲波模塊的單軸舵機云臺的旋轉;而Raspberry Pi則可通過電機驅動模塊來完成對四個直流減速電機轉向和轉速的控制,此外它還能接收超聲波模塊和從Arduino串口發送上來的紅外光電測距模塊的數據來判斷當前機器人的前方和兩側是否遇到障礙物,若機器人與障礙物之間的距離小于一個特定的閾值,則Arduino和Raspberry Pi會分別改變LED的顏色并啟動蜂鳴器來發出警報。
當然,肯定會有人問:為什么我不能僅用Raspberry Pi來作為機器人的核心主控,非要再用一個Arduino呢?其實根據本項目的實際需求,確實只用一個Raspberry Pi就夠了,不過對于我來說使用Arduino主要出于以下三個原因的考慮:
Raspberry Pi一代Model B板子的GPIO引腳數量只有26個,就算復用一些帶有特殊功能的引腳,引腳資源依舊比較緊張。
Raspberry Pi官方提供的GPIO庫雖然含有PWM函數,但是實際在控制舵機的時候可能是由于軟件模擬的PWM方波還不夠穩定,導致舵機抖動得比較厲害。
可以學習Python的串口編程。
因此,綜合以上三個方面我選擇了Arduino和Raspberry Pi雙核心主控的系統架構。
外部電源
因為時間比較緊張,所以我沒有在電源管理上花費太多的功夫。對于Arduino,我使用的是能裝下6個1.5V干電池的的電池盒給其供電,而對于Raspberry Pi耗電量較大的需求,我是從大學舍友那借了一個充電寶來解決問題的,不過雖然供電可以了,但是由于充電寶的重量比較大,導致四個輪子受壓偏大,使得遙控的精準度受到了一定的影響。
電機驅動
機器人的電機驅動部分采用傳統的L293D芯片,它是一款單片集成的高電壓、高電流、四通道電機驅動芯片,其內部包含有兩個雙極型H橋電路,可通過設置IN1和IN2輸入引腳的邏輯電平來控制電機的旋轉方向,而EN使能引腳可連接到一路PWM上,通過調整PWM方波的占空比便可調整電機的轉速。
數據感知
為了能實現最基本的避障功能,我們需要為機器人配備有一些傳感器。這里我使用的傳感器為HC-SR04超聲波測距模塊和紅外光電避障模塊,其中紅外光電避障模塊具有一對紅外線發射與接收管,運行時發射管會發射出一定頻率的紅外線,當檢測方向遇到障礙物后,紅外線會反射回來被接收管接收,經過比較電路處理之后,信號輸出接口會輸出一個低電平信號,這樣只要在程序中對該接口的電平進行判斷便能得知機器人是否距離障礙物比較近。
與紅外光電避障模塊的工作原理類似,超聲波模塊能夠向空中發射超聲波信號,當其檢測到反射回來的信號后,只需將超聲波從發射到接收所用的時間乘上聲速再除以二便能得到機器人和障礙物之間的距離,從而為之后的機器人避障做好準備。
軟件
Raspberry Pi庫代碼
simple_wheeled_robot_lib.py
該庫代碼實現了GPIO引腳初始化函數、LED燈設置函數、蜂鳴器設置函數、電機控制函數、超聲波測距函數和LCD1602顯示函數,其中LCD1602顯示函數調用了Python的SMBUS庫來完成IIC數據通信,從而能將字符串顯示在屏幕上(注意:SMBUS和IIC協議之間是存在區別的,但在Raspberry Pi上兩者概念基本等同)。
import?time import?smbus import?RPi.GPIO?as?gpiomotor_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_timedistance?=?(duration?*?34300)?/?2gpio.cleanup()return?distancedef?send_command(self,?command):buf?=?command?&?0xF0buf?|=?0x04data_bus.write_byte(lcd_address,?buf)time.sleep(0.002)buf?&=?0xFBdata_bus.write_byte(lcd_address,?buf)buf?=?(command?&?0x0F)?<<?4buf?|=?0x04data_bus.write_byte(lcd_address,?buf)time.sleep(0.002)buf?&=?0xFBdata_bus.write_byte(lcd_address,?buf)def?send_data(self,?data):buf?=?data?&?0xF0buf?|=?0x05data_bus.write_byte(lcd_address,?buf)time.sleep(0.002)buf?&=?0xFBdata_bus.write_byte(lcd_address,?buf)buf?=?(data?&?0x0F)?<<?4buf?|=?0x05data_bus.write_byte(lcd_address,?buf)time.sleep(0.002)buf?&=?0xFBdata_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?Falseelse:return?Truedef?clear_lcd(self):self.send_command(0x01)def?print_lcd(self,?x,?y,?lcd_string):if?x?<?0:x?=?0if?x?>?15:x?=?15if?y?<?0:y?=?0if?y?>?1:y?=?1address?=?0x80?+?0x40?*?y?+?xself.send_command(address)for?lcd_char?in?lcd_string:self.send_data(ord(lcd_char))def?move_servo_left(self):servo_range?=?13gpio.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?+=?1time.sleep(0.5)pwm.stop()def?move_servo_right(self):servo_range?=?13gpio.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?-=?1time.sleep(0.5)pwm.stop()Raspberry Pi測試代碼1
simple_wheeled_robot_run_1.py
該代碼調用了上面自己編寫的機器人代碼庫,主要實現了超聲波距離檢測函數和鍵盤遙控函數,其中鍵盤遙控函數里面又根據所按按鍵的不同調用并組合上面代碼庫中的不同函數來完成某些特定的功能(比如機器人遇到障礙物后首先會發出警報,然后再進行相應的規避運動等)。
import?time import?serial import?random import?Tkinter?as?tk import?RPi.gpio?as?gpio from?simple_wheeled_robot_lib?import?SimpleWheeledRobotsimple_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.charkey_press?=?event.charseconds?=?0.05if?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:passdistance?=?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
該代碼實現的功能比較簡單,僅測試了機器人的電機遙控和超聲波避障兩個功能。
import?Tkinter?as?tk import?RPi.GPIO?as?gpio from?simple_wheeled_robot_lib?import?SimpleWheeledRobotsimple_wheeled_robot?=?SimpleWheeledRobot() simple_wheeled_robot.initialize_lcd()def?input_key(event):print?'Key',?event.charkey_press?=?event.charseconds?=?0.05if?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:passdistance?=?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"?%?distanceif?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
該代碼實現的功能與上面的測試代碼2類似,只不過圖形界面本代碼里使用的是Pygame而不是之前的Tkinter。
import?sys import?pygame from?pygame.locals?import?* import?RPi.GPIO?as?gpio from?simple_wheeled_robot_lib?import?SimpleWheeledRobotsimple_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.03if?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()函數初始化引腳的模式和串口波特率后,主函數loop()會不斷地從串口中讀取字符數據,并根據字符的不同進行不同的處理工作。
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); }成果
以下是制作完成后的成果圖和測試視頻:
總結
這個簡單輪式機器人是大一那會兒我對自己課外所學知識的一個應用。雖然現在回過頭再來看自己當初做的項目,感覺技術原理非常簡單,遠沒有我之后研究的ROS和MoveIt!那么復雜,但是通過整個制作過程,我學會了如何根據項目需求去網上購買相關的材料,如何將主控等硬件設備安裝在機器人機械結構最合理的位置上,如何使用IDE編寫Arduino程序,如何在Raspberry Pi上使用Python語言來讀取硬件數據并控制硬件,如何實現簡單的串口通信等等。我一直認為興趣是最好的老師,當你開始接觸一個全新的領域時,興趣可以成為你克服各種困難并鼓舞你前進的強大動力。當然,除了興趣,更重要的是親自動手實踐,書上的東西講得再好也是別人的,不是你的,就算重復造輪子也有著其無法替代的重要意義,因為并不是每個人都能造得出輪子,通過學習并實踐前人所學習過的知識,你會收獲別人不會有的寶貴經驗!
最后,個人認為智能小車對于廣大剛開始接觸機器人的初學者來說確實是一個非常好的練手項目,你可以根據自己的喜好和技術水平的高低來定制屬于你自己的智能小車,實現你想要的各種功能。總之,對于我來說,通過本次項目我開始真正喜歡上了嵌入式開發并逐漸走上了專業化的道路,每個人都應該有自己的夢想,那這個簡單輪式機器人就是我夢想的起點,激勵著我不斷向前!當然,也希望大家能在制作機器人的道路上玩得開心并有所收獲!
文章作者:繆宇飏,myyerrol ?轉載于:https://myyerrol.io/zh-cn/2018/05/15/diy_robots_1_simple_wheeled_robot/
總結
以上是生活随笔為你收集整理的树莓派小车参考方案,了解一下的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老司机又开车(来不及解释,快上!)之秒懂
- 下一篇: 【工具】音乐播放相关工具,音乐文件格式转