0x00 控制手柄簡介
目前在ROS中可以使用的遊戲控制手柄很多,例如羅技F710無線藍牙手柄、北通USB手柄、Sony PS3手柄、xbox360的遊戲手柄等,現在都可以在ROS下使用了。我們可以利用手柄上的搖杆可以開發出很多功能,例如控制ROS小車的移動,這樣我們就不用使用鍵盤遙控程序teleop_twist_keyboard了。下面讓我們來看看各個控制手柄的樣子吧:
通過這幾張圖片我們就能了解現在的手柄造型都差不多,基本上就是搖杆加按鈕。這些手柄的價格還都不便宜,大概要100-200多塊左右。如果我們要設計一款ROS下專用的控制手柄的話,應該也不會很難。因為現在arduino和按鈕、搖杆、旋鈕什麼的都很容易買到。下面我們就自己動手來做一個簡單的ROS下可以使用的控制手柄吧!
0x01 硬體模塊介紹
對於該控制手柄的主控板,我們準備選用arduino。因為開發比較簡單,而且要外接的元器件也比較少,所以選用arduino就很合適了。這裡的arduino主控板我選用DFRobot的beetle,如下圖所示:
Beetle是Arduino Leonardo的極簡版本,具備和Leonardo類似的強大應用能力,特別適於一次性的DIY項目製作和可穿戴電子應用。Beetle與Arduino Leonardo兼容,在使用Arduino IDE開發環境時注意選擇「Arduino Leonardo」。下面我們來詳細查看該板的IO口介紹:
下面來介紹自鎖按鈕,就是按下去不會自動彈起來的按鈕,需要再次按一下才行,這樣我們就可以把它作為一個開關來使用。該按鈕是一個數字型接口的模塊,在使用時需要將其信號線與arduino的數字IO口連接才行。該自鎖按鈕的圖片如下:
下面來看一下模擬角度傳感器,其實有點像電位器的感覺。當在旋轉按鈕的時候,可以獲得旋轉的角度。我們可以利用這個功能來控制小車移動的速度,就跟摩託車的油門差不多。該模塊的輸出是模擬信號,因此需要將其接在arduino的模擬IO口上,該模塊圖片如下:
最後我們來看一下搖杆模塊,該模塊有5根引腳,如下圖所示:
最後,讓我們來看一下所有的模塊:
0x02 電路連接圖
在介紹完製作控制手柄所需的所有模塊後,我們就需要將自鎖按鈕、搖杆、模擬角度傳感器和Beetle主控板的IO口連接起來。在前面已經介紹過每個模塊的輸出是模擬還是數字的了,所以我們只需要根據需要將引腳焊接在Beetle上即可。下面我們來規劃下電路圖,如下圖所示:
根據該設計電路連接圖,我們來實際動手焊接,下面是焊接好的實物圖,如下所示:
0x03 編寫arduino代碼
在根據電路圖焊接好各模塊後,我們就可以來使用Arduino IDE開發程序了。下面先來查看完整的Arduino代碼,後面再來對代碼進行下解析說明:
1
12
13#define BAUD_RATE 57600
14#define ROTATE_RANGE 100
15#define SEND_RATE 10
16
17
20int self_lock_pin = 11;
21int handle_x_pin = A2;
22int handle_y_pin = A1;
23int handle_z_pin = 10;
24int rotation_pin = A0;
25
26
27void setup() {
28 pinMode(self_lock_pin, INPUT);
29 pinMode(rotation_pin, INPUT);
30 pinMode(handle_z_pin, INPUT_PULLUP);
31
32 Serial.begin(BAUD_RATE);
33}
34
35void loop() {
36 int lock_status = digitalRead(self_lock_pin);
37 int rotation_value = analogRead(rotation_pin);
38 int rotate_percent = map(rotation_value, 1023, 0, 0, ROTATE_RANGE);
39
40
41 int handle_x = analogRead(handle_x_pin);
42
43
44 int handle_y = analogRead(handle_y_pin);
45
46
47 int handle_z = digitalRead(handle_z_pin);
48
49
50 outPutData(lock_status, handle_x, handle_y, handle_z, rotate_percent);
51 delay(1000 / SEND_RATE);
52}
53
54
57void outPutData(int lock_status, int handle_x, int handle_y, int handle_z, int rotate_percent)
58{
59 Serial.print(lock_status, DEC);
60 Serial.print(" ");
61 Serial.print(handle_x, DEC);
62 Serial.print(" ");
63 Serial.print(handle_y, DEC);
64 Serial.print(" ");
65 Serial.print(handle_z, DEC);
66 Serial.print(" ");
67 Serial.println(rotate_percent, DEC);
68}
下面來對上述代碼進行下解析:
(1)首先最開始的三個宏定義,先是定義了串口通訊的波特率為57600。然後定義了模擬角度傳感器旋轉的一個範圍,由於該模塊的安裝方式導致它在最左邊位置默認輸出是1023,最右邊是0。但是我們希望在最左邊為0,最右邊為一個最大值,但是不想設置為1023這麼多了,這裡就定義100。意思是說把1023->0給轉換成0->100了,即平均分成100份了。最後一個宏定義是定義了數據的發送頻率,設置為10,表明發送頻率是10Hz,每100ms通過串口發送一次數據。
(2)下面初始化了各模塊連接的引腳,首先是自鎖按鈕,由於其輸出為數字型,所以連接在11引腳。下面三個分別是搖杆的x軸,y軸,z軸的連接引腳,其中x軸,y軸這兩個是模擬輸出,所以分別接在A2,A1引腳上。z軸是數字型輸出,接在10引腳上。最後一個是模擬角度傳感器,模擬輸出,所以接在A0引腳上。
(3)setup函數就是初始化函數,這裡就是配置了arduino的引腳模式和串口通訊的波特率。這裡需要注意對於搖杆的z軸引腳,該數字型引腳的配置需要配置成INPUT_PULLUP上拉,不然電平不穩,輸出的數據不穩定。
(4)loop函數是一直不斷循環執行的函數。在該函數中,我們就需要不斷的讀取各模塊的輸出數據,然後將數據整合成我們指定的協議類型,再通過串口將數據幀輸出即可。我們這裡定義的數據幀格式非常的簡單,省略了那些數據幀校驗,不包含幀頭,幀序號,校驗和,幀尾什麼的。因為我們這裡的數據傳輸不必保證數據的完整性,因為應用場景沒必要保證那麼高的可靠性。但是如果是一些對數據的完整性、穩定性要求較高的場景,我們就需要設計較為完整的數據幀格式來傳輸數據了。這裡我們定義的數據幀格式如下:
(5)最後的outPutData函數就是我們用來格式化我們數據幀並且發送的函數。可以看到我們在發送前四個數據時,使用的是Serial.print()函數,這樣就不會有換行。在發送最後一個數據rotate_percent時,我們使用的是Serial.println()函數,這樣我們就能保證在發送完這五個數據後發送一個換行符,表明一幀數據發送完畢。這樣就方便我們上位機代碼在解析數據時,可以區分什麼時候是一幀完整的數據。可以設想一下,如果我們最後也不加換行的話,那麼所有的數據都是在一行上,我們發送的數據幀又沒有定義幀頭、幀尾,那麼在上位機收到數據後,就無法截取出各模塊的數據了。
0x04 運行測試
在編寫好代碼,下面我們就可以將代碼上傳至beetle中了。在這裡需要注意,在Arduino IDE中需要選擇Leonardo板。當使用microUSB線連接到電腦上時,選擇如下:
然後將該代碼上傳至beetle板中,接下來我們就可以通過IDE提供的"串口監視器"來查看輸出的數據是否正確了。首先來測試一下自鎖按鈕,搖杆的x軸測試。當我們按下自鎖按鈕時,可以發現第一個數字變為1,當彈起來後又變為0。當往左邊推搖杆時,發現第二個數字變為0,推到最右邊為1023。如下圖所示:
接下來測試搖杆的前後,當往最下面推時,可以發現第三個數字變為0。當往前推動時,數字又變為1023。當往下按搖杆時,可以發現第4個數字變為0。具體如下圖所示:
最後來測試一下模擬角度傳感器的輸出,可以發現當扭動到最左邊時,串口輸出的第五個值為0。當扭動到最右邊時,值逐漸變為100。如下圖所示:
如果上面查看串口數據不夠直觀的話,我們就可以利用IDE自帶的「串口繪圖器」來將數據繪製出來,這樣查看更為直觀。如下圖所示,可以查看搖杆左右移動和上下移動時的數據圖效果:
最後來測試下旋鈕的數據圖,當往右邊逐漸旋轉時,發現右下角的圖也逐漸升高。當我們稍微往左邊旋轉時,圖也跟著下降。具體效果如下圖所示:
當現在我們已經測試了手柄的各模塊,它們可以正常工作,數據發送正常。接下來我們就可以編寫解析該數據幀的驅動程序了,在驅動程序中,我們就可以將數據重新封裝成ROS下的Twist消息,這樣就可以控制小車的移動了。
0x05 Reference
[1].ROS Wiki上joystick的主頁.
http://wiki.ros.org/joy
[2].ROS Wiki上ps3joy的主頁.
http://wiki.ros.org/ps3joy
[3].DFRobot設計的微型Arduino控制器Beetle.
http://www.dfrobot.com.cn/goods-839.html
[4].Beetle控制器的產品資料庫.
http://wiki.dfrobot.com.cn/index.php/(SKU:DFR0282)Beetle_%E6%8E%A7%E5%88%B6%E5%99%A8
[5].DFRobot設計的模擬角度傳感器.
http://www.dfrobot.com.cn/goods-108.html
[6].DFRobot設計的自鎖按鈕模塊.
http://www.dfrobot.com.cn/goods-1274.html
[7].自鎖按鈕的產品資料庫.
http://wiki.dfrobot.com.cn/index.php?title=(SKU:DFR0423)%E8%87%AA%E9%94%81%E6%8C%89%E9%92%AE%E6%A8%A1%E5%9D%97_Self-Locking_Switch
[8].淘寶上雙軸按鈕搖杆傳感器.
https://detail.tmall.com/item.htm?spm=a230r.1.14.6.4b8d777dVK7LEd&id=529728518075&cm_id=140105335569ed55e27b&abbucket=10
[9].Arduino搖杆程序開發.
https://blog.csdn.net/sdlgq/article/details/50386197?utm_source=blogxgwz0
0x06 Feedback
大家在按照教程操作過程中有任何問題,可以直接在文章末尾給我留言,或者關注ROS小課堂的官方微信公眾號,在公眾號中給我發消息反饋問題也行。我基本上每天都會處理公眾號中的留言!當然如果你要是順便給ROS小課堂打個賞,我也會感激不盡的,打賞30塊還會被邀請進ROS小課堂的微信群,與更多志同道合的小夥伴一起學習和交流!