Arduino项目

Arduino Project

所以,我正在制作一个项目,其中我将使用 Arduino Uno。我想要做的是,只要开关打开,Arduino 就会让 LED 灯闪烁。但是有一个转折。开关状态变高 10 秒后,LED 将开始闪烁。但是发生的事情是 LED 关闭 10 秒,然后打开 0.5 秒,然后再次关闭 10 秒。我想让它做的是,在保持关闭状态10秒后,它会一直闪烁。

这是代码

const int upperSwitch=2;
int buttonState;
const int ledPin=13;
unsigned long startMillis;  
unsigned long currentMillis;
const unsigned long period = 10000; 

void setup()
{
  pinMode(upperSwitch,INPUT);
  pinMode(ledPin,OUTPUT);
  startMillis=millis();
}

void loop()
{
  buttonState=digitalRead(upperSwitch);
  if(buttonState==HIGH)
  {
    delay(10000);
    currentMillis = millis();
    if (currentMillis - startMillis >= period)  
    {
      digitalWrite(ledPin,HIGH);
      delay(500);
      digitalWrite(ledPin,LOW);
      delay(500);
    }
  }
}

我哪里错了??

我哪里错了?

您的逻辑有缺陷,代码存在一些设计缺陷。如果按下按钮并释放它,它将进入 if(buttonState==HIGH) 部分一次,因此闪烁一次。如果按住按钮(或使用拨动开关),它将重新进入 if(buttonState==HIGH) 部分,但在闪烁之前重复延迟。

您的代码缺少“状态”——一种记住您在上一次 loop() 迭代中所做的事情以通知下一次做什么的方法。

设计缺陷包括:

  • 不必要地使用全局变量 - 这是 Arduino 代码中常见的坏习惯,受到 Arduino 网站上众多示例的鼓励。您只需要 setup()loop() 之间共享的那些变量的全局变量——即便如此,这也不是绝对必要的,但我会放手——Arduino 代码很少会变得复杂到足以成为一个问题.通常允许变量达到必要的最窄范围。

  • loop() 中使用 delay()。这会使您的代码无响应并且浪费 CPU 资源 - 无所事事。在这种情况下,一旦开始延迟,就无法取消延迟或在延迟完成之前进行其他工作。您对 if (currentMillis - startMillis >= period) 的想法是正确的,但是通过在程序开始时延迟 初始化 startMillis 使其变得毫无意义,而不是当按钮被按下。延迟之后,currentMillis - startMillis >= period肯定是true所以测试没有意义。

以下代码通过 必要的 去抖动实现按钮的 press-on/press-off 切换语义。按钮状态可以随时切换 on/off(不会延迟按钮不会被读取)。

打开时,延迟从事件时间戳开始,测试时间从时间戳开始。当延迟到期时,它开始闪烁 - 为每个 LED 状态切换添加时间戳以影响闪光时间。

关闭时,将执行 delay/flash 代码的 none,因此您可以随时取消延迟和闪烁。 LED 在此状态下被强制关闭。这似乎是您想要的语义。

您可以运行 对此here 进行模拟。我包含了调试输出——单击“代码”按钮并展开“串行监视器”以查看调试输出,然后单击“开始模拟”,然后单击模拟轻触开关。仿真时序不准确,比标称 - YMMV 长约 50%。当切换按钮状态且 LED 闪烁时,将输出调试。我添加的电压表用于验证按钮接线是否正确。

const int UPPER_SWITCH = 2 ;
const int LED_PIN = 13 ;

void setup()
{
    pinMode( UPPER_SWITCH, INPUT ) ;
    pinMode( LED_PIN, OUTPUT ) ;
}

void loop()
{
    // Get initial button state
    static int button_toggle_state = digitalRead( UPPER_SWITCH ) ;
    
    // Indicator timing 
    static unsigned long delay_start_timestamp = 0 ;
    
    // Get current time
    unsigned long current_millis = millis();

    // Toggle button state on press (press-on/press-off) with debounce
    static const unsigned long DEBOUNCE_MILLIS = 20 ;
    static unsigned long debounce_timestamp = 0 ;
    static int previous_button_state = digitalRead( UPPER_SWITCH ) ;
    int current_button_state = digitalRead( UPPER_SWITCH ) ;
    if( current_millis - debounce_timestamp > DEBOUNCE_MILLIS &&
        current_button_state == HIGH && previous_button_state == LOW )
    {
        debounce_timestamp = current_millis ;
        
        if( button_toggle_state == LOW )
        {
            button_toggle_state = HIGH ;
            delay_start_timestamp = current_millis ;
        }
        else
        {
            button_toggle_state = LOW ;
        }
    }
    previous_button_state = current_button_state ;
  
    // If button toggle state has remained HIGH for DELAY_PERIOD...
    static const unsigned long DELAY_PERIOD = 10000 ;
    if( button_toggle_state == HIGH && 
        current_millis - delay_start_timestamp > DELAY_PERIOD)
    {
      
        // ... start flashing
        static const int FLASH_PERIOD = 500 ;
        static int led_state = LOW ;
        static unsigned long flash_toggle_timestamp = 0 ;
        if( current_millis - flash_toggle_timestamp > FLASH_PERIOD )
        {
            flash_toggle_timestamp = current_millis ;
            led_state = led_state == HIGH ? LOW : HIGH ;
        }
        digitalWrite( LED_PIN, led_state ) ;
    }
    else
    {
        // LED off
        digitalWrite( LED_PIN, LOW ) ;
    }
}