Иногда не корректно работает millis

itehno
Offline
Зарегистрирован: 18.04.2015

Добрый день. Мне необходимо чередовать включение двух светодиодов независимо друг от друга и при этом не использовать delay.

Я реализовал это таким образом.

Все работает, но есть нюанс. Иногда при вызове и запуску функции led() светодиоды не сразу начинают включаться/выключаться правильно. Первый светодиод может включиться/выключиться дважды и только потом все начинает работать нормально. Иногда начинается со второго светодиода.

Я уже по разному "игрался" с обнулением led_a_previousMillis = led_a_currentMillis, пытался выносить все currentMillis в глобальные переменные и там устанавливать все previousMillis равными currentMillis, но тогда вообще ничего не работает. Только в таком виде ОК, но не всегда с самого начала.

Пожалуйста, если не сложно, разъясните что не так и может Вы сможете предложить более элегантное решение, т.к. я еще только учусь и очень многое мне не понятно.

itehno
Offline
Зарегистрирован: 18.04.2015

Вот код:

#define LED_A 11
#define LED_B 10

int8_t ledState_a = LOW;
int8_t ledState_b = LOW;
int8_t ledState_dalay_a = LOW;
int8_t ledState_dalay_b = LOW;
uint32_t led_a_previousMillis = 0;
uint32_t led_b_previousMillis = 0;
uint32_t led_dalay_a_previousMillis = 0;
uint32_t led_dalay_b_previousMillis = 0;
const uint16_t led_Interval = 500;
const uint16_t dalay_Interval = 300;
bool b_led_a = true;
bool b_led_b = false;
bool b_led_dalay_a = false;
bool b_led_dalay_b = false;
bool b_led_start = false;

void setup() {
    pinMode(LED_A, OUTPUT);
    pinMode(LED_B, OUTPUT);
}

void loop() {
  led();
}

void led(){
  if(b_led_a == true){
  uint32_t led_a_currentMillis = millis();
  if (led_a_currentMillis - led_a_previousMillis >= led_Interval) {
    led_a_previousMillis = led_a_currentMillis;
    if (ledState_a == LOW) {
      ledState_a = HIGH;
    } else {
      ledState_a = LOW;
      b_led_a = false;
      b_led_dalay_a = true;
      b_led_b = false;
      b_led_dalay_b = false;
    }
    digitalWrite(LED_A, ledState_a);
    }
  }

  if(b_led_dalay_a == true){
  uint32_t led_dalay_a_currentMillis = millis();
  if (led_dalay_a_currentMillis - led_dalay_a_previousMillis >= dalay_Interval) {
    led_dalay_a_previousMillis = led_dalay_a_currentMillis;
    if (ledState_dalay_a == LOW) {
      ledState_dalay_a = HIGH;
    } else {
      ledState_dalay_a = LOW;
      b_led_a = false;
      b_led_dalay_a = false;
      b_led_b = true;
      b_led_dalay_b = false;
      }
    }
  }
  
  if(b_led_b == true){
  uint32_t led_b_currentMillis = millis();
  if (led_b_currentMillis - led_b_previousMillis >= led_Interval) {
    led_b_previousMillis = led_b_currentMillis;
    if (ledState_b == LOW) {
      ledState_b = HIGH;
    } else {
      ledState_b = LOW;
      b_led_b = false;
      b_led_dalay_a = false;
      b_led_a = false;
      b_led_dalay_b = true;
    }
    digitalWrite(LED_B, ledState_b);
    }
  }

  if(b_led_dalay_b == true){
  uint32_t led_dalay_b_currentMillis = millis();
  if (led_dalay_b_currentMillis - led_dalay_b_previousMillis >= dalay_Interval) {
    led_dalay_b_previousMillis = led_dalay_b_currentMillis;
    if (ledState_dalay_b == LOW) {
      ledState_dalay_b = HIGH;
    } else {
      ledState_dalay_b = LOW;
      b_led_a = true;
      b_led_dalay_a = false;
      b_led_b = false;
      b_led_dalay_b = false;
      }
    }
  }
}

 

astwo
Offline
Зарегистрирован: 10.07.2019

Похоже intehno запретили использовать классы и цифровой автомат. В общем inteno работает некорректно

itehno
Offline
Зарегистрирован: 18.04.2015

