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


基本功能:

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

元器件清單:

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

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

  1. 脈沖寬度調制(P25 - P27)

  • PWM的輸出可以寫入數值的范圍:0~255
  • PWM的工作原理:方波(占空比的概念)
  • “你並沒有改變輸送到LED的電壓,為何又能在降低占空比時讓LED變暗呢?......如果LED每1ms就開關一次,它看起來就是近乎一半的亮度,這是因為它閃爍的速度超過了人眼能察覺的速度。因此,大腦實際上時平均了這個信號,並欺騙你相信這個LED只有一半的亮度。”

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

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

  

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

  

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

   

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

 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:

  這里的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 }

 實驗截圖:

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

           

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM