基本功能:

  • 长按控制按钮开机,长按控制按钮关机(>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)

  • 没有使用下拉电阻的情况

  

python调光台灯arduino 基于arduino的智能调光台灯_下拉电阻

  • 按键没有按下时,要读取的输入引脚什么也没有接——这个输入引脚被称为“悬空”。由于这个引脚没有实际地接到0V或者5V,读取它时会导致意料之外的结果,因为附近的电气噪声会导致其值在高低电平之间来回波动。
  • 下拉电阻:将输出端拉一根导线连接到地

  

python调光台灯arduino 基于arduino的智能调光台灯_引脚_02

  上拉电阻:将输出端拉一根导线连接到电源

   

python调光台灯arduino 基于arduino的智能调光台灯_sed_03

  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()的时候是不能做其它工作的。

电路图:

  

python调光台灯arduino 基于arduino的智能调光台灯_下拉电阻_04

完整源代码:

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 }

 实验截图:

  自己设计完成的第一个小项目,留两张照片记录一下吧~

  

python调光台灯arduino 基于arduino的智能调光台灯_引脚_05

         

python调光台灯arduino 基于arduino的智能调光台灯_引脚_06