Arduino millis() 翻转?为什么按钮在关闭几秒钟后停止响应
Arduino millis() rollover? Why button stops responding after some seconds turned off
我有一个模拟自行车尾灯的草图。当我点击按钮时,led 开始闪烁。当我再次点击时,它停止闪烁。
如果我在不花费太长时间的情况下打开和关闭闪烁,一切正常。然而,如果我让闪烁停止超过几十秒,下次我按下按钮时,LED 需要很多秒才能再次开始闪烁。
我无法想象为什么会发生这种情况。我考虑过 millis()
翻转,但这需要几天时间,不是吗?
有线索吗?代码如下:
const int timeLedOn = 20;
const int timeLedOff = 7 * timeLedOn;
const int ledPin = 8;
int buttonLevel = LOW;
int previousButtonLevel = LOW;
int ledState = LOW;
bool blinkingTurnedOn = false;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
volatile unsigned long lastMicros;
long debouncingTime = 1000 * 200;
void setup() {
// use interrupt 0 (pin 2) for
attachInterrupt(0, debounceInterrupt, RISING);
pinMode(ledPin, OUTPUT);
// disable onboard led
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// turn led off
digitalWrite(ledPin, LOW);
}
void loop() {
currentMillis = millis();
if (blinkingTurnedOn) {
performBlinking();
}
else {
digitalWrite(ledPin, LOW);
}
}
void debounceInterrupt() {
if ((long)(micros() - lastMicros) > debouncingTime) {
toggleBlinking();
}
lastMicros = micros();
}
void toggleBlinking() {
blinkingTurnedOn = !blinkingTurnedOn;
}
void performBlinking() {
int timeDelta = currentMillis - previousMillis;
// check if time "off" elapsed
bool elapsedOff = ledState == LOW && timeDelta > timeLedOff;
// check if time "on" elapsed
bool elapsedOn = ledState == HIGH && timeDelta > timeLedOn;
// blinking itself
if (elapsedOff || elapsedOn) {
toggleLedState();
}
}
void toggleLedState() {
ledState = 1 - ledState;
digitalWrite(ledPin, ledState);
resetMillis();
}
void resetMillis(){
previousMillis = currentMillis;
}
我怀疑延迟的原因可能是blinkingTurnedOn
标志没有标记为volatile
(与lastMicros
变量相同)。由于它是从中断中(间接地)更改的,因此如果没有 volatile
修饰符告诉它始终从内存中读取值(而不是假设寄存器中的当前值是最新的)。 Arduino reference.
将声明更改为:
volatile bool blinkingTurnedOn = false;
应该可以解决问题。
我有一个模拟自行车尾灯的草图。当我点击按钮时,led 开始闪烁。当我再次点击时,它停止闪烁。
如果我在不花费太长时间的情况下打开和关闭闪烁,一切正常。然而,如果我让闪烁停止超过几十秒,下次我按下按钮时,LED 需要很多秒才能再次开始闪烁。
我无法想象为什么会发生这种情况。我考虑过 millis()
翻转,但这需要几天时间,不是吗?
有线索吗?代码如下:
const int timeLedOn = 20;
const int timeLedOff = 7 * timeLedOn;
const int ledPin = 8;
int buttonLevel = LOW;
int previousButtonLevel = LOW;
int ledState = LOW;
bool blinkingTurnedOn = false;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
volatile unsigned long lastMicros;
long debouncingTime = 1000 * 200;
void setup() {
// use interrupt 0 (pin 2) for
attachInterrupt(0, debounceInterrupt, RISING);
pinMode(ledPin, OUTPUT);
// disable onboard led
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// turn led off
digitalWrite(ledPin, LOW);
}
void loop() {
currentMillis = millis();
if (blinkingTurnedOn) {
performBlinking();
}
else {
digitalWrite(ledPin, LOW);
}
}
void debounceInterrupt() {
if ((long)(micros() - lastMicros) > debouncingTime) {
toggleBlinking();
}
lastMicros = micros();
}
void toggleBlinking() {
blinkingTurnedOn = !blinkingTurnedOn;
}
void performBlinking() {
int timeDelta = currentMillis - previousMillis;
// check if time "off" elapsed
bool elapsedOff = ledState == LOW && timeDelta > timeLedOff;
// check if time "on" elapsed
bool elapsedOn = ledState == HIGH && timeDelta > timeLedOn;
// blinking itself
if (elapsedOff || elapsedOn) {
toggleLedState();
}
}
void toggleLedState() {
ledState = 1 - ledState;
digitalWrite(ledPin, ledState);
resetMillis();
}
void resetMillis(){
previousMillis = currentMillis;
}
我怀疑延迟的原因可能是blinkingTurnedOn
标志没有标记为volatile
(与lastMicros
变量相同)。由于它是从中断中(间接地)更改的,因此如果没有 volatile
修饰符告诉它始终从内存中读取值(而不是假设寄存器中的当前值是最新的)。 Arduino reference.
将声明更改为:
volatile bool blinkingTurnedOn = false;
应该可以解决问题。