zoukankan      html  css  js  c++  java
  • Arduino 开关控制小灯持续亮之具体思路

    Arduino 开关控制小灯持续亮之具体思路

    为什么写这篇文章:

    我们用开关控制灯的亮灭的时候,希望只需要按一下按键就可以做到灯一直亮着。而在《Arduino魔法书》中——有弹性的按键这一节主要讲了消除抖动函数,但是没有讲这个程序的原理。

    书中的代码如下

    const int LED = 9;
    const int BUTTON = 2;
    boolean lastButton = LOW;
    boolean currentButton = LOW;
    boolean ledOn = false;
    
    void setup() {
      pinMode(LED,OUTPUT);
      pinMode(BUTTON,INPUT);
      // put your setup code here, to run once:
    
    }
    
    boolean debounce(boolean last)
    {
      boolean current = digitalRead(BUTTON);
      if(last != current)
      {
        delay(5);
        current = digitalRead(BUTTON);
      }
      return current;
    }
    void loop() {
    currentButton = debounce(lastButton);
    if (lastButton ==LOW && currentButton == HIGH)
    {
      ledOn = !ledOn;
    }
     lastButton = currentButton;
     digitalWrite(LED,ledOn);            
      // put your main code here, to run repeatedly:
    
    }

    首先,我们假设没有抖动,只关注 loop()函数的部分,
    currentButton = debounce(lastButton);
    这时等价于
    current = digitalRead(BUTTON);

    第一次按——开灯

    首先需要想的是:
    当按下的时候,灯能够一直亮着。
    如果使用digitalRead来读当前的值,当按完以后,灯就会熄灭。所以,利用一个条件语句:条件是:按下按键,动作(或者结果)是灯持续亮。
    用代码表示如下

    所以必须更改原来的条件和动作。先考虑动作,不妨把灯亮变成一个状态量,而不是临时读取的量,这里定义为 ledOn. 
    那么接下来需要想的是如何更改 ledOn 这个值呢?那就是通过按键的状态变化来考虑了。另外,我们也想要灯亮时再次按下按键的时候,能够熄灭灯。所以可以用到一个反转语句:
    ledOn = !ledOn;
    接下来就是条件的问题了:无论你是想持续点亮灯还是熄灭灯,这时候按键的状态总是 HIGH,而之前的状态总是 LOW.
    所以你可以用以下语句决定是否执行反转语句:
    if(lastButton = LOW&& currentButton = HIGH);
    来进行判断。

    第一次以后

    然后之下的语句:lastButton = currentButton,此时,lastButton 的值变为 HIGH,然后重新返回 loop()函数的第一行,进入debounce()函数,此时,你已经不再按键了,所以返回的 currentButton 的值为LOW,然后已经返回值后执行下一条语句,也就是if()的条件语句,因为lastButton = HIGH ,currentBUTTON = LOW ,所以不满足条件,直接执行 lastButton = currentButton,这时,lastButton 和 currentButton 的值都为 LOW。

    第二次按——关灯

    下一次你再进行按键的时候,就会反转 ledOn的数值,ledOn熄灭。

    最后,我们来考虑消除抖动

    之所以要消除抖动,是因为如果不消除抖动,currentButton 的值是不确定的,所以会导致结果的无法预测,不能人为地掌控。

    如何消除抖动呢,书中写道5ms之后,抖动一般都会消失,所以 delay(5); 之后再次读取数值。
    但是需要时时刻刻读取吗?不需要,所以可以加一个条件语句。
    也就是 if (last! = current)
    如果没必要进行5ms的等待了再次读取,那么程序变成这样:

    boolean debounce(boolean last)
    {
      boolean current = digitalRead(BUTTON);
      if(last != current)
      return current;
    }

    此时如果last = current ,返回值都是没有消除抖动的,所以消除抖动需要有一个 if 也需要延时delay.

    那么,如果没有if 语句呢?我认为是可行的。经过实验我认为只要延长时间,读两次数即可。

    之所以会存在抖动,我认识是抖动的时间远远地长于程序运行一条语句的时间,此时需要延时再进行读数。





  • 相关阅读:
    [Go] 解决packets.go:36: read tcp 127.0.0.1:51139->127.0.0.1:3306: wsarecv: An established connection was aborted by the software in your host ma chine.
    [javascript] js格式化时间为xx秒前、xx分钟前、xx小时前等
    [日常]UserAgent中的AhrefsBot解释
    [PHP] laravel 框架多项目公用redis会有默认前缀 项目名_database_key
    [Go] go run 时 os.Getwd 和 os.Executable 获取程序根路径
    [laravel] 关闭laravel数据库model维护create_at update_at
    [Go]go.mod 文件中的// indirect意思代表间接依赖
    [Go] 解决 imported from implicitly required module
    [mysql] 解决SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '' for column
    [PHP] windows环境下PHP增加rdkafka扩展 解决需要ext-rdkafka问题
  • 原文地址:https://www.cnblogs.com/FBsharl/p/9973236.html
Copyright © 2011-2022 走看看