astwo пишет:
Похоже intehno запретили использовать классы и цифровой автомат. В общем inteno работает некорректно

Согласен. Я это не умею. Можете ткнуть носом в пример?

 

astwo
Offline
Зарегистрирован: 10.07.2019
itehno
Offline
Зарегистрирован: 18.04.2015

Спасибо. Я именно эту тему сейчас уже и читал. А еще:

http://arduino.ru/forum/programmirovanie/tsifrovye-avtomaty-v-klassakh-p...

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

itehno пишет:

Добрый день. Мне необходимо чередовать включение двух светодиодов независимо друг от друга и при этом не использовать delay.

...

Первый светодиод может включиться/выключиться дважды и только потом все начинает работать нормально. Иногда начинается со второго светодиода.

Опишите словами, как конкретно  должны включаться светодиоды. Просто каждый со своим интервалом и скважностью?

astwo
Offline
Зарегистрирован: 10.07.2019

Если вы говорите он некой несинхронности работы светодиодов, то так и должно быть. Из-за неравномерной загрузки процессора реакция всегда запаздывает. Но этим болеют все современные компьютеры.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

тоись, TTimerList тебе использовать запретили уже? 

itehno
Offline
Зарегистрирован: 18.04.2015

DetSimen пишет:

тоись, TTimerList тебе использовать запретили уже? 

Ни в коем случае. Просто я, наверное, слишком туп, что бы применить его в конкретном случае. Я научился вызывать с его помощью необходимые мне функции, останавливать их и запускать вновь. Также мне очень это помогает во время отладки. На свободный THandle "вешаю" debug в serail и могу кнопкой остановить и запустить его по необходимости. Очень здорово.

Но вот как с помощью TTimerList реализовать, казалось бы, такую простейшую задачу, понять не могу.

Я либо очень узко мыслю или.... даже не знаю. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А надо то чо?  Поточнее

itehno
Offline
Зарегистрирован: 18.04.2015

asam пишет:

itehno пишет:

Добрый день. Мне необходимо чередовать включение двух светодиодов независимо друг от друга и при этом не использовать delay.

...

Первый светодиод может включиться/выключиться дважды и только потом все начинает работать нормально. Иногда начинается со второго светодиода.

Опишите словами, как конкретно  должны включаться светодиоды. Просто каждый со своим интервалом и скважностью?

1-й включается на 500 мс и гаснет

Пауза 300 мс

2-й включается на 500 мс и гаснет

Пауза 300 мс

.... и так по кругу, пока не остановлю. И разумеется без delay. )

 

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

itehno пишет:

1-й включается на 500 мс и гаснет

Пауза 300 мс

2-й включается на 500 мс и гаснет

Пауза 300 мс

.... и так по кругу, пока не остановлю. И разумеется без delay. )

Остановишь чем?  Оба сразу или каждый по отдельности?

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

каоче, без остановки пока

#include <Arduino.h>
#include <TimerList.h>

extern TTimerList TimerList;

static const uint8_t Led1Pin = 13;
static const uint8_t Led2Pin = 10;

bool Led1State = false;
bool Led2State = true;

THandle hLed1, hLed2;

void setLedState(const uint8_t ALedPin, const bool ALedState) {
	digitalWrite(ALedPin, ALedState);
}

void updateLeds(void) {
	setLedState(Led1Pin, Led1State);
	setLedState(Led2Pin, Led2State);
}

void tmrLed1(void) {
	Led1State = !Led1State;
	TimerList.setNewInterval(hLed1, Led1State ? 500 : 300);
	updateLeds();
}

void tmrLed2(void) {
	Led2State = !Led2State;
	TimerList.setNewInterval(hLed2, Led2State ? 500 : 300);
	updateLeds();
}

void setup() {
	Serial.begin(115200);

	Serial.println(F("Program started...."));

	pinMode(Led1Pin, OUTPUT);
	pinMode(Led2Pin, OUTPUT);

	hLed1 = TimerList.Add(300, tmrLed1);
	hLed2 = TimerList.Add(300, tmrLed2);

	updateLeds();
}

void loop() {
  
}

мигають вразнобой 500/300 мс.

itehno
Offline
Зарегистрирован: 18.04.2015

DetSimen пишет:

itehno пишет:

