任务内容:
两个按键A、B,A 按下小灯变亮一点,B 按下小灯变暗一点。
知识准备
· 按键防抖
机械式开关在切换过程中,电子信号并非立即从 0 变成 1( 或从 1 变成 0 ),而会经过短暂的,像下图一样忽高忽低变化的弹跳现象。虽然弹跳动作的时间非常短暂,但微电脑仍将读取到连续变化的开关信号,导致程序误操作。
为了避免上述状况,读取机械式开关信号时,程序(或者硬件)需要加入所谓的**消除弹跳 ( de-bouncing ) **处理机制。最简单的方式,就是在发现输入信号变化时,先暂停 10~30毫秒,然后再读取一次,以便确定输入值。
代码示例:
如下图所示,在 “单击” 操作中,信号改变了两次。
那么我们可以声明一个 click 的变量,记录信号改变的次数,每当此变量值为 2 ,代表按了一下按钮。具备 “ 过滤 ” 弹跳信号的开关代码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| const byte LED = 13; const byte SW = 2; boolean lastState = LOW; boolean toggle = LOW; byte click = 0;
void setup() { pinMode(LED, OUTPUT); pinMode(SW, INPUT); lastState = digitalRead(SW); }
void loop() { boolean b1 = digitalRead(SW); if (b1 != lastState) { delay(20); boolean b2 = digitalRead(SW); if (b1 == b2) { lastState = b1; click++; } } if (click == 2) { click = 0; toggle = !toggle; digitalWrite(LED, toggle); } }
|
loop() 区块不停地读取开关的值,并且对比开关的信号是否和上一次不同。假如监测到开关的信号改变了,要等待 20 毫秒之后,再确认一次开关值。如果等待20毫秒后读取到的开关信号值和上一次读取到的一致,就确认开关的状态真的改变了。
· 开关的接法(上拉电阻 & 下拉电阻)
Arduino 的所有数字和模拟引脚都能读取 / 输出 0 与 1 信号。只要输入值超过电源电压的一半,就代表高电压高电位;若输入值低于 0.25V,则代表低电位。
这样的开关接法并不正确:
若没有按下开关,Arduino 的引脚既没接地接地,也为接到高电位。输入信号可能在 0 与 1 之间的模糊地带漂移,造成所谓的浮动信号,Arduino 将无法正确判断输入值。
正确接法如下:
若开关没有被按下,数字第 2 脚将通过 10kΩ 接地,因而读取到低电位值;按下开关时,5V 电源将流入第 2 脚,产生高电位。如果没有 10kΩ 电阻,按下开关时,正电源将和接地直接相连,造成短路。
像上图一样,在芯片的脚位连接一个电阻再接地,则此电阻称为下拉电阻
当然也有上拉电阻,即将电阻接到电源,像下图这样:
设计方案
材料清单
材料 |
数量 |
Arduino Uno |
1 |
面包板 |
1 |
1kΩ电阻 |
1 |
10kΩ电阻 |
2 |
LED |
1 |
开关 |
2 |
导线 |
若干 |
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| #define LED 9 #define BTN1 2 #define BTN2 3 boolean lastState1 = LOW; boolean lastState2 = LOW; byte click1 = 0; byte click2 = 0; int ledV = 0;
void setup() { pinMode(LED, OUTPUT); pinMode(BTN1, INPUT); pinMode(BTN2, INPUT); lastState1 = digitalRead(BTN1); lastState2 = digitalRead(BTN2); analogWrite(LED, 255); delay(50); analogWrite(LED, 0); delay(50); analogWrite(LED, 255); delay(50); analogWrite(LED, 0); }
void loop() { boolean a1 = digitalRead(BTN1); boolean b1 = digitalRead(BTN2);
if (a1 != lastState1) { delay(50); boolean a2 = digitalRead(BTN1);
if (a1 == a2) { lastState1 = a1; click1++; } }
if (b1 != lastState2) { delay(50); boolean b2 = digitalRead(BTN2);
if (b1 == b2) { lastState2 = b1; click2++; } }
if (click1 == 2) { click1 = 0; click2 = 0; if (ledV == 255) { analogWrite(LED, 0); delay(50); analogWrite(LED, 255); delay(50); analogWrite(LED, 0); delay(50); analogWrite(LED, 255); } else { ledV += 30; if (ledV >= 255) { ledV = 255; } analogWrite(LED, ledV); if (ledV == 255) { analogWrite(LED, 0); delay(50); analogWrite(LED, 255); delay(50); analogWrite(LED, 0); delay(50); analogWrite(LED, 255); } } }
if (click2 == 2) { click1 = 0; click2 = 0; if (ledV == 0) { analogWrite(LED, 255); delay(50); analogWrite(LED, 0); delay(50); analogWrite(LED, 255); delay(50); analogWrite(LED, 0); } else { ledV -= 30; if (ledV <= 0) { ledV = 0; } analogWrite(LED, ledV); if (ledV == 0) { analogWrite(LED, 255); delay(50); analogWrite(LED, 0); delay(50); analogWrite(LED, 255); delay(50); analogWrite(LED, 0); } } } }
|
成果展示