111
Arduino 車循線 / 避障 設計研習營 主辦單位:電資學院 承辦單位:電機系 1

Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

Arduino車循線避障設計研習營

主辦單位電資學院

承辦單位電機系

1

日期 時間 上課內容

850-900 開幕式

900-1030 Arduino自走車實際操作

1030-1040 休息時間

1040-1200 Arduino自走車循線原理與實作

1200-1300 午餐時間

1300-1420 Arduino自走車避障原理與實作

1420-1430 休息時間

1430-1630 Arduino 自走車避障避障實作及

頒發證書

12月26日將舉辦健行電資盃兩輪機器人循軌避障競賽

2

3

Arduino-微電腦控制板介紹Arduino 微電腦控制板大小為長70mm寬54mm核心使用

ATmega328P 八位元的微處理器

具有32K程式記憶體2k存取記憶體及1K可擦拭記憶體14個數位式輸出入端6 個類比式輸出入端支援USB SPII2C等資料傳輸

3

4

Arduino 軟體安裝

至官方網站下載Arduino軟體(免費)( wwwarduinoccenMainSoftware )

將軟體解壓縮到指定資料夾

在桌面建立Arduino捷徑

將Arduino UNO 連結上電腦

4

5

Arduino 官網

6

下載Arduino 軟體

9

解壓縮

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 2: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

日期 時間 上課內容

850-900 開幕式

900-1030 Arduino自走車實際操作

1030-1040 休息時間

1040-1200 Arduino自走車循線原理與實作

1200-1300 午餐時間

1300-1420 Arduino自走車避障原理與實作

1420-1430 休息時間

1430-1630 Arduino 自走車避障避障實作及

頒發證書

12月26日將舉辦健行電資盃兩輪機器人循軌避障競賽

2

3

Arduino-微電腦控制板介紹Arduino 微電腦控制板大小為長70mm寬54mm核心使用

ATmega328P 八位元的微處理器

具有32K程式記憶體2k存取記憶體及1K可擦拭記憶體14個數位式輸出入端6 個類比式輸出入端支援USB SPII2C等資料傳輸

3

4

Arduino 軟體安裝

至官方網站下載Arduino軟體(免費)( wwwarduinoccenMainSoftware )

將軟體解壓縮到指定資料夾

在桌面建立Arduino捷徑

將Arduino UNO 連結上電腦

4

5

Arduino 官網

6

下載Arduino 軟體

9

解壓縮

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 3: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

3

Arduino-微電腦控制板介紹Arduino 微電腦控制板大小為長70mm寬54mm核心使用

ATmega328P 八位元的微處理器

具有32K程式記憶體2k存取記憶體及1K可擦拭記憶體14個數位式輸出入端6 個類比式輸出入端支援USB SPII2C等資料傳輸

3

4

Arduino 軟體安裝

至官方網站下載Arduino軟體(免費)( wwwarduinoccenMainSoftware )

將軟體解壓縮到指定資料夾

在桌面建立Arduino捷徑

將Arduino UNO 連結上電腦

4

5

Arduino 官網

6

下載Arduino 軟體

9

解壓縮

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 4: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

4

Arduino 軟體安裝

至官方網站下載Arduino軟體(免費)( wwwarduinoccenMainSoftware )

將軟體解壓縮到指定資料夾

在桌面建立Arduino捷徑

將Arduino UNO 連結上電腦

4

5

Arduino 官網

6

下載Arduino 軟體

9

解壓縮

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 5: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

5

Arduino 官網

6

下載Arduino 軟體

9

解壓縮

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 6: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

6

下載Arduino 軟體

9

解壓縮

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 7: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

9

解壓縮

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 8: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

10

Arduino 軟體

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 9: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

11

啟動 Arduino

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 10: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

12

Arduino IDE

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 11: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

13

中文畫面

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 12: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

14

Arduino USB

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 13: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

15

Arduino 初體驗

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 14: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

16

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 15: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

17

程式驗證

按下

檢查程式語法是否正確但不保證功能正常

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 16: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

18

程式上傳

按下

將程式燒錄進Arduino

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 17: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

19

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 18: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

20

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 19: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

21

程式架構1註解2定義參數3Setup()初始化工作 ndash 放於主程式開始運作前

例如 IO腳設定 參數設定 啟動引用特定函式

4Loop函式主程式主程式會持續重複執行其內容直到Arduino電源被關閉

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 20: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

耶 我設計的第一個程式了(example_1)

實驗一 認識 Arduino操作

組別 第一組

姓名 王小明李大可

日期 20151107說明 設計將13腳位控制一個LED ON時間 OFF 時間可隨意設定

Arduino 微控制板的 Pin 13 腳已經有接一個 LED 無須另外接int led = 13 定義一個可存取記憶體名字叫 lsquoledrsquo 的 並將13存入

int ON_time = 300 設定LED ON時間

int OFF_time = 200 設定 LED OFF 時間

void setup( ) pinMode (led OUTPUT) 將led 設定為輸出 相當於設定13腳位為輸出

void loop( ) digitalWrite (led HIGH) led 腳位輸出 HIGHdelay(ON_time) 延續 300 毫秒

digitalWrite(led LOW) led 腳位輸出 LOWdelay(OFF_time) 延續 200 毫秒

22

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 21: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

程式的內容有以下幾個部分 1程式的標頭注解

開頭

內容包括 實驗名稱 作者 日期 文件說明等

結尾

單行注解

2 定義常數 define led 13 (程式設計者自訂)3 定義變數(暫存器) int led = 13 每行程式的結尾必須加上

變數區分為全域變數和區域變數兩種全域變數可應用於整個程式區域變數僅在設定該變數之程式區使用

4控制結構

void Setup( ) void loop( ) 5 程式 a = b + 5 6 函式(副程式) pinMode(led OUTPUT) (Arduino 函式庫提供)

delay(1000) (Arduino函式庫提供)Motor(100100) (程式設計者自訂)

常數 OUTPUT INPUT HIGH LOW (Arduino 設定常數)23

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 22: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

24

連續旋轉型RC伺服馬達Continuous Rotation Servo Motor

RC伺服機(馬達)

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 23: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

