Arduino Labs

Embedded System Knowledge

記憶體的種類

開關的上拉與下拉電阻

Labs

Lab 3-1 GPIO Output

將 Arduino pin 10 設為 OUTPUT (數位輸出)。將一顆 LED 如電路圖所示接上 pin 10 ,並寫程式讓 LED 每隔 0.5 秒閃爍一次

電路圖

程式碼

#define LED (10) #define DELAY (500) void setup() { // put your setup code here, to run once: pinMode(LED, OUTPUT); } void loop() { // put your main code here, to run repeatedly: digitalWrite(LED, HIGH); delay(DELAY); digitalWrite(LED, LOW); delay(DELAY); }

Lab 4-1 GPIO Input

Lab 4-1-1 Pull-down Resistor

電路圖

程式碼
#define SWITCH (2) #define LED (6) void setup() { // put your setup code here, to run once: pinMode(SWITCH, INPUT); pinMode(LED, OUTPUT); } void loop() { // put your main code here, to run repeatedly: bool inputVal = digitalRead(SWITCH); digitalWrite(LED, inputVal); }

Lab 4-1-2 External Pull-up Resistor

電路圖

程式碼

程式碼與 Lab 4-1-1 Pull-down Resistor 相同。

Lab 4-1-3 Internal Pull-up Resistor

啟用 Arduino 數位接腳的內建上拉電阻。根據 Atmel 公司的技術文件,此內建上拉電阻值為 20K歐姆 ~ 50K歐姆 間。內建上拉電阻預設沒有啟用,須將接腳設定為 INPUT_PULLUP ,才可啟用內建上拉電阻

電路圖

程式碼
#define SWITCH (2) #define LED (6) void setup() { // put your setup code here, to run once: pinMode(SWITCH, INPUT_PULLUP); pinMode(LED, OUTPUT); } void loop() { // put your main code here, to run repeatedly: bool inputVal = digitalRead(SWITCH); digitalWrite(LED, inputVal); }

Lab 4-2 Toggle LED

沿用 Lab 4-1-1 Pull-down Resistor 的硬體 電路 。將程式改為: 一開始 LED 滅。之後,按一下開關 LED 亮。再按一下開關 LED 滅。

程式碼

  • 全域變數
    ledStateprevSWState 為全域變數。
    ledState 負責記錄 LED 的狀態。初始值為 LOW ,也就是熄滅。
    prevSWState 負責記錄按鈕的前一個狀態。初始值為 RELEASED
    swState 負責記錄按鈕目前的狀態。初始值為 RELEASED
  • setup
    將 pin 6 (LED) 設定為 OUTPUT 。 pin 2 (SWITCH) 設定為 INPUT 。並且將 LED 設定為熄滅。
  • loop
    • 因為 Arduino 板子啟動並執行完 setup 後,會不斷地執行 loop ,所以 loop 不斷地讀入按鈕 (SWITCH) 的狀態 (即第 23 行的 digitalRead(SWITCH) )。若 digitalRead(SWITCH) 讀到的按鈕狀態為 HIGH (即按鈕被按下),則將 swStatePRESSED 。否則,將 swStateRELEASED
    • 假設此時按鈕被按下,第 24 行的敘述會被執行。所以 swState 會被設為 PRESSED
    • 接著第 29 行的 if 條件句成立, prevSWState 會被設定為 swState 的值,也就是 PRESSED
    • 由於此時按鈕仍為按下的狀態,所以第 33 行的 if 條件不成立。
    • 當按鈕被放開後,第 23 行讀到按鈕的狀態為 LOW ,所以第 26 行會被執行。 swState 被設定為 RELEASED
    • 因為此時 swStateRELEASED ,所以第 29 行的 if 條件句不成立,prevSWState 仍維持 PRESSED
    • 因為 swStateprevSWState 分別為 RELEASEDPRESSED ,所以第 33 行的 if 條件句成立。
      • ledState 的值被轉換成 HIGH 。 (第 34 行) 。然後將新的 LED 狀態寫入 LED (即 pin 6) ,點亮 LED。
      • 然後將 prevSWState 設為 RELEASED 。 所以下一個迴圈中 (假設按鈕沒有再被按下) ,第 33 行的 if 條件句不成立 (因為 swStateprevSwState 皆為 RELEASED)。進而維持 LED 被點亮的狀態。
    • 由上列敘述可知,LED 的狀態會在按鈕被釋放時進行轉換。
    • 當按鈕再次被按下,然後放開時,LED 就會熄滅。
