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 ) ;
}
}
所以,我正在制作一个项目,其中我将使用 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 ) ;
}
}