25

伺服馬達轉動特性

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 24: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

26

RC伺服馬達程式控制觀念

伺服馬達是由脈衝時間寬度來調控稱為脈波寬度調變(Pulse Width Modulation簡稱PWM)我們只要依照這樣時序送電壓脈波給RC馬達的訊號線(白色線)馬達就會按照我們的設定旋轉

脈波寬度是輸出高準位訊號 (High) 並維持時間所需時間(如下)控制訊號週期為20 毫秒 (Low) (ms)

脈波寬Pulse Width 轉向 Direction of Rotation13 ms 順時鐘轉

15 ms 停止轉動

17 ms 逆時鐘轉

P12

15 ms 15 ms

20 ms

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 25: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

27

Rotational Velocity vs Pulse Width for Servo

-60

-40

-20

0

20

40

60

1300 1350 1400 1450 1500 1550 1600 1650 1700

Pulse Width ms

Rot

atio

nal V

eloc

ity R

PM

Right Servo

伺服馬達轉速與脈波關係圖

可藉由改變脈波寬度對伺服馬達調控轉速

通常是 1500 plusmn 100 ms 就可以了

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 26: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

28

1啟動伺服馬達函式庫

2建立自己的伺服馬達函式庫

include ltServohgtServo myservo

之後就可以引用此函式庫內所預先設計好的函式例如

myservoattach( )myservowrite( )myservowriteMicroseconds()

28

引用Arduino伺服馬達函式庫

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 27: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

29

讓Arduino車乖乖聽話 (Example 2)

include ltServohgt 引入 servo 函式庫Servo servoLeft 宣告左邊伺服馬達servo 函式庫名稱叫做servoLeftServo servoRight 宣告右邊伺服馬達servo 函式庫名稱叫做servoright

int L_servoPin =12 左邊RC伺服馬達由D12控制int R_servoPin =13 右邊RC伺服馬達由D13控制

void setup( ) 建立初始功能servoLeftattach(L_servoPin ) 啟動D11腳位的左邊RC伺服馬達servoRightattach(R_servoPin) 啟動D12腳位的右邊RC伺服馬達

void loop( )servoLeftwriteMicroseconds(1600) 左邊伺服馬達 PWM 1600usservoRightwriteMicroseconds(1400) 右邊伺服馬達 PWM 1400us delay(2000) 前進 2s servoLeftwriteMicroseconds(1500) 左邊伺服馬達 PWM 1500usservoRightwriteMicroseconds(1500) 右邊伺服馬達 PWM 1500us delay(2000) 停止 2s

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 28: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

30

說明

使用Arduino特定功能函式庫或外掛的函式庫注意如下

1 若是Arduino自己的函式庫直接 include lt函式庫hgt若是外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

我們在使用循軌感測器時需要借用外掛的函式庫再介紹如何安裝外掛函式庫

2通常需要宣告誰引用函式庫方式如下 Servo servoLeft Servo servoRight

這樣 servoLeft servoRight 就可以分別引用Servo的函式庫內的所有函式

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 29: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

31

Servo函式庫提供可以隨時啟動或關閉伺服馬達的設定

servoLeftattach (L_servoPin ) 啟動servoLeft(左邊RC伺服馬達)servoRightattach (R_servoPin) 啟動servoRight(右邊RC伺服馬達)

Servo函式庫提供伺服馬達直接轉動到所需角度的函式例如

servoLeftwrite(pos) 這裡 pos 指轉動角度 0-180

這功能用於擺動式的伺服機擺動式伺服機外觀與連續轉動伺服馬達相同唯一不同處擺動式伺服機只能左右擺動180度

至於連續轉動伺服馬轉動的函式寫法如下

servoLeftwriteMicroseconds( ) servoLeftwrite( )servoRightwriteMicroseconds( ) servoRightwrite( )

( ) 內是PWM的時間單位 微秒(us) ( ) 內是角度單位 度若想讓伺服馬達反轉 ( )填入 1700 ( ) 填入gt 90 例如 180

伺服馬達正轉 ( )填入 1300 ( ) 填入 lt 90 例如 0伺服馬達停止 ( )填入 1500 ( ) 填入 90

PWM啟動後伺服馬達會一直運轉直到我們下達改變writeMicroseconds( )內的數值或關閉Servo函式庫指令為止

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 30: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

32

問題探討

1如果發現Arduino車該停止時沒有完全停止該如何調整

2 請問 若想讓Arduino 車 前進 2秒停止 2秒該怎麼設計3 請問 如何設計讓Arduino 車向後退4 請問 如何讓Arduino 車向左向右轉該怎麼設計5 如果 發現Arduino車走不直該如何調整

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 31: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

連續轉動伺服馬達靜止數值為1500us 但是由於內部回授機制誤差會出現些微轉動

若左邊馬達出現微向後轉可將1500每次向上加10us 微向前轉可將1500每次向減加10us 直到停止為止

若右邊馬達出現微向前轉可將1500每次向上加10us 微向後轉可將1500每次向減加10us 直到停止為止

void loop()servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us delay(2000) 停止 2s

請務必記住左邊伺服馬達 停止轉動 修正後為 xxxx us 右邊伺服馬達 停止轉動 修正後為 xxxx us

Arduino 車靜止調整(Example 3)

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 32: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

34

建立運動副程式開始設計自己的副程式 (運動副程式) (Example 4)

Arduino 車前進時左邊馬達反轉右邊馬達正轉因此我們定義所謂 ldquo前進rdquo的動作要求如下

void forward( ) 前進副程式servoLeftwriteMicroseconds (1600) 左邊伺服馬達前進

servoRightwriteMicroseconds(1400) 右邊伺服馬達 前進

void stoprun( ) 停止副程式servoLeftwriteMicroseconds(1500) 左邊伺服馬達修正為 xxxx us servoRightwriteMicroseconds(1500) 右邊伺服馬達修正為 xxxx us

void loop( ) 主程式forward( ) 呼叫前進副程式delay(2000) 前進時間stoprun( ) 呼叫停止副程式delay(2000) 停止 2s

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 33: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

設計自己的副程式設計副程式的目的首先是可以節省程式的空間將相同功能寫成一個

