所需元件
可插入面包板的按钮1个
220Ω电阻1个
10kΩ电阻1个
3mm或5mm LED 1个
面包板1块
Arduino Uno开发板1块
面包板连接线数条
使用外接电阻
将5V接到按钮,按钮的另一端串联1个10kΩ电阻再接地,这样的接法被称为下拉电阻(pull-down resistor)。若测量电阻及按钮间的电压,当按钮未按下时电路未接通,测量到低电位;当按钮按下时测量到高电位。当按钮被按下时,点亮LED;反之则熄灭。
线路图
实际的装置照片
程式码如下:
#define LEDPIN 7
#define BUTTONPIN 4
#define BAUDRATE 9600
int state;
void setup() {
pinMode(LEDPIN, OUTPUT);
pinMode(BUTTONPIN, INPUT);
Serial.begin(BAUDRATE);
}
void loop() {
state = digitalRead(BUTTONPIN);
if (state == HIGH) {
digitalWrite(LEDPIN, HIGH);
} else {
digitalWrite(LEDPIN, LOW);
}
}
使用开发板内建的上拉电阻
开发板内建有上拉电阻(pull-up resistor),若使用内建的电阻可以使接线方式更加简单,接法如下。
线路图
实际的装置照片
若测量电阻及按钮间的电压,当按钮未按下时电路未接通,测量到高电位;当按钮按下时测量到低电位。当按钮被按下时,点亮LED;反之则熄灭。程式码如下:
#define LEDPIN 7
#define BUTTONPIN 4
#define BAUDRATE 9600
int state;
void setup() {
pinMode(LEDPIN, OUTPUT);
pinMode(BUTTONPIN, INPUT_PULLUP); //启用上拉电阻
Serial.begin(BAUDRATE);
}
void loop() {
state = digitalRead(BUTTONPIN);
if (state == LOW) {
digitalWrite(LEDPIN, HIGH);
} else {
digitalWrite(LEDPIN, LOW);
}
}
按钮的弹跳问题(方法1:时间延迟)
若连续且快速地按按钮,有时候LED不会在按下时被点亮,这是因为按钮被按下到弹回来的过程中程式已经读取了接脚的状态很多次。为了解决这个问题,我们可以先读取一次接脚的状态并储存起来,隔一小段时间后再测量一次,如果两次的状态相同,代表按钮真的被按下。程式码如下:
#define LEDPIN 7
#define BUTTONPIN 4
#define DELAYTIME 200
#define BUADRATE 9600
boolean ledState;
unsigned long timePrevious, timeCurrent;
void setup() {
Serial.begin(BUADRATE);
pinMode(LEDPIN, OUTPUT);
pinMode(BUTTONPIN, INPUT_PULLUP);
ledState = LOW;
digitalWrite(LEDPIN, ledState);
}
void updateLed() {
timeCurrent = millis();
if ((timeCurrent - timePrevious) > DELAYTIME) {
timePrevious = timeCurrent;
ledState = !ledState;
digitalWrite(LEDPIN, ledState);
// Serial.println(ledState);
}
}
void loop() {
boolean buttonState = digitalRead(BUTTONPIN);
if (buttonState == LOW) {
updateLed();
// Serial.println("Change");
}
}
在这个程式当中void updateLed()是自己设定的函数,开头的void 代表函数没有返回值。我们会将程式当中会一直使用到的部分写成一个函数,在程式里其它的部分不断地调用它,这样可以减少代码的长度。
问题:若一直按着按钮会发生什么事?
请先努力地尝试写出解决方案,至少坚持10分钟以后再看,而且这不是唯一的写法,其它写法也能做到同样的效果。
#define LEDPIN 7
#define BUTTONPIN 4
#define DELAYTIME 50
#define BAUDRATE 9600
boolean ledState;
unsigned long timePrevious, timeCurrent;
void setup() {
Serial.begin(BAUDRATE);
pinMode(LEDPIN, OUTPUT);
pinMode(BUTTONPIN, INPUT_PULLUP);
ledState = LOW;
digitalWrite(LEDPIN, ledState);
}
void updateLed() {
timeCurrent = millis();
if ((timeCurrent - timePrevious) > DELAYTIME) {
timePrevious = timeCurrent;
ledState = !ledState;
digitalWrite(LEDPIN, ledState);
}
}
void loop() {
boolean buttonPrevious, buttonCurrent;
buttonPrevious = digitalRead(BUTTONPIN);
delay(DELAYTIME);
buttonCurrent = digitalRead(BUTTONPIN);
if (buttonCurrent == LOW && buttonCurrent != buttonPrevious) { //若按下按鈕而且不是持续按著則更新LED状态
updateLed();
Serial.println("Change");
}
}
按钮的弹跳问题(方法2:Bounce2.h)
已经有热心人士将去除弹跳的函式库写好了,名为Bounce2.h,我们可以从Arduino官网上找到( http://playground.arduino.cc/Code/Bounce ),下载的连结为https: //github.com/thomasfredericks/Bounce-Arduino-Wiring/archive/master.zip,将下载的档案解压缩后得到的资料夹复制到Arduino开发程式的资料夹内即可。可能的路径为
Windows环境 C:\Program Files (x86)\Arduino\libraries\
接下来在程式码的开头只要加上#include <Bounce2.h>即可引用。程式码如下:
#include <Bounce2.h>
#define LEDPIN 7
#define BUTTONPIN 4
#define DELAYTIME 50
#define BAUDRATE 9600
Bounce bouncer = Bounce(BUTTONPIN, DELAYTIME);
boolean ledState;
void setup() {
Serial.begin(BAUDRATE);
pinMode(LEDPIN, OUTPUT);
pinMode(BUTTONPIN, INPUT_PULLUP);
ledState = LOW;
digitalWrite(LEDPIN, ledState);
}
void loop() {
if (bouncer.update() == true && bouncer.read() == LOW) {
ledState = !ledState;
digitalWrite(LEDPIN, ledState);
Serial.println(ledState);
}
}
其中
Bounce bouncer = Bounce(buttonPin, delayTime);
先定义了一个名为bouncer 的物件,需要指定读取的接脚及延迟时间。在void loop() 当中
if (bouncer.update() == true && bouncer.read() == LOW){
ledState = !ledState;
digitalWrite(ledPin, ledState);
Serial.println(ledState);
}
bouncer.update() 会读取接脚的状态且判断状态是否有变化,因此这段程式码的功能是当状态发生变化且为低电位时改变LED 的状态。