Проблема с Millis

Chadin

✩✩✩✩✩✩✩
5 Авг 2020
3
1
Привет. Помогите понят, почему счетчик millis работает не стабильно? Почему-то отрабатывает только в первый раз а потом на 2-4 секунды меньше и каждый раз по разному.




#define key_pin 3 //подключение кнопки
#define led_pin 10 // подключение лампочки
#define led_time 6000 // время свечения
boolean led_flag, key_status;
unsigned long last_time_led ;


void setup() {
pinMode (key_pin, INPUT_PULLUP);
pinMode (led_pin, OUTPUT);

}

void loop() {
digitalWrite (led_pin, led_flag);
key_status = digitalRead (key_pin);
key_status = !key_status;
if (key_status == 1 ) {
led_flag = 1;
}

if (led_flag == 1 && millis() - last_time_led > led_time) {
led_flag = 0;
last_time_led = millis();
}
}
 

Arhat109

★★★✩✩✩✩
9 Июн 2019
369
113
1. Код удобней оформлять при выкладке как-то так, тут есть спец. кнопка. Читать "поток сознания" не очень удобно и не каждый просто заглянет в него..

C++:
#define key_pin 3 //подключение кнопки
#define led_pin 10 // подключение лампочки
#define led_time 6000 // время свечения

boolean led_flag, key_status;
unsigned long last_time_led ;

void setup()
{
  pinMode (key_pin, INPUT_PULLUP);
  pinMode (led_pin, OUTPUT);
}

void loop()
{
  digitalWrite (led_pin, led_flag);
  key_status = digitalRead (key_pin);
  key_status = !key_status;
  if (key_status == 1 ) {
    led_flag = 1;
  }

  if (
      (led_flag == 1) &&
      (millis() - last_time_led > led_time)
  ){
    led_flag = 0;
    last_time_led = millis();
  }
}
Далее. Не инициализированные переменные last_time_led, led_flag используются раньше чем им присваивается значение, то есть "что попало". Тут Вам конкретно повезло, т.к. Ардуино заполняет их нулями самостоятельно перед запуском программы, вместо "ученика".. проект-то учебный!

Строки 17-21 сработают "несколько раз" при нажатии кнопки, полезный результат будет в последнем разе срабатывания, а вот условие в строке 23 сработает (если кончился интервал) только первый раз. В целом, это приведет к нарушению длительности не более чем время дребезга кнопки. Но, если контакт фиговый и держать его 1-3сек .. то он столько и даст в нарушениях интервалов.

Интересно тут то, что изначально переменная led_flag равна нулю. То есть условие строки 23 не сработает ни разу до нажатия кнопки.. отсюда - вся проблема в величине дребезга, кмк.

Ну и ещё. Предпочитаю не запоминать приоритеты, а сложные условия по &&, || обрамлять скобками. Кмк, так и наглядней и надежней.
 
  • Лойс +1
Реакции: Chadin

Chadin

✩✩✩✩✩✩✩
5 Авг 2020
3
1
Проблема решилась всего одной строчкой добавленной после 20 строки


C++:
#define key_pin 3 //подключение кнопки
#define led_pin 10 // подключение лампочки
#define led_time 6000 // время свечения

boolean led_flag, key_status;
unsigned long last_time_led ;

void setup()
{
pinMode (key_pin, INPUT_PULLUP);
pinMode (led_pin, OUTPUT);
}

void loop()
{
digitalWrite (led_pin, led_flag);
key_status = digitalRead (key_pin);
key_status = !key_status;
if (key_status == 1 ) {
led_flag = 1;
last_time_led = millis();
}

if (
(led_flag == 1) &&
(millis() - last_time_led > led_time)
){
led_flag = 0;
last_time_led = millis();
}
}

СПАСИБО за Советы)
 
  • Лойс +1
Реакции: Arhat109

Arhat109

★★★✩✩✩✩
9 Июн 2019
369
113
Теперь у Вас переменная будет хранить время последнего дребезга из-за строки 21. И после отпускания кнопки, условия в строке 25 - истина, а в строке 26 будет держать заданный интервал от момента последнего дребезга, после чего выключит флаг и зачем-то запомнит снова текущее время.
Кмк, теперь строка 29 - лишняя.
 

Chadin

✩✩✩✩✩✩✩
5 Авг 2020
3
1
Я об этом и не подумал. И без 29 строки работает как часики. Спасибо за помощь.