Skip to content

Latest commit

 

History

History
214 lines (150 loc) · 8.56 KB

3.md

File metadata and controls

214 lines (150 loc) · 8.56 KB

三、使用按钮

时不时地,你会想要与用户互动。与用户交互最常见的元素是按钮。现在电子产品中最常见的按钮是按钮。该按钮不会持续关闭电路,但只会持续按下。使用按钮最基本的例子是按下按钮时打开发光二极管。我将在下一节对此进行描述。

按钮

这个例子是在使用按钮时的 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 来产生声音信号。