1-й включается на 500 мс и гаснет

Пауза 300 мс

2-й включается на 500 мс и гаснет

Пауза 300 мс

.... и так по кругу, пока не остановлю. И разумеется без delay. )

Остановишь чем?  Оба сразу или каждый по отдельности?

 

 

Да, сразу оба. Например, булевой переменной

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ну я там код выклал.  Остановить: 

TimerList.Stop(hLed1);

TimerList.Stop(hLed2);

запустить снова 

TimerList.Reset(хэндл) - запускает интервал сначала, не с того места где остановились 

а если 

TimerList.Start(хэндл) то продолжить с того места, где остановились

itehno
Offline
Зарегистрирован: 18.04.2015

DetSimen пишет:

ну я там код выклал.  Остановить: 

TimerList.Stop(hLed1);

TimerList.Stop(hLed2);

запустить снова 

TimerList.Reset(хэндл) - запускает интервал сначала, не с того места где остановились 

а если 

TimerList.Start(хэндл) то продолжить с того места, где остановились

Огромное спасибо. Я разобрался. 

И отдельная благодарность всем не равнодушным людям. Программирование микроконтроллеров действительно интересная штука, но чем больше в это углубляешься, тем больше понимаешь, что ничего не понимаешь. )))

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

itehno пишет:

Огромное спасибо. Я разобрался. 

Ну, мошт, нальёшь при случае. 

b707
Offline
Зарегистрирован: 26.05.2017

itehno пишет:

И отдельная благодарность всем не равнодушным людям. Программирование микроконтроллеров действительно интересная штука, но чем больше в это углубляешься, тем больше понимаешь, что ничего не понимаешь. )))

все отлично. только в будущем не называйте темы "некорректно работает миллис" или "ошибается цикл for" и тому подобное, а то смешно делается. "Некорректно работает" и "ошибается" обычно программист, миллис и for ведут себя аккуратнее :)

itehno
Offline
Зарегистрирован: 18.04.2015

И еще послание для совсем нубов, только начинающих что-то пробовать. Я сам таким был еще некоторое время назад, но по чуть-чуть глаза начинают открываться. Смотрю, бывает, на просьбы о помощи и уже замечаю откровенные глупые ошибки. Я понимаю, что еще по сути в 1-м классе, если это можно сравнить со школой и до окончания "школы программистов" мне еще очень далеко, но это действительно круто, когда ты железку заставляешь работать так, как планировал.

itehno
Offline
Зарегистрирован: 18.04.2015

b707 пишет:

itehno пишет:

И отдельная благодарность всем не равнодушным людям. Программирование микроконтроллеров действительно интересная штука, но чем больше в это углубляешься, тем больше понимаешь, что ничего не понимаешь. )))

все отлично. только в будущем не называйте темы "некорректно работает миллис" или "ошибается цикл for" и тому подобное, а то смешно делается. "Некорректно работает" и "ошибается" обычно программист, миллис и for ведут себя аккуратнее :)

Согласен, учусь

itehno
Offline
Зарегистрирован: 18.04.2015

DetSimen пишет:

itehno пишет:

Огромное спасибо. Я разобрался. 

Ну, мошт, нальёшь при случае. 

Всегда за

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

в будущем не называйте темы "некорректно работает миллис" или "ошибается цикл for" и тому подобное

у гуру это вызывает смех, а у новичков - панику. :) 

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

b707 пишет:

все отлично. только в будущем не называйте темы "некорректно работает миллис" или "ошибается цикл for" и тому подобное, а то смешно делается. "Некорректно работает" и "ошибается" обычно программист, миллис и for ведут себя аккуратнее :)

ты ещё в богов ему запрети верить - он обитает во вселенной одушевлённых сущностей, где миллис и цикл фор обладают свободой воли.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Клапауций 003 пишет:

b707 пишет:

все отлично. только в будущем не называйте темы "некорректно работает миллис" или "ошибается цикл for" и тому подобное, а то смешно делается. "Некорректно работает" и "ошибается" обычно программист, миллис и for ведут себя аккуратнее :)

ты ещё в богов ему запрети верить - он обитает во вселенной одушевлённых сущностей, где миллис и цикл фор обладают свободой воли.

Еще, у них часто while неправильно работает, а if вапще ахинею несет, прямо в массы.