【问题标题】:Arduino millis() rollover? Why button stops responding after some seconds turned offArduino millis() 翻转?为什么按钮在关闭几秒钟后停止响应
【发布时间】:2015-03-30 01:24:44
【问题描述】:

我有一个模拟自行车尾灯的草图。当我单击按钮时,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; 
}

【问题讨论】:

    标签: timer arduino rollover arduino-uno milliseconds


    【解决方案1】:

    我怀疑延迟的原因可能是blinkingTurnedOn 标志未标记为volatile(与lastMicros 变量相同)。由于它是从中断中(间接)更改的,因此在没有 volatile 修饰符的情况下,从 loop() 调用的代码可能不会立即看到它的新值来告诉它始终从内存中读取值(而不是假设当前值)在寄存器中是最新的)。 Arduino reference.

    将声明更改为:

    volatile bool blinkingTurnedOn = false;
    

    应该解决问题。

    【讨论】:

    • 现在代码似乎可以工作了。支持你的答案的确切段落,顺便说一下,与我的代码非常相关,说“一个变量应该被声明为 volatile,只要它的值可以被它出现的代码部分控制之外的东西改变,比如同时执行“非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2020-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    相关资源
    最近更新 更多