【Arduino學習筆記05】Arduino數字輸入、輸出和脈衝寬帶調製 -- 小項目:彩色小檯燈

基本功能:

  • 長按控制按鈕開機,長按控制按鈕關機(>3s)
  • 經過三個調節按鈕調節燈的顏色,每個按鈕分別對應R,G,B值
  • 模式切換:短按控制按鈕切換模式(長亮模式/閃爍模式)

元器件清單:

  • Arduino Uno R3
  • 小號麪包板
  • 跳線
  • 10kΩ 電阻(×4)
  • 220Ω 電阻(×3)
  • USB電纜
  • 按鍵 (×4)
  • 5mm 共陰極 RGB LED

知識回顧:(參考書目《Arduino魔法書》)

  1. 脈衝寬度調製(P25 - P27)git

  • PWM的輸出能夠寫入數值的範圍:0~255
  • PWM的工做原理:方波(佔空比的概念)
  • 「你並無改變輸送到LED的電壓,爲什麼又能在下降佔空比時讓LED變暗呢?......若是LED每1ms就開關一次,它看起來就是近乎一半的亮度,這是由於它閃爍的速度超過了人眼能察覺的速度。所以,大腦實際上時平均了這個信號,並欺騙你相信這個LED只有一半的亮度。」

  2. 上拉電阻和下拉電阻(P28 ~ P30)函數

  • 沒有使用下拉電阻的狀況

  

    • 按鍵沒有按下時,要讀取的輸入引腳什麼也沒有接——這個輸入引腳被稱爲「懸空」。因爲這個引腳沒有實際地接到0V或者5V,讀取它時會致使意料以外的結果,由於附近的電氣噪聲會致使其值在高低電平之間來回波動。
  • 下拉電阻:將輸出端拉一根導線鏈接到地

  

  上拉電阻:將輸出端拉一根導線鏈接到電源oop

   

  3. 按鈕的消抖動(P30 ~ P33)ui

 1 /*
 2  * 消抖動函數:
 3  * button: 要消抖動的按鈕
 4  * last: 該按鈕的上一個狀態
 5  * 返回值:消抖動後讀回的按鈕狀態
 6 
 7   * - 這裏所謂的消抖動,實際上就是若是檢測到電壓變化後先不操做,由於多是抖動階段的
 8   * 電壓改變,等5m以後再讀取當前值,避開抖動階段。
 9   * - 若是沒有使用消抖動函數,在抖動的過程當中電壓屢次變化,會獲得不少次「按鈕按下」的
10   * 結論,從而形成短期內頻繁的開燈關燈。
11 */
12 boolean debounce(int button, boolean last) {
13     boolean current = digitalRead(button);
14     if (last != current) {
15         delay(5);
16         current = digitalRead(button);
17     }
18     return current;
19 }

  4. BlinkWithoutDelay:spa

  這裏的bilink借鑑的是examples中的BlinkWithoutDelay.ino中的blink方法,這種寫法容許在blink的同時作其它工做。好比:讀取按鈕的輸入等。可是若是使用的是Blink.ino中的寫法,在delay()的時候是不能作其它工做的。設計

電路圖:

  