獨立的副程式使用時呼叫它來執行即可其次是讓程式變得簡潔好看及容易除錯

常見的 Arduino 副程式設計有以下4種型式

1 純粹呼叫副程式 無回傳執行結果 格式如下

void 副程式名稱 () 副程式內容

例如

void forward() 前進副程式

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 34: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

設計副程式(續)2 帶有傳遞參數的呼叫副程式 無回傳執行結果

void 副程式名稱 (參數) 副程式內容

例如

void forward(int times) 前進副程式 帶有需要的延遲時間

servoLeftwriteMicroseconds (L_forward ) 左邊伺服機前進

servoRightwriteMicroseconds(R_forward) 右邊伺服機 前進

delay(times) 前進時間

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 35: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

設計副程式(續)3 純粹呼叫副程式 但要回傳執行結果

回傳資料形式 副程式名稱 ()

副程式內容return 回傳資料

例如 呼叫超音波感測器副程式 進行前方障礙物掃描

int ultrasonic( ) example 12

超音波感測器前方掃描處理程式

return cm 回傳前方障礙物的距離

回傳資料形式 char byte int unsigned int long boolean

寫於 呼叫副程式的前頭

注意 若用 void 表示無回傳值

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 36: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

設計副程式(續)4 帶有傳遞參數呼叫副程式 回傳執行結果

回傳資料形式 副程式名稱 (參數)

副程式內容

例如 例如有兩個超音波進行前方障礙物掃描

int ultrasonic( int dir ) 呼叫超音波感測器 藉由dir決定是啟動哪個超音波

if (dir == left)啟動左邊超音波

else啟動右邊超音波

感測器前方掃描處理程式

return cm

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 37: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

39

建立運動副程式設計Arduino 車帶有時間參數的ldquo前進rdquo ldquo停止rdquo 副程式(Example 5)

void forward(int times) 前進副程式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void stoprun ( int times) 停止副程式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達 1500usservoRightwriteMicroseconds( R_stop) 右邊伺服馬達 1500us delay(times) 停止並等待時間

void loop() 主程式forward(2000) 前進 2 秒stoprun(2000) 停止 2 秒

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 38: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

40

Arduino車運行模式的討論

1 停止2 直線前進3 急速轉彎90度(小S) 以車軸中心旋轉(循軌轉彎使用)4 緩速轉彎90度(大S) 以一邊車輪為中心旋轉5 差速轉彎 (避障使用)5 直線後退6 以車軸中心180度迴轉

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 39: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

41

建立所有運動副程式(Example 6)

include ltServohgt 引入 servo 函式庫

Servo servoLeft 宣告左邊伺服馬達引用servo 函式庫

Servo servoRight 宣告左邊伺服馬達引用servo 函式庫(注意名稱不可重複)

int Left_Motor = 12 左邊RC伺服馬達由D12控制

int Right_Motor = 13 右邊RC伺服馬達由D13控制

int L_forward = 1600 左邊馬達前進int L_stop = 1500 左邊馬達停止int L_backward = 1400 左邊馬達後退

int R_forward = 1400 右邊馬達前進int R_stop = 1500 右邊馬達停止int R_backward = 1600 右邊馬達後退

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 40: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

42

void forward(int times) 前進函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達前進servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 前進時間

void backward(int times) 後退函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_backward) 右邊伺服馬達後退delay(times) 後退時間

void trunLeft(int times) 左轉函式servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉動時間

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 41: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

