--- tags: 單晶片助教 --- # [6] Arduino講義:超音波&步進馬達(TA版) [ToC] ## 超音波感測器(Ultrasonic sensor) * 超音波模組工作原理: ![](https://i.imgur.com/ODTMfKF.png) * 觸發 : 採用I/O觸發測距,給至少為 <font color="red">10us</font> 的高電位信號。 * 發射 : 模組自動發送 8 個 40KHz 的方波,自動檢測是否有信號返回。 * 接收 : 有信號返回,通過模組之 I/O 輸出高電位,<font color="red">高電位持續的時間</font>就是超聲波 從發射到返回的時間。 ![](https://i.imgur.com/qci8enf.png) * 距離計算 = (高電位時間 / 2) * 聲速 。 * 讀取高電位時間 : 使用 <font color="red">pulseIn( )</font> 此Function,單位為microsecond(µs)。 * Reference: [Arduino pulseln()](https://www.arduino.cc/en/Reference.PulseIn) * 聲速 = 331.5 + 0.607 * t(攝氏溫度)。 Ex : 溫度為攝氏 20 度,則聲速為 331.5 + 0.607 * 20 = 343.64 m/s。 * 將聲速還算成 cm/µs => 343.64 * 100 / 1000000 = 0.034364 cm/µs。 * 超音波模組規格與腳位 : * 電源需求 : DC 5V / 2mA * 輸出電位( 1/ 0):5V/ 0V * 精度:3mm * <font color="red">距離範圍:2 ~ 450cm</font> * 有效的角度:<15℃ ![](https://i.imgur.com/LWgbM7Z.png) * 超音波使用須知 * 不可少於2公分 ![](https://i.imgur.com/z9utTOL.jpg) * 每次訊號間隔不可太短 ![](https://i.imgur.com/B5eTjnD.png) * 待測物注意反射角度 ![](https://i.imgur.com/6CxZFXd.jpg) * 待測物圓柱體時反射角度較廣 ![](https://i.imgur.com/Rv82yzQ.png) ### Lab1-1 - 超聲波測距器+7段顯示 #### 實作說明: * 實作目的 : 學習使用超聲波模組以及7段顯示器之應用。 * 實作範例 : 使用超聲波模組搭配 LCD 顯示器與7段顯示器,將超音波感測器讀取到之數值換算成距離顯示在7段顯示器上。顯示整數需能支援百位數,小數則需顯示到小數點第一位。 * Ex:測得距離=20.3cm,7段顯示器顯示"020.3"。 * Ex:測得距離=115cm,7段顯示器顯示"115.0"。 * <font color="red">Hint : round()函式</font> * 實作腳位配置 : | HC-SR04 | Arduino | LCM 1602 |Arduino| | -------- | -------- | -------- | -------- | | Vcc | 5V | GND | GND | | Trig | Pin12(可自行決定) | Vcc | 5V | | Echo | Pin11(可自行決定) | SDA | A4 | | Gnd | GND | SCL | A5 | * 實作影片 : {%youtube Oac_2GWuUnU %} ```c= const int SEG_COM[4] = {A0,A1,A2,A3}; //控制線 const int SEG_data[10][7] = {{1, 1, 1, 1, 1, 1, 0}, //"0" //資料線 {0, 1, 1, 0, 0, 0, 0}, //"1" {1, 1, 0, 1, 1, 0, 1}, //"2" {1, 1, 1, 1, 0, 0, 1}, //"3" {0, 1, 1, 0, 0, 1, 1}, //"4" {1, 0, 1, 1, 0, 1, 1}, //"5" {1, 0, 1, 1, 1, 1, 1}, //"6" {1, 1, 1, 0, 0, 0, 0}, //"7" {1, 1, 1, 1, 1, 1, 1}, //"8" {1, 1, 1, 0, 0, 1, 1}}; //"9" int echoPin = 11; //Echo Pin int trigPin = 12; //Trig Pin float cm; float duration; float soundspeed=0.034; void setup() { Serial.begin (9600); // Serial Port begin for(int i=2; i<=9; i++){ pinMode(i, OUTPUT); digitalWrite(i, HIGH); //共陽極 } for(int i=0; i<=3; i++){ pinMode(SEG_COM[i], OUTPUT); digitalWrite(SEG_COM[i], HIGH); //共陽極 } pinMode(trigPin, OUTPUT); // 定義輸入及輸出 pinMode(echoPin, INPUT); } void loop() { // To do:給 Trig 高電位,持續 10微秒 duration = pulseIn(echoPin, HIGH); // 收到高電位時的時間 //To do:算出距離 //To do:顯示在7段顯示器 } void SEG_Drive(int number){ //將字元變數從SEG_data[][]找到相對應的位置,並寫入a~g中 for(int i=0;i<=6;i++) { //To do:輸出至7段顯示器 } } ``` ### Lab1-2 - 測距控制LED燈閃爍 #### 實作說明: * 實作目的 : 學習透過距離控制LED燈閃爍。 * [下載LCD_I2C模組程式庫](https://github.com/johnrickman/LiquidCrystal_I2C) * 實作範例 : 使用超聲波模組搭配三科LED燈。 * 當物體距離 0~20 公分時,一號LED隨距離愈近閃爍越快,距離愈遠閃爍愈慢。 * 當物體距離 20~40 公分時,二號LED隨距離愈近閃爍越快,距離愈遠閃爍愈慢。 * 當物體距離 40~60 公分時,三號LED隨距離愈近閃爍越快,距離愈遠閃爍愈慢。 * 當物體距離 >60 公分時,三顆LED均熄滅。 * 實作影片 : {%youtube 5c6yjdvmGk0 %} ```c= #include <Wire.h> #include <LiquidCrystal_I2C.h> #define led1 3 #define led2 4 #define led3 5 int trigPin = 12; int echoPin = 11; LiquidCrystal_I2C lcd(0x27, 16, 2); float duration; int cm; float soundspeed=0.034; void setup() { Serial.begin (9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(led1,OUTPUT); digitalWrite(led1, LOW); pinMode(led2,OUTPUT); digitalWrite(led2, LOW); pinMode(led3,OUTPUT); digitalWrite(led3, LOW); lcd.init(); lcd.backlight(); } void loop() { // ex.給 Trig 高電位,持續 10微秒 duration = pulseIn(echoPin, HIGH); //To do : 算出距離 if(cm>0 && cm<=20) { //To do } else if(cm>20 && cm<=40) { //To do } else if(cm>40 && cm<=60) { //To do } else if(cm>60) { //To do } //To do : 顯示距離於lcd上 } ``` ## 步進馬達(Stepping motor) * 步進馬達工作原理: 由電流通過線圈激磁後,使得線圈產生磁場(電磁鐵)吸引中間轉子磁鐵轉動,所以若要控制馬達旋轉,需控制好線圈的激磁順序。 * <font color="red">紅色線</font>:電源線供給馬達電力。 * <font color="blue">藍色線</font>:線圈。 * <font color="pink">粉色線</font>:線圈。 * <font color="FFDD00">黃色線</font>:線圈。 * <font color="Orange">橘色線</font>:線圈。 ![](https://i.imgur.com/XQmFqWY.jpg) * 步進馬達規格 : * 額定電壓:5 VDC * 相數:4 * 變速比:64/1 圈 (輸入/輸出) ( 1 : 9,2 : 32/11,3 : 22/9,4 : 27/8,5 : 24 )(齒輪比) ![](https://i.imgur.com/JJ7us5I.jpg) * 步進角度:5.625度 藉由以上數據可得知 輸出的轉速(度) = 主軸轉速(度) x 9/32 x 11/22 x 9/27 x 8/24 = 主軸轉速(度) x 1/64 假設馬達步進角為5.625度 x 1/64 = 0.087890625度 所以若要轉一圈,則需360/0.087890625 = 4096步 經過角度與步數的運算,馬達就可以依需求來做控制。 * 步進馬達控制方法 : * 單相激磁(優點:省電,缺點:力矩小) ![](https://i.imgur.com/epLYANa.jpg) * 二相激磁(優點:力矩大,缺點:耗電) ![](https://i.imgur.com/ZnlY9Zc.jpg) * 一二相激磁(優點:省電,缺點:力矩小) ![](https://i.imgur.com/madKBT0.jpg) <font color="blue">hint</font> : 一二相與單相二相差異點為輸出所需的步數,假設一二相所需一圈為4096步,那單相與二相就只需2048步,由此可知,一二相可做到較精準的角度控制。 * ULN2003A驅動IC : ![](https://i.imgur.com/g4J3dzs.jpg) 此IC特點在於,透過控制數位訊號來控制哪個輸出接腳要接地。 ### Example ```c= //單相激磁 int t= 10; //換相所需的時間 void setup() { pinMode(7,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(10,OUTPUT); } void loop() { digitalWrite(7,1); digitalWrite(8,0); digitalWrite(9,0); digitalWrite(10,0); delay(t); digitalWrite(7,0); digitalWrite(8,1); digitalWrite(9,0); digitalWrite(10,0); delay(t); digitalWrite(7,0); digitalWrite(8,0); digitalWrite(9,1); digitalWrite(10,0); delay(t); digitalWrite(7,0); digitalWrite(8,0); digitalWrite(9,0); digitalWrite(10,1); delay(t); } ``` ### Lab2-1 - 步進馬達角度控制 #### 實作說明: * 實作目的 : 學習控制步進馬達轉動角度。 * 實作範例 : 使用步進馬達搭配 LCD 顯示器與按鈕。 按鈕A:按1下時,馬達逆轉90度;長按2秒以上,馬達逆轉720度。 按鈕B:按1下時,馬達順轉180度;長按2秒以上,馬達順轉135度。 LCD第一行顯示自己學號,第二行顯示"Steps : 步數"。 hint : 必須確實計算所需角度得步數 * 實作影片 : {%youtube lKkT2FSfM8Q %} ```c= //0.17578125 //8192 2048 1536 1024 //720 180 135 90 #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); int t = 1000; int Count ; int but[2] = {3, 4}; int state1[5] = {1,1,1,1,1}; int state2[5] = {1,1,1,1,1}; boolean a[] = {1, 1, 0, 0, 0, 0, 0, 1}; boolean b[] = {0, 1, 1, 1, 0, 0, 0, 0}; boolean c[] = {0, 0, 0, 1, 1, 1, 0, 0}; boolean d[] = {0, 0, 0, 0, 0, 1, 1, 1}; void setup() { Serial.begin(9600); lcd.init(); //初始化LCD lcd.backlight(); //開啟背光 pinMode(7,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(10,OUTPUT); pinMode(but[0],INPUT_PULLUP); pinMode(but[1],INPUT_PULLUP); } void loop() { int IN1 = digitalRead(but[0]); int IN2 = digitalRead(but[1]); Count = 0; if (state1[0] == 0 && state1[1] == 0 && state1[2] == 0 && state1[3] == 0 && state1[4] == 0 && IN1==1) { mode720(); } else if (state1[4] == 0 && IN1==1) { mode90(); } if (state2[0] == 0 && state2[1] == 0 && state2[2] == 0 && state2[3] == 0 && state2[4] == 0 && IN2==1) { mode135(); } else if (state2[4] == 0 && IN2==1) { mode180(); } delay(??); //To do:該怎麼delay才能達到計時2秒的效果? for(int i=0;i<=3;i++) { state1[i] = state1[i + 1]; state2[i] = state2[i + 1]; } state1[4] = IN1; state2[4] = IN2; } void mode90() { for (int j = 0; j < 128 ; j++) { for (int i = 0; i < 8 ; i++) { digitalWrite(7, a[i]); digitalWrite(8, b[i]); digitalWrite(9, c[i]); digitalWrite(10, d[i]); delayMicroseconds(t); Count++; } } lcd.clear(); lcd.print("M16121051"); lcd.setCursor(0, 1); lcd.print("Steps : "); lcd.print(Count); } void mode135() { // To do } void mode180() { // To do } void mode720() { // To do } ``` ### Bonus - 超音波+按鈕控制步進馬達 #### 實作說明: * 實作目的 : 學習更加進階之步進馬達控制。 * 實作範例 : 利用超音波量得距離控制步進馬達旋轉速度及方向。 * 預設馬達逆時針轉動,當按下按鈕時變順時針運轉,再按一次逆時針,以此類推。 * 物體距離愈遠馬達旋轉愈慢,距離愈近旋轉愈快。 * 需在LCD上第一列顯示clockwise或counterclockwise,第二列顯示距離(cm)。 * 參考影片 : {%youtube 7LeSqDdeqcI %} ## 課後問題 (三題) :::info * Q1.詳述 超聲波模組感測原理。 * Q2.詳述 步進馬達動作原理。 * Q3.請列舉 3 個超音波感測器在現實生活中之應用。並詳述你列舉的應用如何使用超音波感測器收集到的資訊。 回答請勿直接複製上述講義內容! ::: Arduino *1 超音波感測器 *1 步進馬達+ULN2003AN驅動板 *1 LCD *1 LED燈 *3 按鈕 *2 電阻10K歐姆 *2