#define SWITCH (2) #define LED (6) #define HIGH (1) #define LOW (0) byte ledState = LOW; byte prevSWState = LOW; byte swState = LOW; void setup() { // Setup the GPIO pins. pinMode(SWITCH, INPUT); pinMode(LED, OUTPUT); digitalWrite(LED, ledState); } void loop() { swState = digitalRead(SWITCH); if (swState) { prevSWState = swState; } if (swState != prevSWState) { ledState = !ledState; digitalWrite(LED, ledState); prevSWState = LOW; } }

用程式消除開關的彈跳現象

用上述的程式與電路實驗後發現,有時候會發生 LED 該熄滅的時候沒有熄滅,該點亮的時候沒有點亮。這是因為開關的彈跳現象造成的誤動作。可以用程式解決這個問題。
當 Arduino 偵測到開關被按下時,延遲 20 ms ,忽略掉那段訊號不穩定的時間後,再讀一次開關的狀態。確認開關真的被按下後,在進行狀態切換。

#define SWITCH (2) #define LED (6) #define HIGH (1) #define LOW (0) byte ledState = LOW; byte prevSWState = LOW; byte swState = LOW; void setup() { // Setup the GPIO pins. pinMode(SWITCH, INPUT); pinMode(LED, OUTPUT); digitalWrite(LED, ledState); } void loop() { swState = digitalRead(SWITCH); if (swState) { // Arduino detects that the button has been pressed. // To de-bounce, delay 20 ms. delay(20); // After 20 ms, read the button status again. // If the button status is still pressed, // the status of LED will be changed. byte swTmpState = digitalRead(SWITCH); if (swState == swTmpState) { prevSWState = swState; } } if (swState != prevSWState) { ledState = !ledState; digitalWrite(LED, ledState); prevSWState = LOW; } }

Lab 4-5 LED 跑馬燈

電路圖

程式碼

#define LED1 (2) #define LED2 (3) #define LED3 (4) #define LED4 (5) #define LED5 (6) const byte firstLed = LED1; const byte lastLed = LED5; byte currLed = firstLed; void setup() { // put your setup code here, to run once: for (int led = LED1; led <= LED5; ++led) { pinMode(led, OUTPUT); digitalWrite(led, LOW); } } void loop() { // put your main code here, to run repeatedly: digitalWrite(currLed, HIGH); delay(200); digitalWrite(currLed, LOW); if (currLed < lastLed) { ++currLed; } else { currLed = firstLed; } }

Lab 4-6 LED 來回跑馬燈

電路圖

沿用 Lab 4-5 LED 跑馬燈 的電路。

程式碼

#define LED1 (2) #define LED2 (3) #define LED3 (4) #define LED4 (5) #define LED5 (6) byte leds[] = {LED1, LED2, LED3, LED4, LED5}; byte numLeds = sizeof(leds) / sizeof(leds[0]); void setup() { // put your setup code here, to run once: for (int i = 0; i < numLeds; ++i) { pinMode(leds[i], OUTPUT); digitalWrite(leds[i], LOW); } } void loop() { for (int i = 0; i < numLeds - 1; ++i) { digitalWrite(leds[i], HIGH); delay(200); digitalWrite(leds[i], LOW); } for (int i = numLeds - 1; i > 0; --i) { digitalWrite(leds[i], HIGH); delay(200); digitalWrite(leds[i], LOW); } }

Reference

Block Circuit EDIT