前面介紹了那麼多,完成的設計思路是這樣的:python
使用 樹莓派 ,Arduino , 小車底盤 Arduino電機擴展板。攝像頭,步進電機, USB無線網卡。linux
結構以下:PC <---TCP---> 樹莓派 <---Serial-->Arduino<---Serial-->步進電機git
PC爲主控端,樹莓派爲服務端,Arduino爲下位機驅動步進電機。PC作爲主控端經過WIFI發送指令給樹莓派(服務端),樹莓派再將指令經過Serial 發給下位機Arduino控制下邊的硬件。攝像頭鏈接樹莓派並將視頻回傳給PC端。後續能夠考慮加入手機端控制,試想經過手機來控制小車,並將視頻回傳給手機,這感受棒極了!不過這裏的手機端還沒有實現,不過技術上式徹底可行的,實現與否應該就是時間的問題吧。ubuntu
下面開始進行測試:vim
一、Arduino端:下面的代碼執行的功能是:經過樹莓派傳輸控制指令控制小車基本運動,具體操做指令以下,數字按鍵表示的是鍵盤上的按鍵。其中,按鍵8:——前進,按鍵2——後退,按鍵4——左轉彎,按鍵6——右轉彎,按鍵5——中止。服務器
將PC經過USB數據線與Arduino鏈接起來,編譯上述代碼,而後將其燒製到Arduino板上便可。燒製完成以後,斷開數據線。網絡
int pin1=8; int pin2=9; int speedpin1=11; int pin3=6; int pin4=7; int speedpin2=10; char sign; void setup() { // put your setup code here, to run once: pinMode(pin1,OUTPUT); pinMode(pin2,OUTPUT); pinMode(speedpin1,OUTPUT); pinMode(pin3,OUTPUT); pinMode(pin4,OUTPUT); pinMode(speedpin2,OUTPUT); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: if(Serial.available()) { sign=Serial.read(); switch (sign){ case '6'://right { analogWrite(speedpin1,200);//set the PWM speed as 100 analogWrite(speedpin2,200);//set the PWM speed as 100 digitalWrite(pin1,HIGH); digitalWrite(pin2,LOW); digitalWrite(pin3,HIGH); digitalWrite(pin4,LOW); break; } case '2'://backward { analogWrite(speedpin1,200);//set the PWM speed as 100 analogWrite(speedpin2,200);//set the PWM speed as 100 digitalWrite(pin1,LOW); digitalWrite(pin2,HIGH); digitalWrite(pin3,HIGH); digitalWrite(pin4,LOW); break; } case '4'://left { analogWrite(speedpin1,200);//set the PWM speed as 100 analogWrite(speedpin2,200);//set the PWM speed as 100 digitalWrite(pin1,LOW); digitalWrite(pin2,HIGH); digitalWrite(pin3,LOW); digitalWrite(pin4,HIGH); break; } case '8'://forward { analogWrite(speedpin1,200);//set the PWM speed as 100 analogWrite(speedpin2,200);//set the PWM speed as 100 digitalWrite(pin1,HIGH); digitalWrite(pin2,LOW); digitalWrite(pin3,LOW); digitalWrite(pin4,HIGH); break; } case '5'://stop { analogWrite(speedpin1,0);//set the PWM speed as 0 analogWrite(speedpin2,0);//set the PWM speed as 0 break; } Serial.flush(); } } }
二、樹莓派:樹莓派扮演者服務器的角色。打開樹莓派以後,編譯並運行OLSR自組網協議。socket
1)配置網絡爲ad-hoc網絡:ide
編輯以下的腳本程序,完成後保存爲"wlan0.sh"。oop
1 #!/bin/sh 2 #DEV=$1 3 ifconfig eth0 down 4 ifconfig wlan0 down 5 iwconfig wlan0 mode ad-hoc essid 522 channel 3 6 ifconfig wlan0 up 7 ifconfig wlan0 192.168.1.52/24 8 echo 1 > /proc/sys/net/ipv4/conf/all/accept_source_route
這裏須要注意的是,每張網卡因爲每次因爲所插位置的不一樣系統爲其分配的「wlanX」名中的「X」均不相同,可是隻要保持其物理位置不變,該名稱也不會再發生變化。於是針對每一個位置的每張網卡,在作上述修改以前須要使用命令:iwconfig 查看系統爲其指定的名稱以替換上述代碼中的「wlan0」。不一樣網卡應當配置不一樣的ip地址,即每次都須要修改「192.168.1.52/24」中的值。
因爲不但願每次打開樹莓派都要重複進行上述配置,於是但願將上述腳本添加到樹莓派開機自啓動程序列表中。
很多網友們建議修改"rc.local"文件,然而 "rc.local"的執行是隨機的,即不能保證每次開機都能執行,穩定性較差,故而考慮別的方法。比較穩妥的方法之一是執行腳本添加到/etc/init.d目錄下。具體操做以下:
首先,切換到root權限,而後將"wlan0.sh"移動至/etc/init.d目錄下。
接下來須要修改"wlan0.sh"的執行權限,執行命令:
root@raspiberrypi :/home/pi #chmod 777 /etc/init.d/wlan0.sh
而後把腳本加入到啓動清單:
root@raspiberrypi :/home/pi # update-rc.d wlan0.sh defaults
最後重啓系統,發現IP地址成功地開機就自動配置爲咱們設置好的IP地址了。
root@raspiberrypi :/home/pi # reboot
若是但願刪除某個開機自啓動項,能夠使用以下的指令:
pi@raspberrypi $ sudo update-rc.d -f wlan0.sh remove
2)編譯/運行olsrd源代碼
1.首先從http://www.olsr.org/?q=download下載olsrd源碼
2.解壓 tar包
tar jxvf olsrd-0.6.6.tar.bz2
3.編譯與安裝
解壓後會生成一個olsrd-0.6.6文件
#cd olsrd-0.6.6 //進入olsrd-0.6.6目錄
首先,切換進入olsrd-0.6.8的文件目錄,裏面的文件目錄結構以下所示:
一般在ubuntu下編譯(make)的時候會提示錯誤,提示缺乏flex、bison,因此在編譯make以前咱們須要安裝flex、bison兩個插件,須要聯網。安裝命令爲:
root@raspiberrypi #olsrd-0.6.8 $ apt-get install flex bison //在root權限下
pi@raspiberrypi #olsrd-0.6.8 $ Sudo apt-get install flex bison //在普通模式下
下載並安裝完成以後編譯文件,
pi@raspiberrypi #olsrd-0.6.8 $make // 編譯 pi@raspiberrypi #olsrd-0.6.8 $make install // 編譯後會生成olsrd目標文件,安裝olsrd
pi@raspiberrypi #olsrd-0.6.8 $make clean // 清除以前編譯生成的中間文件 pi@raspiberrypi #olsrd-0.6.8 $make libs // 編譯庫文件 pi@raspiberrypi #olsrd-0.6.8 $make install_libs // 安裝庫
安裝成功後,修改配置文件"/etc/olsrd/oldrd.conf",添加相應的網卡接口
用vim 打開/etc/olsrd/olsrd.config
pi@raspiberrypi #olsrd-0.6.8 $ vim /etc/olsrd/olsrd.config
在配置文件的最後有 「<OLSRd-Interface1>」 「<OLSRd-Interface2>」 ,在其後添加 「wlanX」,其中X爲你的工做無線網卡。
能夠經過iwconfig 查看當前使用的無線網卡,一般爲「wlan0」。
最後,運行olsrd
pi@raspiberrypi #olsrd-0.6.8 $sudo olsrd
若是出現如下的界面,說明運行成功了。
3)運行小車上的服務器程序
1 #!/usr/bin/env python 2 import socket 3 import serial 4 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 5 sock.bind (('192.168.1.24',8180)) 6 sock.listen(5) 7 while True: 8 print "aaaaaaaaaaaa" 9 connection,address=sock.accept() 10 print "client ip is " 11 print address 12 try: 13 connection.settimeout(5) 14 buf=connection.recv(1) 15 ser=serial.Serial('/dev/ttyACM0',9600) 16 ser.write(buf) 17 print "wwwwwwwwwwww" 18 print buf 19 except socket.timeout: 20 print "timeout" 21 connection.close()
上述配置完成以後,咱們考慮將其所有依次添加到開機自啓動項之中,這樣樹莓派每次加電啓動以後就會自動運行咱們的olsrd協議。完整的配置文件內容以下:
備註:其中olsrd程序所在位置「/usr/local/sbin/olsrd」是經過指令「which olsrd」查找到的。
3. PC 端:打開PC以後,編譯並運行OLSR自組網協議。接下來運行下列python客戶端程序「client.py」。
1 #!/usr/bin/env python 2 import socket 3 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 4 5 sock.connect(('192.168.1.25',8180)) 6 7 import time 8 #time.sleep(2) 9 buff=raw_input('enter:') 10 sock.send(buff) 11 print "aaaaaaaaaa" 12 sock.close()
上述爲python代碼均爲單擊測試代碼,多機測試代碼以下:
小車做爲client端,代碼以下:
1 #!/usr/bin/env python 2 import socket 3 import time 4 5 #create the TCP socket 6 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 8 #"192.168.1.25" is the sever's IP address 9 #"8180" is the port number of the sever 10 sock.connect(('192.168.1.25',8180)) 11 12 13 #time.sleep(2) 14 while True: 15 #the receive thread is obstructed until it receive data from the sever , 16 #or it won't run the next tatement 17 buff=sock.recv(1) 18 #when the link is disconnected ,the client will pirint "recv data is :" repeatedly 19 print "recv data is :" 20 print buff 21 #print "recv data is :{0}".foramt(buff) 22 #read form the serial ,/dev/ttyACM0 is the name of the equipment and 9600 23 #is the rate of bote 24 ser=serial.Serial('/dev/ttyACM0',9600) 25 ser.write(buf) 26 27 sock.close()
PC做爲csever端,代碼以下:
1 #!/usr/bin/env python 2 from multiprocessing import Process, Value 3 import socket 4 import serial 5 import time 6 7 #"l" respresent an interger,"0" represents the original value 8 num=Value('l',0) 9 handle=Value('l',0) 10 value_change=Value('l',0) 11 12 13 #user self-defined function 14 def hand(client,count): 15 while True: 16 if value_change.value==1 and num.value==count: 17 print "ready to send" 18 temp=handle.value 19 client.send(str(temp)) 20 print "handle send success." 21 while value_change.value: 22 temp=0 23 time.sleep(0.7) 24 client.close() 25 26 27 28 #mian function 29 if __name__ == '__main__': 30 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 31 print "socket create success." 32 sock.bind (('192.168.1.12',8180)) 33 sock.listen(1) 34 count=1 35 36 while True: 37 client, addr = sock.accept() 38 print "connect from :" 39 print addr 40 #fork a process to handle a new connecting client 41 t = Process(target = hand, args = [client,count]) 42 t.start() 43 #t.join() 44 print "process create success." 45 46 count=count+1 47 48 flag=raw_input("all the client connected?(y/n)") 49 if flag=="y": 50 #when all the client is connected 51 #continue to send info to control 52 #need to change for dymacially connected and disconnected 53 while True: 54 value_temp=raw_input("which client do you want to handle :") 55 handle_temp=raw_input("your handle :") 56 #get the number of the client need to contorl 57 num.value=int(value_temp) 58 #get the information that need to send to the client 59 handle.value=int(handle_temp) 60 #set the condition that all the client need to read 61 value_change.value=1; 62 #delay for 1 sescond for all the client to read from the shared memory 63 time.sleep(1) 64 #cancel the condition that all the client need to read 65 value_change.value=0; 66 s.close()
參考資料:
http://linux.51yip.com/search/iwconfig