單晶片lab5結報

tags: arduino
實驗日期 : 2021/10/21

上課教材

lab1

SPEC

使用超聲波模組搭配LCD顯示器與LED燈。

物體距離(cm) LCD第2行顯示
d<20
Distance : xx cm
d>20
Out of Distance
  • LCD第1行顯示{自己學號}
  • LED隨距離越近閃爍越快,5cm以下恆亮。

實現方法

pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);

定義trig為輸出,也就是MCU輸出並傳給超聲波模組HC-SR04的訊號;定義echo為輸入,也就是超聲波模組HC-SR04輸出傳給MCU接收的訊號。

digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

Trig高電位,持續10微秒。

duration = pulseIn(echoPin, HIGH);

參見Arduino官方doc,讀入echo腳位,如上值函數參數為HIGH,意思是當訊號HIGH時開始計時,等到回到LOW時,則回傳這段以microseconds(

μs)為單位的脈衝的時間長度。

接下來是物理計算,令溫度為

20C,換算為距離,最後再由LCD顯示。
distance=echo time (μs)2×(331.5+0.607×20)(100106cmms)

lab2

SPEC

使用超聲波模組搭配步進馬達。

物體距離(cm) 馬達運動
d<10
順時針旋轉
d>15
逆時針旋轉
d[10,15]
停止旋轉

激磁種類

單相激磁 (力矩小) 二相激磁 (力矩大) 一二相激磁 (力矩小)
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

ULN2003A功能

這個IC功能是控制哪個輸出接腳要接地。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

digitalWrite(8,1);
digitalWrite(9,0); 
digitalWrite(10,0); 
digitalWrite(11,0); 

例如上述程式是腳位8給高電位,其餘給低電位,對應到輸出為腳位8接地,其餘浮接。

實現方法

digitalWrite(8, 0);
    for (int j = 3; j >= 0; j--) {
        digitalWrite(j + 8, 1);
        if (j != 3) digitalWrite(j + 1 + 8, 0);
        delay(3);
    }

使用單相激磁,經實測,順時針的激磁順序是腳位11到腳位8,逆時針則為相反。由於外圍定子的激磁需要時間來讓轉子轉到指定方向,因此需要加上3毫秒的延遲。

lab3

SPEC

判斷按鈕狀態,反應於步進馬達與LCD顯示器。

按鈕 馬達運動
按鈕A按1下 順時針旋轉
90
按鈕A長按3秒以上 順時針旋轉
360
按鈕B按1下 逆時針旋轉
180
按鈕B長按3秒以上 逆時針旋轉
120
  • LCD第1行顯示{自己學號},第2行顯示Steps : {步數}(計算所需角度得步數)。

實現方法

  1. 判斷按鈕按壓狀況
//press == LOW for pull-up resistor
while (button_A == LOW) { 
    delay(50);
    button_A = digitalRead(button_A_pin);
    //counter
    if (millis() - timer > 1000) {
        number++;
        timer = millis();
    }

    //press for 500ms
    if (button_A == HIGH) {
        rotate(true, 90);
        break;
    }

    //press for 3 seconds
    if (button_A == LOW && number > 2) {
        rotate(true, 360);
        break;
    }
}

lab1 lab2-1實現方法,上拉電阻當按鈕按下為LOW,進入while迴圈,先delay(50)以解決機械按鈕de-bouncing的問題,接下來再次讀值並啟動計時器,一旦button_A == HIGH也就是未按按鈕,即判斷為"按1下",否則在持續按壓下且秒數到2秒,再加上delay()造成時間,差不多3秒後就判斷為"長按3秒以上"。

  1. 控制步進馬達28BYJ-48轉動
void rotate(bool clockwise, int degree);

包成一個副程式,前者為順、逆時針,後者為轉動角度。主要關鍵是求出要旋轉的角度對應所需的步數兩者之間關係。


  • 28BYJ-48規格表
item value
Rated voltage 5VDC
Number of Phase 4
Speed Variation Ratio 1/64
Stride Angle 5.625° /64
Frequency 100Hz

知道步進角度是

5.625度,馬達變速比(輸入/輸出)是1:64。意思就是給28BYJ-48發送一個脈衝訊號,馬達旋轉
5.62564
,而馬達旋轉一圈是
360
度,因此需要
3605.63564=4096
個脈衝信號,也就是說轉一圈總共是
4096
個step。但我們是採用單相激磁,轉一圈所需步數為一二相激磁的一半,故還需要除以2

float step = degree * 5.68888;  
//1 dregree = 2048/360 = 5.68888 step

由於多項式運算實測計算錯誤,也抓不出原因,故上面程式已將分數計算完的結果化為小數。

for (int i = 0; i < step/4; i++) {
    /*lab2 實現方法*/
}

激磁一次稱為一步,轉子轉一圈則需四步。

lab4

SPEC

利用按鈕控制步進馬達旋轉角度。

按鈕 馬達旋轉角度
按1下
90
快速按2下
120
快速按3下
180
長按3秒
360

實現方法

if (button_state == LOW && before_state == HIGH) {
    press_count++;
    if (press_count == 1) {
        timer = millis();
        while (button_state == LOW) {}
    }
}

