时不时地,你会想要与用户互动。与用户交互最常见的元素是按钮。现在电子产品中最常见的按钮是按钮。该按钮不会持续关闭电路,但只会持续按下。使用按钮最基本的例子是按下按钮时打开发光二极管。我将在下一节对此进行描述。
这个例子是在使用按钮时的 Hello World。基本上它所做的是当一个按钮被按下时,它打开发光二极管,然后一旦按钮被释放,它就关闭。这是零件清单和接线:
本节零件清单:
- Arduino 一号
- 按钮
- USB 电缆
- 1 个 100 欧姆的发光二极管电阻器(引脚 13)
- 1 个 10k 欧姆的按钮电阻器
- 面包板
- 1 个 5 毫米发光二极管
- 5x 面包板跳线
图 27:按钮接线模式
这个例子的代码非常简单。我们不断从引脚 2 读取状态,如果它处于高电平状态,我们会打开发光二极管。请注意,我们将发光二极管连接到引脚 13,以便板载发光二极管也会发光。下面是代码:
// variable holding button state
int buttonState = 0;
// LED pin
int ledPin = 13;
// Button pin
int buttonPin = 2;
void setup() {
// initialize pins
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop(){
// read the state of the button
buttonState = digitalRead(buttonPin);
// pressed button is in state high
if (buttonState == HIGH) {
// LED on
digitalWrite(ledPin, HIGH);
}
else {
// LED off
digitalWrite(ledPin, LOW);
}
}
在本例中,我们将首次读取引脚输入。我们用digitalRead
功能来做。检查读数的循环比人眼能注意到的要快得多,所以我们没有注意到按钮的有趣效果。我们看到发光二极管立即打开,当按钮最初被按下时,我们无法感知任何振荡。此外,我们在释放按钮后没有看到指示灯闪烁一会儿。让我们看看下一个例子,深入了解这个有趣的效果。
本节的接线和零件与上一节相同(请查看这些示意图)。区别在于编程和使用。例如,在使用按钮时,打开和关闭发光二极管并不是最有用的情况。当涉及微控制器时,通常是某种状态的改变。所以我们按下按钮的时候会改变 LED 的状态。为此,我们将使用以下代码:
// variable holding button state
int buttonState;
// variable holding previous button state
int previousButtonState = LOW;
// variable holding the LED state
int ledState = HIGH;
// LED pin
int ledPin = 13;
// Button pin
int buttonPin = 2;
void setup() {
// initialize pins
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop(){
// read the state of the button
int reading = digitalRead(buttonPin);
// if the button is pressed, change the state
if (reading != buttonState) {
buttonState = reading;
// toggle the LED state only when the button is pushed
if (buttonState == HIGH) {
ledState = !ledState;
}
}
// turn the LED on or off depending on the state
digitalWrite(ledPin, ledState);
// save current reading so that we can compare in the next loop
previousButtonState = reading;
}
现在,试着玩一下这个按钮。如果你这样做了,你会注意到它的行为不像你预期的那样;它有时会错过按键,表现得有点古怪。你会注意到灯一直亮着,即使它不应该亮,反之亦然。虽然我们有digitalRead
功能,但这里有一个有趣的模拟效应在起作用。
开关由金属零件制成,按下按钮就可以将它们连接在一起。这个动作会产生一个运动,开关内部的金属表面会弹开,然后再结合几次(在很短的时间内)。这是一种已知的效果,例如,当打开和关闭灯泡时,它不代表问题。在我们的第一个例子中,只要按钮被按下,发光二极管就一直亮着,这并不代表问题。但是,当涉及到逻辑电路时,我们可以在短时间内快速读取变化,我们不能确定按钮是否被按下。
我们来看下图。本质上,峰值的每一次变化都会导致发光二极管状态的变化。因此,使用这个按钮而不进行某种噪声过滤,就相当于玩彩票。当你松开或按下按钮时,你不会确定发光二极管是打开还是关闭。这里有一个图,显示了在短时间按下按钮时电流的变化。记住,尖峰的每一次变化都是 LED 状态的变化:
图 28:短按按钮后释放时的电量读数
人眼不会察觉到每一个变化,但我们会在按键结束时注意到错误的状态变化。在下一节中,我们将实现一种过滤技术来避免这种奇怪的行为。电路和零件将保持与本节相同。
零件列表和接线与上一示例中的相同。区别在于过滤按钮噪音的软件:
// variable holding the button state
int buttonState;
// variable holding previous button state
int previousButtonState = LOW;
// variable holding the LED state
int ledState = HIGH;
int buttonPin = 2;
const int ledPin = 13;
// millis always stored in long
// becomes too big for int after 32,767 millis or around 32 seconds
// timestamp of a previous bounce
long previousDebounceTime = 0;
// debounce time in millis, if the LED is still quirky increase this value
long debounceDelay = 50;
void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void loop() {
// for now it's the same as in previous example
int reading = digitalRead(buttonPin);
// if the previous reading is different than the previous button state
if (reading != previousButtonState) {
// we'lll reset the debounce timer
previousDebounceTime = millis();
}
// if the reading is the same over a period of debounceDelay
if ((millis() - previousDebounceTime) > debounceDelay) {
// check if the button state is changed
if (reading != buttonState) {
buttonState = reading;
// toggle the LED state only when the button is pushed
if (buttonState == HIGH) {
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save current reading so that we can compare in the next loop
previousButtonState = reading;
}
现在,对一些人来说,代码清单可能看起来有点太复杂了,这是完全可以理解的。有一个巧妙的硬件技巧,我们可以用来过滤噪音。我们可以使用一种叫做电容器的电子元件。
我们现在将使用几乎相同的组件和接线,就像我们使用古怪和基本的按钮示例一样。为了滤除噪声,我们将在电路中增加一个电容。
本节零件清单:
- Arduino 一号
- 按钮
- USB 电缆
- 1 个 100 欧姆的发光二极管电阻器
- 1 个 10k 欧姆的按钮电阻器
- 面包板
- 1 个 5 毫米发光二极管
- 5x 面包板跳线
- 10uF 电容器
图 29:带电容过滤噪声的按钮
这个程序和古怪的按钮是一样的。噪声滤波分配由电容决定。电容器有一个有趣的特点,只要不充满电,它就能让电流通过。当它被填满时,电流不再流过它。但是,如果一些波动开始发生,它会立即开始释放积累的电流(基本上平滑了信号)。实际上,过滤电噪声是电容器的主要用途之一。有各种类型和尺寸的电容器。以下是一些基本的电容形式:
图 30:基本电容形式
有些类型的电容,其接线方式并不重要。对某些人来说,连接正极和负极引脚时必须小心。在电容上,正极引脚标有加号,负极引脚标有“0”号。因此,没有像发光二极管那样找出引脚极性的技巧。也有一些类型的电容器具有较长的引脚,该引脚是正引脚;这与发光二极管的规则相同。但是电容器上的正极或负极引脚需要有清晰的标记。
在这一节中,我介绍了按钮组件以及它们如何与 Arduino 结合使用。我还展示了一些鲜为人知的古怪按钮,以及如何在软件和硬件层面处理它。在下一节中,我将向您展示如何使用 Arduino 来产生声音信号。