void trunRight(int times) 右轉函式servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void stoprun ( int times) 停止函式servoLeftwriteMicroseconds( L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds( R_stop) 右邊伺服馬達停止delay(times) 停止時間

void setup()servoLeftattach(Left_Motor) 啟動左邊伺服馬達

servoRightattach(Right_Motor) 啟動右邊伺服馬達

43

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 42: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

44

void loop() 主程式forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_s(750) 小s左轉

stoprun(1000)trunRight_s(750) 小s左轉

stoprun(1000)

forward(2000) 前進 2 秒stoprun(1000) 停止 01 秒trunLeft_S(1200) 大S左轉

stoprun(1000)trunRight_S(1200) 大S右轉

stoprun(1000)backward(2000)stoprun(100)

耶 我可以完全控制Arduino車囉

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 43: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

馬達左右轉方式的討論

void trunLeft(int times) 左轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_S(int times) 左轉函式(向前左轉 ) (大S)servoLeftwriteMicroseconds(L_stop ) 左邊伺服馬達停止servoRightwriteMicroseconds(R_forward) 右邊伺服馬達前進delay(times) 轉彎時間

void trunLeft_SS(int times) 左轉函式(向後左轉 ) (倒S)servoLeftwriteMicroseconds(L_backward ) 左邊伺服馬達後退servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

45

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 44: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

void trunRight(int times) 右轉函式(急轉) (小S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 後進delay(times) 轉彎時間

void trunRight(int times) 右轉函式 (大S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_stop) 右邊伺服馬達停止delay(times) 轉彎時間

void trunRight(int times) 右轉函式(倒S)servoLeftwriteMicroseconds(L_forward ) 左邊伺服馬達 前進servoRightwriteMicroseconds(R_backward) 右邊伺服馬達 停止delay(times) 轉彎時間

46

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 45: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

47

練習1 利用前進及左轉右轉副程式 讓控制Arduino車走L型

路徑(重點設計90度的轉彎)2 利用前進及左轉右轉90度的轉彎副程式 讓控制

Arduino車走以下路徑(每段時間3秒)

3 直線路徑來回走(重點利用(小S)設計180度的迴轉) (行走時間3秒)

47

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 46: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

48

馬達控制 參數法 (Example 7)

定義馬達參數 前進(100) 停止(0) 後退(-100)

左 右馬達參數組合如下( 0 0) 車子停止 ( 100 100) 車子前進 (-100 -100) 車子後退( 0 100) 前進左轉(大S)

(-100 0) 後退左轉 (大S)

(-100 100) 急速左轉 (小S)( 100 0) 前進右轉 (小S) (0 -100) 後退右轉 (倒S) (100 -100) 急速右轉 (倒S)

48

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 47: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

49

引用函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳

define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定 void setup()

MOTORON() 開啟 RC 伺服馬達功能

49

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 48: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

50

引用副程式 void MOTORON()L_motorattach(L_motor_pin) 啟動 L_motor_pin (D 11) 的伺服馬達

R_motorattach(R_motor_pin) 啟動 R_motor_pin (D 12) 的伺服馬達

void MOTOROFF()L_motordetach() 關閉接於 L_motor_pin 的伺服馬達

R_motordetach() 關閉接於 R_motor_pin 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左邊馬達送出 1500 + L (us)R_motorwriteMicroseconds(1500 - R) 右邊馬達送出 1500 - R (us)

50

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 49: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

51

主程式 void loop()

MOTOR(100 100) 車子前進

delay(1000)MOTOR(0 0) 車子停止

delay(1000)MOTOR(-100 -100) 車子後退

delay(1000)MOTOR(0 0) delay(1000)MOTOR(0 100) 前進左轉

delay(1000)MOTOR(0 0)delay(1000)

51

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 50: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

52

MOTOR(100 0) 前進右轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(-100 0) 後退左轉

delay(1000)MOTOR(0 0)delay(1000)MOTOR(0 -100) 後退右轉

delay(1000)MOTOR(0 0)delay(1000)

MOTOROFF() 關閉 RC 伺服馬達功能

delay(5000)

52

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 51: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

53

Arduino車循軌及避障設計

1 掌握系統的參數是設計的重點

2 使用感測器的性能要很清楚

3 如何用簡單易懂的方式呈現設計

4 如何提高感測速率避免影響準度

53

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 52: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

54

Arduino 車基本參數長(L)125 cm 寬(W)115 cm 高(H) gt75 cm

輪直徑(d) 67 cm

輪軸距前緣 25 cm

輪軸距後緣 100 cm

輪軸距紅外線感測器 35 cm

輪軸距超音波感測器 2 cm

Arduino 車使用RC伺服馬達

RC伺服馬為3pin接線 黑(地) 紅(+5v) 白(訊號)

RC伺服馬達轉數 45-50 rpm

以48rpm為基準 換算為 08rps 每秒08圈

每圈的長度 πd = 20 cm

車速 16 cms 或 625 mscm

54

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 53: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

55

問 急轉90度(小S) 換算車輪轉動多少圈(n)

耗時(T)多久

急轉車輪一邊前進一邊後退車子會以車軸中心為座標原點而旋轉

轉90度相當於車子以車軸為中心旋轉14圈長度既 14 π(W) 此時假如車輪轉動n圈長度既 nπd兩者相等(nπd = 14 πW )整理得知

n = 14 (Wd) = 025 (11567) = 04291圈T = 0429108 = 0536375 (S) = 536 (mS)

注意 必須考慮加減速摩擦力的問題實際值會略大於計算值

55

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 54: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

設計左轉90度(小S)有4種方法

1 直接設定小S左轉 再延遲90所需要時間(毫秒)Motor(-100 100) 設定小S左轉

delay(700) (執行)延遲700 毫秒

2設計左轉90度時間的副程式 turnLeft( int delay_time)

int delay_time = 700

呼叫左轉副程式参數為 delay_time 毫秒

void turnLeft( int delay_time)

Motor(-100 100) 設定小S左轉

delay(delay_time) 執行700 毫秒

如何設計左轉90度(小S)

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 55: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

3 設計左轉90角的副程式 turnLeft_angle(int angle )int angle90 = 700

void turnLeft( angleƟ) Motor(-100 100) 設定小S轉動方式

int delay_time = long(700) angleƟ 90delay(delay_time) 執行延遲毫秒

4 設計任意方向旋轉任意角度的副程式 turn_angle(angle) 正角度表示向右轉 負角度表示向左轉

void turn_angle( int angle) if ( angle gt 0 )

Motor(100 -100) 設定小S向右轉動

else Motor(-100 100) 設定小S向左轉動

int delay_time = long(700 (abs(angle)) 90 delay(delay_time) 執行延遲毫秒

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 56: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

58

問 緩轉90度(大S) 換算車輪轉動多少圈(n) 延遲時間(T)

緩轉車輪一邊停止一邊前進或後退車子以靜止車輪為座標原點旋轉

車子以一邊車輪為中心轉14圈長度即 14 π2W假如車輪轉動n圈長度即 nπd兩者相等整理得知

14 π(2W) = n π dn = 14 (2Wd) = 025 (2x11567) = 08582圈T = 0858208 = 107275 (S) = 1073 (mS)

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 57: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

59

認識循軌競賽

1 比賽車子有長寬高的限制(少數會有重量限制)

2 最短時間走完全程

3 全程不得遙控或接觸

4 車子必須放於起跑區內 聽哨音開始啟動

5 車頭離開起跑區接觸軌道開始計時

6 過程中車身不得全部離開軌道否則算出局

7 障礙區與斷線區例外但必須在指定區間內返回軌道

8 車頭接觸終點線停止計時

9 車子必須停於終點區內(有些未規定)

10 若規定時間內尚未回到終點則採計階段成績

59

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 58: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

60

認識比賽軌道

1 白底黑軌 或 黑底白軌

2 軌道寬度一般為 18cm plusmn 10

3 直角轉彎(L型路口)(迷宮)

4 圓弧轉彎(競速)

5 T字路口(迷宮)

6 十字路口(迷宮)(競速)

7 死巷(180度迴轉)(迷宮)

循軌避障算迷宮的一種

60

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 59: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

61

循軌研究

61

藉由感測器對軌道的追蹤讓車子可以一直保持在軌道上

顯然必須一直監視及控制車子左右微調讓車子不要偏離軌道

所以對於車子的調整能力感測器的性能及軌道特性必須弄清楚是循軌設計之首要

車子的調整能力必須實作逐步調整才能讓車子做出完美的追蹤

以下介紹感測器的性能

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 60: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

62

循軌感測器研究TQR-8RC 反射式感測陣列

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 61: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

63

bull TQR-8RC 反射式感測陣列使用5V電源

bull TQR-8RC 反射式感測陣列可以依需要調整使用個數本次將使用4顆感測器中間兩顆及最左最右 1顆

bull TQR-8RC 反射式感測陣列使用時離地距離(6-12mm)最佳10mm

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 62: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

64

認識感測器與循軌關係1 首先確定白色黑色何者是(High1) 何者是(Low0)

以TQR-8RC為例

偵測到黑色是(High1)而偵測到白色是(Low0)

2 以黑底白軌為例

出現0表示在軌道上

出現1表示離開軌道

3 循軌設計 兩個感測器 三個感測器 及 五個感測器等常見手法

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 63: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

65

黑白校準

bull一般比賽的環境都說是現場的燈光環境可是A場地換成B場地誰也沒保握燈光的條件都是一樣的

bull顯然不想要讓自己辛苦努力因為現場條件改變而毀於一旦

bull最好的概念就是賽前對針對現場的燈光環境進行校準這樣就可以降低意外的發生

bull循軌就是靠黑白來判斷是否在線上因此比賽前要找出紅外線對黑白的讀值是多少以它為基準就可以大大提昇判斷的準確性

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 64: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

66

什麼做黑白校準

假設沒有任何校準動作紅外線感測器對黑白的讀值分別是45V 及 23V

通常我們認為黑白的讀值是5V及0V 而以中間數25V為界線如此會發現黑色有(45V-25V=2V)的安全區域而白色只有(25V-23V=02V)的安全區域因此只要光源發生變化就容易出錯

若發現黑白的讀值分別是45V 及23V而以中間數 (45V+ 23V) 2 = 34V為界線如此黑色白色的安全區域一樣大(11V) 如此光源發生變化相對比較不容易出錯這就叫黑白校準

重點就是比賽前找出黑白的讀值再以中間值做為準線這樣就可以得到最大的安全區域

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 65: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

1 出售TQR-8RC 反射式感測陣列的POLOLU公司針對此產品提供了一個函式庫叫 QTRSensors 可以讓使用者進行黑白校準以提高對循軌的正確度

2 除了黑白校準外可以讓使用者可以彈性選用幾顆紅外線感測器可選 1-8顆

3 針對讀取紅外線感測器的處理 QTRSensors 提供方便的副程式

4 唯一不方便的是引用QTRSensors 函式庫必須額外的設定包括

1 使用紅外線感測器數量

2 感測器讀值時最長等待時間

3 驅動LED 接腳 D24 建立紅外線感測器的資料儲存區塊(矩陣)

67

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 66: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

68

建立TQR-8RC 函式庫範例include ltQTRSensorshgt 引用TQR-8RC函式庫

define NUM_SENSORS 4 使用紅外線感測器數量define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 驅動LED 接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

引用QTRSensors函式庫規定的寫法 QTRSensorsRC qtrrc為我們的函式名稱函式內容數位接腳位置 使用紅外線感測器數量 最長等待時間

驅動LED 接腳 4顆感測器分別接於數位接腳的 D3-D6

QTRSensorsRC qtrrc( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 67: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

69

使用 TQR-8RC函式庫說明這裡使用外掛的函式庫TQR-8RC函式庫

include ltQTRSensorshgt注意如下

1 使用外掛的函式庫則必須是先將函式庫放入Arduino的檔案夾裡的libraries資料夾裡

2引用TQR-8RC函式必須注意的地方

首先需要定義3個参數及一個儲存資料的矩陣方式如下

define NUM_SENSORS 使用紅外線感測器數量

define TIMEOUT 感測器讀值時最長等待時間

define EMITTER_PIN 驅動LED 接腳 D2unsigned int sensorValues[NUM_SENSORS] 資料儲存矩陣

這裡 unsigned int 為一種資料型態表示所存取的資料均為正數不具正負號

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 68: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

70

2宣告引用QTRSensors函式庫方式如下

QTRSensorsRC qtrrc ( (unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

誰引用函式庫 qtrrc 你可以改成你記得住的名稱

QTRSensors函式庫提供的功能如下1 qtrrccalibrate( )2 qtrrccalibratedMinimumOn[i]3 qtrrccalibratedMaximumOn[i]

i 表示 0 到 NUM_SENSORS的值4 qtrrcreadLine(sensorValues)

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 69: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

71

對TQR-8RC進行校準(example 8)

觀念做法 校準時讓車子左右各擺動90度

引用TQR-8RC 函式庫及定義參數

include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量 最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 70: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

72

引用Arduino車函式庫及定義參數include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達Servo R_motor 設定右邊馬達

define L_motor_pin 12 左邊馬達 arduino 接腳define R_motor_pin 13 右邊馬達 arduino 接腳

開機參數設定void setup( )Serialbegin(9600) 開啟監視視窗MOTORON() 開啟 RC 伺服馬達功能Calibration() 感測器校準delay(1000)

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 71: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

主程式void loop()qtrrcreadLine(sensorValues) 直接讀取TQR-8RC

Serialprint( LL = ) Serialprint(sensorValues[0]) 顯示 LL 讀值

Serialprint(t) Serialprint( L = ) Serialprint(sensorValues[1]) 顯示 L 讀值

Serialprint(t) Serialprint( R = ) Serialprint(sensorValues[2]) 顯示 R 讀值

Serialprint(t) Serialprint( RR = ) Serialprint(sensorValues[3]) 顯示 RR 讀值

Serialprintln()delay(250)

73

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 72: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

引用副程式 void MOTORON( )

L_motorattach(L_motor_pin) 啟動接於 pin 13 的伺服馬達

R_motorattach(R_motor_pin) 啟動接於 pin 12 的伺服馬達

void MOTOROFF( )L_motordetach( ) 關閉接於 pin 13 的伺服馬達

R_motordetach( ) 關閉接於 pin 12 的伺服馬達

void MOTOR(int L int R)L_motorwriteMicroseconds(1500 + L ) 左輪的PWM值

R_motorwriteMicroseconds(1500 - R) 右輪的PWM值

74

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 73: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

感測器校準 void Calibration()

define count_90 40 馬達轉90度的次數 請以實際測試值修正define count_180 80 馬達轉180度的次數 請以實際測試值修正

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(-50 50) 讓Arduino車向左緩慢旋轉for (int i = 0 i lt count_180 i++) 校準過程 向左180度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(50 -50) 讓Arduino車向右緩慢旋轉for (int i = 0 i lt count_90 i++) 校準過程 向右90度

qtrrccalibrate( ) 讀取所有紅外線感測器值

MOTOR(0 0) 車子停止

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 74: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

76

循軌設計

1兩個感測器循軌設計

2三個感測器循軌設計

3五個感測器循軌設計

感測器數量越多表示循軌越精細然而判斷的條件也變得複雜

無形中也增加設計的困難度

對於初學者應該盡量將問題簡化雖然可能造成循軌精度變差然而不影響整體功能表現

因此以下我們將以兩個感測器循軌為我們主要的設計

同時也使用兩個感測器做為路口判斷的設計

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 75: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

77

兩個感測器循軌設計

1兩個感測器距離大約09cm 若中間對準軌道中央則感測器相當於在軌道的14處及34處

2當左邊感測器出現HIGH時表示車子向左偏移14進行向右邊修正

3當右邊感測器出現HIGH時表示車子向右偏移14進行向左邊修正

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 76: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

78

循軌設計以中間2個感測器(LR)做為循軌

左右2個感測器(LLRR)做為路口判斷

各出現4種可能的狀況

78

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 77: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

79

循軌狀況討論

00 表示車子正好在軌道中央不用調整 繼續前進

01 表示車子偏右需要向左修正

10 表示車子偏左需要向右修正

11 表示離開軌道了一般設計讓車子停下來

11 有人設計讓它繼續前進例如有些比賽會設計斷線區

車子必須無偵測狀態下走過斷線區又回到軌道上

這是考驗車子直線行走能力

79

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 78: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

80

路口狀況討論

0 0 表示遇到T字路口或 十字路口

0 1 表示遇到左轉路口

1 0 表示遇到右轉路口

1 1 表示正常軌道上

80

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 79: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

81

循軌狀況為4選一的情況

Arduino語法 提供幾種分岔(多選一)處理式

1利用多個 if 條件式組合處理

2利用 if else 條件式的多選一處理

3使用 Swtich case的分岔(多選一)處理

81

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 80: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

82

if 條件式組合成多選一的處理

if(感測值 = = 00 ) 車子繼續前進 if(感測值 = = 01 ) 車子向左修正if(感測值 = = 10 ) 車子向右修正if(感測值 = = 11 ) 車子繼續前進

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 81: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

8383

例假設循軌感測器值存於 T_index

if (T_index = = 00) T_index = 00 表示車子在軌道中央處forward ( )

if (T_index = = 01) T_index = 01 表示車子在軌道偏右向左修正trunleft ( )

if (T_index = = 10) T_index = 10 表示車子在軌道偏左向右修正trunright ( )

if (T_index = = 11) T_index = 11 表示車子在斷線區維持前進forward ( )

if 條件式多選一處理範例

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 82: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

8484

if(軌道感測值 == 00 ) 車子繼續前進

else if(軌道感測值 == 01 ) 車子向左修正

else if(軌道感測值 == 10 ) 車子向右修正

else if(軌道感測值 == 11 ) 車子維持前進

else 車子前進

If else 條件式的多選一處理

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 83: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

8585

Switch (軌道感測值 ) case 00 車子前進

breakcase 01 車子向左修正

break case 10 車子向右修正

breakcase 11 車子維持前進

break其他 break

Swtich case 的分岔(多選一)處理

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 84: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

86

路口狀況 4選一的情況處理

以Swtich case 處理為例

Switch (路口感測值) case 00 視狀況 遇到T字路口或十字路口

breakcase 01 車子向左轉90度 遇到左轉路口

break case 10 車子向右轉90度 遇到右轉路口

breakcase 11 車子前進 正常軌道上

break其他 break

86

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 85: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

87

Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)

功能說明 引入 4 個 IR 紅外線循軌設計

0 表示出現黑色 1 表示出現白色定義4個 IR 紅外線感測器名稱 LL L R RR

彎道偵測 (LL RR) LL 偵測軌道左彎 RR 偵測軌道右彎

循軌偏離偵測 (L R) 循軌偵測總共有4種組合 如下(00) 車子在軌上 (01) 車子偏右(10) 車子偏左(11) 車子不在軌上

彎道偵測總共有4種組合 如下(00) 出現十字路口或 T型路口(01) 左邊出現彎道(10) 右邊出現彎道(11) 正常軌道上

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 86: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

88

引用TQR-8RC 函式庫及定義參數 include ltQTRSensorshgt

define NUM_SENSORS 4 使用紅外線感測器數量最多到 8個define TIMEOUT 2500 感測器讀值時最長等待時間define EMITTER_PIN 2 LED 驅動接腳 D2

unsigned int sensorValues[NUM_SENSORS] 自訂變數矩陣

QTRSensorsRC qtrrc((unsigned char[]) 3 4 5 6NUM_SENSORS TIMEOUT EMITTER_PIN)

int LL L R RR T_index R_index level

引用Arduino車函式庫及定義參數 include ltServohgt 引入 RC 伺服機函式庫

Servo L_motor 設定左邊馬達

Servo R_motor 設定右邊馬達

define L_motor_pin 11 左邊馬達 arduino 接腳

define R_motor_pin 12 右邊馬達 arduino 接腳

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 87: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

開機參數設定 void setup()MOTORON() 開啟 RC 伺服機功能

MOTOR(0 0) Calibration() 感測器校準

MOTOROFF() delay(2000)MOTORON()

主程式void loop()

IRread() 讀取TQR-8RC Tracking() 循軌處理

Cross() 路口處裡

89

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 88: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

馬達副程式 感測器校準同前例

讀取軌道黑白值校準後

全黑值 = 1000全白值 = 0中間值 0 到 1000 之間

因此將黑白的分界值設為 500讀值 gt 500 視為讀到黑色

讀值 lt= 500 視為讀到白色

當出現白色將相對應的監視 LED 亮起來

當出現黑色將相對應的監視 LED 熄滅

這樣可方便觀測循軌及轉彎的現象

90

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 89: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

if (sensorValues[0] gt 500)LL = 1

elseLL = 0

if (sensorValues[1] gt 500) L = 1

elseL = 0

if (sensorValues[2] gt 500)

R = 1

else

R = 0

91

if (sensorValues[3] gt 500)

RR = 1

else

RR = 0

讀取軌道黑白值 void IRread()

unsigned int position = qtrrcreadLine(sensorValues)

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 90: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

92

循軌處裡 void Tracking()

T_index = L10+Rswitch(T_index)case 00 出現00表示軌道上

MOTOR(100 100) 車子繼續前進

breakcase 01 MOTOR(0 100) 01 表示車子偏右 向左修正

delay(25)break

case 10 MOTOR(100 0) 10 表示車子偏左 向右修正

delay(25)break

case 11 MOTOR(100 100) 表示在軌道外或斷線區

break default MOTOR(100 100) 其他

break

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 91: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

路口處理 void Cross()R_index = LL10 + RR

switch(R_index)case 00 出現表示在十字路口或T字路口上

MOTOR(0 0) 目前不處理

breakcase 01 表示出現左轉路口向左轉90度

MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(220)MOTOR(-100 100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) | |(R ==1))MOTOR(0 0) delay(50) break

93

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 92: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

case 10 表示出現右轉路口向右轉90度MOTOR(100 100) 向前行35cm 讓車軸移動路口

delay(250)MOTOR(100 -100) 小S旋轉直到 L R 感測器出現訊號為止

doIRread()

while ((L == 1) ampamp (R == 1))MOTOR(0 0) delay(50) break

case 11 MOTOR(100 100) 表示在軌道上

break default

MOTOR(100 100) 其他

break

94

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 93: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

循軌處理理念

首先將(L R)的讀值先轉成 0 或 1接著經由 T_index = L10+R 的運算 用來產生

00 01 10 11 四種狀況

再運用 swtich case 處理就可以

轉彎處理理念 相同

轉彎處理必須注意之處

就是偵測到轉彎訊號時 不可以立刻轉彎 這樣會發生轉彎動作提前容易造成出軌現象

解決方案

讓車子再向前走一小段路確定車軸到轉彎處再進行轉彎這樣可確保轉彎不出軌

轉彎到什麼情狀為止 有兩種做法

1 設計控制轉彎 90度(有把握正確轉90度)2 轉彎後 偵測 L R 感測器出現訊號為止 (不用理會轉90度)

95

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 94: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

96

避障設計

許多車子競賽中都會出現避障設計 就是當車子遇到避障物時自行必須閃避過去然後再繼續前進這方面的處理必須考慮以下問題

1 先確定車子距離障礙物多遠是可以安全旋轉的距離

2 採取向右迴避或向左迴避 依實境來決定或建議向右迴避

3 常見迴避技巧有直角迴避三角迴避及圓弧迴避3種方法

96

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 95: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

討論直角轉法bull 由直角示意圖得知當車子準備

再度回到軌道時若出現車子與軌道呈現90度這很容易讓車子離開轉彎的程序後回到循軌程序時誤判為T字路口而出錯

bull 解決的方法就是不要讓車子垂直回到軌道因此最後一次轉彎時記得小於90度如中間圖示

bull 最佳方案就是靠近軌道時再反方向轉個角度讓車子與軌道的夾角小於45度為最安全的作法如下圖所示

97

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 96: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

98

三直角方式避障設計

車子先轉45度角前進一段距離再反方向轉90的方式來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉45度

3 前進(障礙物大小一半 + 安全值)x(radic3 ~2倍)的距離

4 小S向左轉90度

5 前進(障礙物大小一半 + 安全值x(radic3 ~2倍)的距離

6 小S向右轉45度 (注意車尾不要碰到障礙物)

98

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 97: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

99

圓弧方式避障設計

利用車輪的速度差來避障 遇到避障物可採取向右迴避或向左迴避以向右迴避為例

1 先確定車子距離障礙物是可以安全旋轉的距離

2 小S向右轉90度

3 MOTOR(20 100)

4 前進圓弧180度

5 小S向右轉90度(注意車尾不要碰到障礙物)

99

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 98: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

100

避障感測器介紹

bull 超音波

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 99: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

101

超音波發射接收原理

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 100: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

102

超音波測距原理

室溫(250C)超音波速度約為 v = 3465 ms

假設被測物距離為 d (m) 超音波測得時間為 t(S) 兩者關係為 d = v t 2 = 0017325 t(us) (cmus)

換算成 d = t(us)58 (cm us)

V air = 3315+ (06xTC) ms

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 101: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

103

超音波測距程式範例(Example 10)

定義 超音波 ultrasonic 參數

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

int distance 存放超音波所測得距離

void setup( ) Serialbegin(9600) 開啟監視視窗pinMode (echoPin INPUT) echo 回波為輸入訊號pinMode (trigPin OUTPUT) trig 觸發為輸出訊號

void loop( )distance = ultrasonic( ) 呼叫超音波測距函式Serialprintln(distance) 將超音波測得距離顯示在監視視窗上

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 102: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

104

int ultrasonic( )digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

int echo_times = pulseIn(echoPin HIGH 15000) 讀回波時間

int echo_distance = echo_times 58 計算與物件的距離

return echo_distance 將結果回送

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 103: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

程式說明

由於數位接腳幾乎被用光了只剩下D11準備留給開關使用由於超音波使用兩個接腳只好將類比接腳當成數位接腳來使用Arduino 允許將類比接腳當成數位接腳使用編號從14-19所以 echo 及 trigger 設定如下

define echoPin 14 超音波訊號回波 Pin (A0)define trigPin 15 超音波觸發 Pin (A1)

超音波觸發訊號需要一個脈衝形式輸出因此超音波副程式開頭設計

digitalWrite(trigPin LOW) trigPin 腳 low 5uSdelayMicroseconds(5)digitalWrite(trigPin HIGH) trigPin 腳 high 10uS delayMicroseconds(10)digitalWrite(trigPin LOW) trigPin 腳 low

105

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 104: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

至於如何接收超音波回波(echo)訊號Arduino 提供一個專門處理輸入脈波寬度的函式供設計者使用

pulseIn(輸入腳位 偵測準位(HIGH 或 LOW) 最長等待時間(us) )

若不寫最長等待時間則會自動補上1 秒鐘

echotimes = pulseIn(echoPin HIGH 15000) Read in times pulse

超音波測距的換算

distance= echotimes 58 Calculate distance from time of pulse

106

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 105: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

注意 副程式的一種型態不同於 (void setup( ) )int ultrasonic( ) 呼叫副程式處理完畢後將結果回傳

helliphelliphelliphelliphellipreturn distance

主程式方面

distance = ultrasonic( ) 呼叫超音波測距函式

107

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 106: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

108

完整的範例因為程式太長

請直接看 程式例介紹

避障方法研究(I) 採用直角轉彎避障方式 (Examlpe 11)

避障方法研究(II) 採用三角轉彎避障方式 (Examlpe 12)

避障方法研究(III) 採取繞圓弧避障方式 (Examlpe 13)

練習後將舉行簡單的競賽

祝福各位有好成績

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 107: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

範例說明超音波參數設定 ultrasonic define echoPin_C 14 Pin to receive echo pulse (A0)define trigPin_C 15 Pin to send trigger pulse (A1)define near_dis 348 658define far_dis 522 958

我們定義遇到障礙物的起轉點為超音波距離障礙物6-9cm

原本可以使用前一個例子的程式換算超音波測距

echotimes = pulseIn(echoPin HIGH 15000) distance= echotimes 58 return echo_distance 將結果回送

109

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 108: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

最大的問題是Arduino對於除法運算會耗費很多時間由於車子是一直在前進的因此會造成算出起轉點時車子又向前走一段了

為了減少超音波處裡時間就不計算距離了直接回傳超音波測得的時間

int echo_times = pulseIn(echoPin HIGH 15000) distance= distance58 return (echo_times )

起轉點偵測 void Obstacle()forward_distance = Ultrasonic_Scan(echoPin_C trigPin_C) if ((forward_distance gt near_dis) ampamp (forward_distance lt far_dis ))

ObstacleON()

110

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111
Page 109: Arduino車循線 避障 設計研習營web.ee.uch.edu.tw/attachments/article/178/2015_健行盃高中職循線及避障自走... · Arduino特定功能函式庫或外掛的函式庫,注意如下:

111

本次研習課程

到此告一個段落

感謝大家的堅持

祝福各位收穫滿滿

111

  • Arduino車循線避障設計研習營
  • 投影片編號 2
  • Arduino-微電腦控制板介紹
  • Arduino 軟體安裝
  • Arduino 官網
  • 下載Arduino 軟體
  • 投影片編號 7
  • 投影片編號 8
  • 解壓縮
  • Arduino 軟體
  • 啟動 Arduino
  • Arduino IDE
  • 中文畫面
  • Arduino USB
  • Arduino 初體驗
  • 投影片編號 16
  • 程式驗證
  • 程式上傳
  • 投影片編號 19
  • 投影片編號 20
  • 程式架構
  • 耶 我設計的第一個程式了(example_1)
  • 投影片編號 23
  • 連續旋轉型RC伺服馬達Continuous Rotation Servo Motor
  • 伺服馬達轉動特性
  • RC伺服馬達程式控制觀念
  • 伺服馬達轉速與脈波關係圖
  • 引用Arduino伺服馬達函式庫
  • 讓Arduino車乖乖聽話 (Example 2)
  • 說明
  • 投影片編號 31
  • 問題探討
  • Arduino 車靜止調整(Example 3)
  • 建立運動副程式
  • 設計自己的副程式
  • 設計副程式(續)
  • 設計副程式(續)
  • 設計副程式(續)
  • 建立運動副程式
  • Arduino車運行模式的討論
  • 建立所有運動副程式(Example 6)
  • 投影片編號 42
  • 投影片編號 43
  • 投影片編號 44
  • 馬達左右轉方式的討論
  • 投影片編號 46
  • 練習
  • 馬達控制 參數法 (Example 7)
  • 投影片編號 49
  • 投影片編號 50
  • 投影片編號 51
  • 投影片編號 52
  • Arduino車循軌及避障設計
  • Arduino 車基本參數
  • 投影片編號 55
  • 如何設計左轉90度(小S)
  • 投影片編號 57
  • 投影片編號 58
  • 認識循軌競賽
  • 認識比賽軌道
  • 循軌研究
  • 循軌感測器研究TQR-8RC 反射式感測陣列
  • 投影片編號 63
  • 認識感測器與循軌關係
  • 黑白校準
  • 什麼做黑白校準
  • 投影片編號 67
  • 建立TQR-8RC 函式庫範例
  • 使用 TQR-8RC函式庫 說明
  • 投影片編號 70
  • 對TQR-8RC進行校準(example 8)
  • 投影片編號 72
  • 投影片編號 73
  • 投影片編號 74
  • 投影片編號 75
  • 循軌設計
  • 兩個感測器循軌設計
  • 循軌設計
  • 循軌狀況討論
  • 路口狀況討論
  • 循軌狀況為4選一的情況
  • if 條件式組合成多選一的處理
  • if 條件式多選一處理範例
  • If else 條件式的多選一處理
  • Swtich case 的分岔(多選一)處理
  • 路口狀況 4選一的情況處理
  • Arduino車TQR-8RC紅外線感測器循軌設計(Example 9)
  • 投影片編號 88
  • 投影片編號 89
  • 投影片編號 90
  • 投影片編號 91
  • 投影片編號 92
  • 投影片編號 93
  • 投影片編號 94
  • 投影片編號 95
  • 避障設計
  • 討論直角轉法
  • 三直角方式避障設計
  • 圓弧方式避障設計
  • 避障感測器介紹
  • 超音波發射接收原理
  • 超音波測距原理
  • 超音波測距程式範例(Example 10)
  • 投影片編號 104
  • 程式說明
  • 投影片編號 106
  • 投影片編號 107
  • 投影片編號 108
  • 範例說明
  • 投影片編號 110
  • 投影片編號 111