//1秒後timeout,開始計算結果
if (millis() - timer > 1000 && press_count > 0) {
    if (press_count == 1) {
        /*reaction of LCD and motor*/
    } 
    else if (press_count == 2) {
        /*reaction of LCD and motor*/
    }
    else if (press_count == 3) {
        /*reaction of LCD and motor*/
    }
    else {
        /*exception*/
    }
    press_count = 0; //initialization
    }

當按下按鈕開始計時,若還是繼續長按,進入while迴圈數到3秒即觸發"長按3秒"。否則當時間經過1秒且按壓累計次數大於0次的情況下,會統計資料並使LCD與步進馬達運作,有3種預期的可能分別為"按1下"、"快速按2下"、"快速按3下"。

課後習題

Question 1

詳述超聲波模組HC-SR04感測原理。

Answer 1

紀錄訊號從輸出至反射所需的總時間,再經由物理運算即可量測距離。

由輸入模組訊號trig與輸出模組訊號echo所構成,一開始Arduino發送給trig腳位由1->0,發射器發出840KHz方波,而旁邊的接受器會先受到影響,將echo0->1。方波經由物體反射後,接收器接收到回傳波形,再將echo腳位由1->0,因此可計算echo處於high level的時間,即為訊號來回所需的時間。

距離計算公式為

L=echo time2×(speed of sound)where speed of sound is (331.5+0.607×temp in Celsius)

Question 2

詳述步進馬達28BYJ-48運作原理。

Answer 2

運用電磁感應,轉動轉子,轉子再帶動齒輪來改變轉向和增加轉矩。

其內部構造可分為定子、轉子,外圍四個定子上纏繞線圈以生成磁場,磁場感應中間轉子產生磁力,藉由調整外圍定子的激磁順序來控制中間轉子的轉向

本次實驗的馬達內部由四個定子組成,依序對四個定子激磁,即可讓內部轉子轉動。激磁一次稱為一步,轉子轉一圈則需四步。因為齒輪比的關係,轉子轉1024圈,馬達則轉動一圈,因此共需4096步,馬達才可轉動360度。

Question 3

詳述步進馬達會因程式內容導致轉速變慢,此問題該如何處理。

Answer 3

若使用delay()來控制步進馬達的激磁順序,可能受到其他區塊的程式碼影響造成delay()增加。若要改善此狀況,需要以non-blocking的方式來編程。

  1. 使用millis()來追蹤時間,若時間到則觸發你要執行的動作。
  2. 直接使用別人寫好的函式庫<arduino-timer.h>,如下方LED閃爍程式,每隔1秒會自行開關且不受delay()影響。
#include <arduino-timer.h>

auto timer = timer_create_default();  // create a timer with default settings

bool toggle_led(void *) {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));  // toggle the LED
    return true;                                           // keep timer active? true
}

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);  // set LED pin to OUTPUT
    // call the toggle_led function every 1000 millis (1 second)
    timer.every(1000, toggle_led);
}

void loop() {
    timer.tick();  // tick the timer
}

心得

劉永勝

這次實驗是透過程式來控制馬達的轉動和用超音波測量距離。這兩樣模組的運作原理在之前其他課程就已熟悉,為了達成運作,需依序對特定腳位讀出、輸入。

  • 超音波模組
    需間隔一段時間再發送8個高頻方波,以確保訊號已經完成來回,若發送間格太短的話,則無法測量實際距離。
  • 步進馬達
    先了解馬達轉動一圈後,需要激磁的次數,再決定激磁方式以配合馬達所需的扭力。

李宇洋

沒有搞懂助教講義,所以不知道馬達的一個step是轉一圈還是轉90度,因此步進馬達的實驗部分卡住。此外,馬達旋轉帶動齒輪我個人理解有問題,導致其實很簡單的lab2沒有很快做完。原本以為馬達會因為磁極的瞬間改變導致轉動位置直接被更改,因此還多想了要用一個暫存器記住位置,但是經助教提點後,才知道因為多個齒輪帶動轉動的關係,因此只會看磁極旋轉的方向帶動轉子旋轉方向,不會瞬間改變轉子的位置。

陳旭祺

這次實驗熟悉2個常見的模組與按鈕判定,原理為高中物理內容。

  • 超音波模組HC-SR04
    利用兩個訊號的間隔得時間,再由聲速公式推算實際距離。
  • 步進馬達28BYJ-48
    使用ULN2003A控制哪個輸出接腳要接地。計算出旋轉的角度mapping到所需步數

    如這篇教學Control 28BYJ-48 Stepper Motor with ULN2003 Driver & Arduino,也可以使用函式庫<Stepper.h>,有成員函數方便直接調用。
    • 設定轉速setSpeed(long rpms)
    • 設定每分鐘轉速step(int steps)(負值為逆時針轉動)
  • 按鈕判定
    包兩層迴圈,判斷按下後,再繼續長按的狀況,需要用到秒數就用millis()當計數器,而lab4題目關於"快速按"較主觀的功能要求,我是限定使用者只能在1秒內按完做為實作。