完整源代碼:

  1 /* 彩色小檯燈
  2 
  3  * 基本功能:   長按控制按鈕開機,長按控制按鈕關機(>3s);
  4                         經過三個調節按鈕調節燈的顏色,每個按鈕分別對應R,G,B值;
  5                         模式切換:短按控制按鈕切換模式(長亮模式/閃爍模式)
  6 
  7  * 做者:Shadow
  8  * 時間 : 2020/09/08
  9  */
 10 
 11 const int BLED = 9;
 12 const int GLED = 10;
 13 const int RLED = 11;
 14 
 15 const int R_BUTTON = 2;
 16 const int G_BUTTON = 3;
 17 const int B_BUTTON = 4;
 18 
 19 // 用來記錄當前燈顏色對應的RGB值
 20 int R = 0;
 21 int G = 0;
 22 int B = 0;
 23 
 24 // lastButton_X是按鈕的上一個狀態;currentButton_X是按鈕的當前狀態
 25 // 這裏所講的按鈕狀態其實是指按鈕所鏈接的引腳讀入的電平值是HIGH仍是LOW
 26 // 用來輔助實現按鈕消抖函數debounce()
 27 boolean lastButton_R = LOW;
 28 boolean currentButton_R = LOW;
 29 boolean lastButton_G = LOW;
 30 boolean currentButton_G = LOW;
 31 boolean lastButton_B = LOW;
 32 boolean currentButton_B = LOW;
 33 
 34 // 輔助實現blink()函數的變量
 35 int ledState = LOW;                      // 記錄LED燈的當前狀態,LOW: dark; HIGH: light
 36 unsigned long previousMillis = 0;        // will store last time LED was updated
 37 const long interval = 500;               // interval at which to blink (milliseconds)
 38 
 39 // 與控制按鈕相關的變量
 40 const int MODE_BUTTON = 6;
 41 int mode = 0;                            // 0: 關機; 1: 長亮; 2: blink
 42 boolean lastButton_mode = LOW;
 43 boolean currentButton_mode = LOW;
 44 
 45 void setup()
 46 {
 47     pinMode(BLED, OUTPUT);
 48     pinMode(GLED, OUTPUT);
 49     pinMode(RLED, OUTPUT);
 50     pinMode(R_BUTTON, INPUT);
 51     pinMode(G_BUTTON, INPUT);
 52     pinMode(B_BUTTON, INPUT);
 53     pinMode(MODE_BUTTON, INPUT);
 54 }
 55 
 56 /*
 57  * 消抖動函數:
 58  * button: 要消抖動的按鈕
 59  * last: 該按鈕的上一個狀態
 60  * 返回值:消抖動後讀回的按鈕狀態
 61 */
 62 boolean debounce(int button, boolean last) {
 63     boolean current = digitalRead(button);
 64     if (last != current) {
 65         delay(5);
 66         current = digitalRead(button);
 67     }
 68     return current;
 69 }
 70 
 71 // light the led
 72 void light() {
 73     analogWrite(RLED, R);
 74     analogWrite(BLED, B);
 75     analogWrite(GLED, G);
 76 }
 77 
 78 // turn off the led
 79 void dark() {
 80     digitalWrite(RLED, LOW);
 81     digitalWrite(BLED, LOW);
 82     digitalWrite(GLED, LOW);
 83 }
 84 
 85 // blink
 86 void blink() {
 87     // 這裏的bilink借鑑的是examples中的BlinkWithoutDelay.ino中的blink方法,這種寫法容許在blink的同時作其它工做
 88     // 好比:讀取按鈕的輸入等。可是若是使用的是Blink.ino中的寫法,在delay()的時候是不能作其它工做的。
 89     unsigned long currentMillis = millis();
 90 
 91     if (currentMillis - previousMillis >= interval) {
 92         // save the last time you blinked the LED
 93         previousMillis = currentMillis;
 94 
 95         // if the LED is off turn it on and vice-versa:
 96         if (ledState == LOW) {
 97             ledState = HIGH;
 98             light();
 99         }
100         else {
101             ledState = LOW;
102             dark();
103         }
104 
105     }
106 }
107 
108 void loop()
109 {
110     // Step1: check the current mode 
111     if (mode == 0)
112     {
113         dark();
114     }
115     else if (mode == 1) {
116         light();
117     }
118     else {
119         blink();
120     }
121         
122 
123     // Step2: change the color if some buttons were pressed
124     // read the current state of buttons
125     currentButton_R = debounce(R_BUTTON, lastButton_R);
126     currentButton_G = debounce(G_BUTTON, lastButton_G);
127     currentButton_B = debounce(B_BUTTON, lastButton_B);
128 
129     // if button is pressed, change the related rgb value
130     if (lastButton_R == LOW && currentButton_R == HIGH) {
131         // button_R is pressed
132         R += 5;
133         if (R == 260)
134             R = 0;
135     }
136     if (lastButton_G == LOW && currentButton_G == HIGH) {
137         // button_G is pressed
138         G += 5;
139         if (G == 260)
140             G = 0;
141     }
142     if (lastButton_B == LOW && currentButton_B == HIGH) {
143         // button_B is pressed
144         B += 5;
145         if (B == 260)
146             B = 0;
147     }
148 
149     // update last state of each button
150     lastButton_R = currentButton_R;
151     lastButton_G = currentButton_G;
152     lastButton_B = currentButton_B;
153 
154     //Step3: change the mode if mode_button is pressed, turn on or off if mode_button is pressed more than 3 seconds
155     currentButton_mode = debounce(MODE_BUTTON, lastButton_mode);
156     if (lastButton_mode == LOW && currentButton_mode == HIGH) {
157         // button_mode is pressed, start timing
158         unsigned long pressMillis = millis();
159         unsigned long releaseMillis = millis();
160         while (digitalRead(MODE_BUTTON) == HIGH) {
161             releaseMillis = millis();
162         }
163         // button_mode is released, record the period from press to release
164         unsigned long periodMillis = releaseMillis - pressMillis;
165 
166         if (periodMillis > 3000 && mode != 0) {
167             mode = 0;
168         }
169         else if (periodMillis > 3000 && mode == 0) {
170             // if the previous state is dark, then light
171             mode = 1;
172         }
173         else if (mode == 1) {
174             mode = 2;
175         }
176         else {
177             mode = 1;
178         }
179     }
180 
181 }

 實驗截圖:code

  本身設計完成的第一個小項目,留兩張照片記錄一下吧~blog

           

相關文章
相關標籤/搜索