Можно ли обойтись без delay ()?

junior_developer
Offline
Зарегистрирован: 27.11.2017

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

То есть например при одном условии мигнул 2 раза, при другом - например 5. Я думаю, что нужно создать функцию и просто передавать ей это число. То есть как-то так:

blink_count(5); // количество миганий 5

а сама функция, я думаю, должна выглядеть так:

void  blinking_count(byte counter) {
 while (counter > 0) {
       blink_led();  // это обычное мигание с короткой паузой
       counter--; }
}

а вот дальше должна идти  пауза (например 1 секунда). Если дописать  delay (1000); это конечно просто, а вот как сделать это через millis не используя delay вообще? То есть получается нужно отсчитывать два временных интервала. Я назвал их так
 

long long_interval = 1000;       // интервал между циклами миганий
long short_interval = 100;      // короткий интервал между вкл./выкл. светодиода;

С коротким интервалом всё ясно, я могу использовать для него фактически готовую функцию? А как прикрутить ещё длинную паузу без delay? Кто разбирается, подскажите пожалуйста! Мой вариант кода

void  blink_led ();  // функция  мигания (предварительное объявление)

const int ledPin = 13;      // номер выхода, подключенного к светодиоду
//переменные
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода 
long previousMillis = 0;        // храним время последнего переключения светодиода
long prevMill = 0;

long long_interval = 1000;       // интервал между циклами миганий
long short_interval = 100;      // короткий интервал между вкл./выкл. светодиода;
void setup() {
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);      
}
void loop(){
  blinking_count(4); // сколько раз мигнуть между длинной паузой
}
void  blinking_count(byte counter) {
 while (counter > 0) {
       blink_led();
       counter--;
       }
      long currMill = millis();
      if(currMill - prevMill > long_interval) {
      prevMill = currMill; }
      
   }

void  blink_led () {
 unsigned long currentMillis = millis();
 
  //проверяем не прошел ли нужный интервал, если прошел то
  if(currentMillis - previousMillis > short_interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;  

    // если светодиод не горит, то зажигаем, и наоборот
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // устанавливаем состояния выхода, чтобы включить или выключить светодиод
    digitalWrite(ledPin, ledState);
  }
}

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А Вы можете каждую строчку снабдить комментарием - что она дедлает? Только не в терминах "вычитает 1 из а", а в терминах поставленной задачи?

Сразу всё и поймёте.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Вот код  с коментариями каждой строки функции:

void  blinking_count(byte counter) { // это начало функции для мигания столько раз, сколько передается в параметр функции под названием counter 
 while (counter > 0) { // пока он больше нуля
       blink_led();    // выполнить функцию мигания 
       counter--;      // уменьшить счетчик на 1
       }
     unsigned long currMill = millis(); // присвоить currMill значение millis();
      if(currMill - prevMill > long_interval) { // если разница этого значения и предыдущего то есть  prevMill больше, чем интервал
      prevMill = currMill; }   // присвоить предыдущему текущее, чтобы можно было отсчитывать снова
    что тут написать??? чтобы попасть в начало функции только после того, как прошел заданный интервал?
   }

Мне только непонятно, что использовать для перехода в начало функции лишь после того, как прошел интервал? Я пробовал оператор continue. Компилятор на него ругается!
 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну Вы же уже мигнули count раз. Нафига Вам вообще считать этот интервал и переходить потом в начало?

junior_developer
Offline
Зарегистрирован: 27.11.2017

чтобы сделать длинную паузу после того, как светодиод быстро мигнул несколько раз! И вот я думал, что после того как цикл закончился (количество быстрых миганий отсчитано) сделать паузу, через отсчет интервала?
То есть буквально ЕСЛИ интервал прошел ТО  ПРОДОЛЖИТЬ! То есть опять быстро помигать светодиодом.

Логично я так и пробовал писать!
IF (интервал прошел)
CONTINUE
А компилятор ругается на continue! Может я что-то не так написал? Подскажите пожалуйста!
 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Может и не так. Я не понимаю, что Вы хотите написать. Попробуйте объяснить внятно, чтобы кто-то кроме Вас понял (хотя я уверен, что настолько, насколько это надо для программирования, Вы и сами не понимаете).

junior_developer
Offline
Зарегистрирован: 27.11.2017

если описать алгоритм то он будет таким:

включить светодиод;
пауза 100 миллисекунд;
выключить светодиод;
Это одно короткое мигание.

Я пытаюсь написал функцию, которая принимает в качестве параметра количество коротких миганий светодиода и делает (точнее должна делать) после них длительную  паузу (1 секунда)! То есть, чтобы по количесву этих коротких миганий светодиода (их подсчету) можно было определить например режим работы устройства, если в нём всего 1 светодиод!
например в одном режиме работы устройство мигает светодиодом 2 раза, в другом  3 или 5 и т.д.
 

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

junior_develope, у вас ошибка в понимании работы данного устройства . Функций должно быть две. 1-я это отдача команды-"мигнуть столько импульсов" . И 2-я функция для выполнения задания. Ее надо закидывать в loop или вешать в обрабртчика таймера прерывания. А иначе ну никак.

ПС: я бы решал через цифровой автомат.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

при неблокирующем подходе, то есть при таком программировании, при котором система не погибает в ожидании завершение какого либо действия (то есть без  delay() ) следует немного иначе смотреть на код.

Вместо фунции совершающей законченное действие, мы сосздаем функцию делающюу нужный шаг в нужное время и завершающуюся на этом.

Если Вы учили иностранный язык, то ту аналогия со временами - мы заменяем перфект на континуус ;).

Цикл  loop() мы при этом должны сделать максимальнго быстрым, при каждом вызове loop() перебирая наши неблокирующие "шаги".

В случае такого мигания, ка вы хотите, нужно "шаг" функции описать так:

1. при первом вызове: обнулить счетчик фаз мигания, включить светодиод, запомнить время, назначить величину интервала ожидания. Первый вызов от не первого отличаем по значению параметра, например так: положительное значение  - первый вызов, ноль в параметре - вызов очередного "шага".

2. если это не первый вызов, то посмотреть на часы (то есть вызвать millis()), проверить не прошел ли интервал ожидания окончания фазы, если не прошел - выход, если прошел - меняем фазу светодиода, запоминаем время и назначает величину интервала ожидания, а затем выход.

3. если значение фазы достигло окончания цикла миганий - то все обнуляем и выходим. Фазу разумно взять как удвоенное количество миганий, потому что свет бывает в двух состояниях - включен и выключен и три мигания это 6 состояний: вкл, выкл, вкл, выкл, вкл,  конец.

----------------------

Итог: первым оператором в loop() у нас будет вызов функции "шага" - например ее можно назвать checkBlink(0). С нулем в параметре.

Если мы, в каком то месте программы, хотим моргнуть три раза то вызовем checkBlink(3).

Это просто рекомендации. С использованием классов С++ можно это сделать читабельнее и изящнее. Если понимать, что делаешь.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

junior_developer пишет:

если описать алгоритм то он будет таким:

включить светодиод;
пауза 100 миллисекунд;
выключить светодиод;
Это одно короткое мигание.

Я пытаюсь написал функцию, которая принимает в качестве параметра количество коротких миганий светодиода и делает (точнее должна делать) после них длительную  паузу (1 секунда)! 

Ну, это как раз к тому же, о чём я говорил. Вы не до конца продумали чего хотите. Это не алгоритм - это разведение руками в стили "грабить корованы".

Ну, например, в каком именно месте Вашего "алгоритма" указана, что между "короткими миганиями" должна быть пауза? И какая там должна быть пауза?

Это только один вопрос - их больше.

Попробуйте таки строго расписать последовательность действий. Чтобы Вы могли выполнить её автоматом: делай раз, делай два. Пока у Вас не будет такого понимания - программа у Вас не получится никогда.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Вот код с delay();

const byte ledPin=13;
byte blink_count = 0; // счетчик миганий

unsigned long long_delay = 1000; // большая длительность
unsigned long short_delay = 300; // и маленькая
bool ledState = LOW; // состояние LED 

void blink_led() {
     if (ledState == LOW)
      ledState = HIGH;
       else
       ledState = LOW;
   digitalWrite(ledPin, ledState);
   delay (short_delay);
  }


void  LED_blinking(byte counter) { // это начало функции для мигания столько раз, сколько передается в параметр функции под названием counter
        counter*=2; // умножаем на 2, чтобы передавать в функцию реальное количество миганий
 while (counter > 0) { // пока он больше нуля
       blink_led();    // выполнить функцию мигания 
       counter--;      // уменьшить счетчик на 1
       }
     delay (long_delay);
   }
   
void setup() {
  // put your setup code here, to run once:
pinMode(ledPin, OUTPUT); 
}

void loop() {
  // put your main code here, to run repeatedly:
LED_blinking (5); // количество коротких миганий
}

 Работает!

5N62V
Offline
Зарегистрирован: 25.02.2016

вот эту громоздкую штуку:

09      if (ledState == LOW)
10       ledState = HIGH;
11        else
12

       ledState = LOW;

Проще записать как 

ledState = !ledState;

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

Morroc
Offline
Зарегистрирован: 24.10.2016

junior_developer пишет:

Вот код с delay();

Почитайте что wdrakula написал. Нужно изменить подход, уйти от последовательного выполнения команд и соответствующего написания кода. У вас что то постоянно должно вызываться / проверяться, а вот результатом вызова / проверки может быть включение / выключение, а может и не быть в зависимости от времени и предыдущего состояния системы.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Создал ещё одну переменную blink_enable, разрешающую или запрещающую мигание:


const byte ledPin = 13; // пин светодиода
bool blink_enable = 1;  // разрешены ли мигания
byte blink_counter; // счетчик
unsigned long long_delay = 1000; // большая длительность
unsigned long short_delay = 200; // и маленькая
bool ledState = 0; // состояние LED 
long previousMillis = 0; // предыдущее время


void  LED_blinking (byte counter) { // это начало функции для мигания
 if(blink_enable){ // если мигания разрешены...
   
   while (counter > 0) { // пока счетчик больше нуля
        unsigned long currentMillis = millis(); // считываем время в переменную currentMillis
        if(currentMillis - previousMillis > short_delay) { // если время прошло...
    
  digitalWrite(ledPin, !ledState);  // меняем состояние светодиода
  previousMillis = currentMillis;  // сохраняем время последнего переключения
       counter--;      // уменьшить счетчик на 1
       }
     }
	blink_enable = 0;  // запретить мигания  
 }
 else {
   unsigned long currentMillis = millis();  // считываем время в переменную currentMillis
   if(currentMillis - previousMillis > long_delay) { // если длинный интервал прошел, то...
      previousMillis = currentMillis;}  // сохраняем время
    blink_enable = 1; // разрешить мигания
 }
}

void setup() {
  // put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);
}

void loop() {
  // put your main code here, to run repeatedly:
LED_blinking(4);
}

однако светодиод не мигает - он просто включается и горит! Впечатление такое, что цикл while неправильный! Ведь по идее он должен выполнятся и выполняться, пока условие истинно. То есть пока счетчик не обнулится

 while (counter > 0) { // пока счетчик больше нуля
        unsigned long currentMillis = millis(); // считываем время в переменную currentMillis
        if(currentMillis - previousMillis > short_delay) { // если время прошло...
    
  digitalWrite(ledPin, !ledState);  // меняем состояние светодиода
  previousMillis = currentMillis;  // сохраняем время последнего переключения
       counter--;      // уменьшить счетчик на 1
       }
     }
	blink_enable = 0;  // запретить мигания  

Верно? При вызове функции мигания в loop в неё передается число 4. Это значит, что светодиод должен мигнуть 2 раза (изменить состояние 4 раза). Однако светодиод просто включается и горит!

Morroc
Offline
Зарегистрирован: 24.10.2016

Вот вы попали в цикл, а выйдете из него когда ? Когда светодиод моргнет 4 раза ? За что боролись то ? :) Разбейте это все на фазы в case или if и сделайте так чтобы loop() этот код "насквозь" пролетал или, в случае функции, вызвали её и если время события не пришло (ни какого) или мигание выключено - сразу на выход.

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

junior_developer - вы так и не поняли, что вам обьяснил Дракула в посте #8. Ваша новая программа опять построена принципиально неверно. Вы входите в вашу функцию LED_blinking и "сидите" в ней, пока светодиод не мигнет положенного числа раз. Например, если вы решили мигнуть 4 раза с промужутком в 200мс - ваша функция зависит программу на 0.8сек. Пока вы используете такой подход, вы НИКОГДА не достигнете результата. Попробуйте еще раз перечитать то, что написал Дракула...

junior_developer
Offline
Зарегистрирован: 27.11.2017

значит цикл WHILE здесь использовать невозможно в принципе? Нужно проверять условие только через IF?

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

junior_developer пишет:

значит цикл WHILE здесь использовать невозможно в принципе? Нужно проверять условие только через IF?

да. while тут явно ни к месту. Но и с If надо строить логику не так, как у вас - а как написано в сообщении 8. А вообще - вы явно не поняли принципа работы "блин без делей". Попробуйте сначала переписать в этом стиле просто свою функцию однократного мигания... - она у вас тоже с делеями написана.

Morroc
Offline
Зарегистрирован: 24.10.2016

Для проверки его можно использовать, но по смыслу получится IF. Цикл у нас уже есть - loop(), остальное будет определяться, например, blink_enable / previousMillis / номером фазы / millis()... в общем текущим состоянием системы.
 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Структура программы должна быть такой

/**/
void  LED_init () { /*функции иницирования*/
}
void  LED_run () { /*функции работы*/
}
void  LED_blinking (byte counter) { /*функции запуска мигания*/
}
//------main()-------------------
void setup() {
  LED_init ();
}

void loop() {
  LED_run ();
  if (HIGH/*условие запуска*/) LED_blinking (3);
}
/*Скетч использует 444 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
*/

 

Morroc
Offline
Зарегистрирован: 24.10.2016

Самое интересное дальше, в структуре LED_run(), но на форуме уже много раз встречалось.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Светодиод уже мигает. Теперь в коде нет никаких задержек, а только две проверки:

прошел ли интервал;
достиг ли счетчик значения;

Когда, достиг - длительность пауы должна поменяться с 100мс на 1с. Однако этого почему-то не происходит! Я специально добавил для отладки такие строчки
 

Serial.print("Counter=");
Serial.println(counter);
Serial.print("ledState=");     
Serial.println(ledState);
Serial.print("interval_delay=");
Serial.println(interval_delay);

и через порт приходит

Counter=1 
ledState=1 
interval_delay=100 
Counter=2 
ledState=0 
interval_delay=100 
Counter=3 
ledState=1 
interval_delay=100 
Counter=4 
ledState=0 
interval_delay=100 
Counter=1 
ledState=1 
interval_delay=100 
Counter=2 
ledState=0 
interval_delay=100 

Видно, что переменная interval_delay не меняется совсем! Хотя она должна измениться по условию:

if (counter >= state_changes){
    
	   interval_delay = long_delay;  // длительная задержка
	   counter = 0;

Вот код целиком:

const byte ledPin = 13; // пин светодиода
bool blink_enable = 1;  // разрешены ли мигания
byte counter = 0; // счетчик
byte state_changes;
unsigned long long_delay = 1000; // большая длительность
unsigned long short_delay = 100; // и маленькая
bool ledState = 0; // состояние LED 
long previousMillis = 0; // предыдущее время


void  LED_blinking (byte state_changes) {// это начало функции для мигания
unsigned long interval_delay;
  if (counter >= state_changes){
    
	   interval_delay = long_delay;
	   counter = 0;
 }
    else {interval_delay = short_delay;}
 
 unsigned long currentMillis = millis();  // считываем время в переменную currentMillis
 
   if(currentMillis - previousMillis > interval_delay) { // если время прошло...
     ledState = !ledState;
    digitalWrite(ledPin, ledState);  // меняем состояние светодиода
    previousMillis = currentMillis;  // сохраняем время последнего переключения
       counter++;      // увеличить счетчик на 1
Serial.print("Counter=");
Serial.println(counter);
Serial.print("ledState=");     
Serial.println(ledState);
Serial.print("interval_delay=");
Serial.println(interval_delay);
       }
     }

void setup() {
Serial.begin(9400);
  // put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);
}

void loop() {
  // put your main code here, to run repeatedly:
LED_blinking(4);
}

Не могу понять, почему значение interval_delay не меняется. Как такое может быть?

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

junior_developer пишет:

Не могу понять, почему значение interval_delay не меняется. Как такое может быть?

Да нет, оно меняется. Вставьте вывод значения interval_delay на 16 строке  - увидите. Просто при следующем же цикле loop() через несколько микросекунд - длинная задержка меняется обратно на короткую и вы не успеваете заментить изменения.

junior_developer
Offline
Зарегистрирован: 27.11.2017

а как же сделать, чтобы это значение не пропадало? Подскажите пожалуйста!

ven-til
Offline
Зарегистрирован: 13.02.2018

Засунуть проверку counter внутрь if(currentMillis - previousMillis > interval_delay) {

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

junior_developer пишет:

а как же сделать, чтобы это значение не пропадало? Подскажите пожалуйста!

например, перенести строки с 13 по 18 внутрь условия If на строке 22

junior_developer
Offline
Зарегистрирован: 27.11.2017

я добавил ещё одну переменную и получилось так:
 

const byte ledPin = 13; // пин светодиода
//bool blink_enable = 1;  // разрешены ли мигания
byte counter = 0; // счетчик
byte state_changes;
unsigned long long_delay = 1000; // большая длительность
unsigned long short_delay = 100; // и маленькая
bool ledState = 0; // состояние LED 
long previousMillis = 0; // предыдущее время
bool long_delay_state = 0;

void  LED_blinking (byte state_changes) {// это начало функции для мигания
unsigned long interval_delay;
  if (long_delay_state) {
	  interval_delay = long_delay;
	  }
 else {
	  interval_delay = short_delay;
	  }
 
 unsigned long currentMillis = millis();  // считываем время в переменную currentMillis
 
   if(currentMillis - previousMillis > interval_delay) { // если время прошло...
     ledState = !ledState;
    digitalWrite(ledPin, ledState);  // меняем состояние светодиода
    previousMillis = currentMillis;  // сохраняем время последнего переключения
    long_delay_state = 0;
       counter++;      // увеличить счетчик на 1

     	 Serial.print("Counter=");
     Serial.println(counter);
     Serial.print("ledState=");     
     Serial.println(ledState);
     Serial.print("interval_delay=");
     Serial.println(interval_delay);
	   if (counter >= state_changes){
    
      long_delay_state = 1;
	  counter = 0;
	  }
     }
	}
void setup() {
Serial.begin(9400);
  // put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);
}

void loop() {
  // put your main code here, to run repeatedly:
LED_blinking(4);
}

Теперь работает! Наконец-то

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

ну, можно и так, хотя непонятно, зачем эта переменная? Что мешает прямо в строке 37 поменять величину интервала? Тогда строки с 13 по 18 и вашу новую переменную можно смело выкинуть из кода.

ven-til
Offline
Зарегистрирован: 13.02.2018

junior_developer пишет:

Теперь работает! Наконец-то

осталось избавится от 

ledState = !ledState;

и вернуть старую конструкцию

if (ledState == LOW)

ledState = HIGH;

else

ledState = LOW;

а то как-то не солидно, на фоне остального  раздувательства))))))

 

junior_developer
Offline
Зарегистрирован: 27.11.2017

b707 пишет:

ну, можно и так, хотя непонятно, зачем эта переменная? Что мешает прямо в строке 37 поменять величину интервала? Тогда строки с 13 по 18 и вашу новую переменную можно смело выкинуть из кода.

я попробовал "выкинуть" её, как Вы посоветовали, но программа после этого работает неправильно.
Обратите внимание ещё на строку 26. там эта переменная обнуляется.
то есть она нужна для того, чтобы понять, прошла ли длинная пауза.
Если прошла, то перейти к коротким вкл./ выкл. светодиода и т.д.
 

ven-til
Offline
Зарегистрирован: 13.02.2018

прошла ли длинная пауза проверяется вот тут if(currentMillis - previousMillis > interval_delay) больше проверок не нужно
Советы как сделать дали в #24 и #25.

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

junior_developer
Offline
Зарегистрирован: 27.11.2017

Сократил вот так:
 

const byte ledPin = 13; // пин светодиода
bool blink_enable = 1;  // разрешены ли мигания
byte counter = 0; // счетчик
byte state_changes;
unsigned long long_delay = 3000; // большая длительность
unsigned long short_delay = 500; // и маленькая
bool ledState = 0; // состояние LED 
long previousMillis = 0; // предыдущее время


void  LED_blinking (byte state_changes) {// это начало функции для мигания
unsigned long interval_delay = short_delay;
  
 
 unsigned long currentMillis = millis();  // считываем время в переменную currentMillis
 
   if(currentMillis - previousMillis > interval_delay) { // если время прошло...
    if (counter >= state_changes){
    
     interval_delay = long_delay;
     counter = 0;
 }

Serial.print("Counter=");
Serial.println(counter);
Serial.print("ledState=");     
Serial.println(ledState);
Serial.print("interval_delay=");
Serial.println(interval_delay);
     ledState = !ledState;
    digitalWrite(ledPin, ledState);  // меняем состояние светодиода
    previousMillis = currentMillis;  // сохраняем время последнего переключения
       counter++;      // увеличить счетчик на 1

       }
     }

void setup() {
Serial.begin(9400);
  // put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);
}

void loop() {
  // put your main code here, to run repeatedly:
LED_blinking(4);
}

Значения переменных увеличил в несколько раз, чтобы не мелькали при выводе через порт. Вместо 100 мс поставил 500, а вместо 1сек 3 сек. В итоге значение выводятся вроде правильно!  А вот светодиоду, кажется нет до них никакого дела - он просто мигает, то есть длительной паузы нету! Хотя, если смотреть через порт - ёё значение есть:

Вот, кому интересно:

Counter=0
ledState=0
interval_delay=500
Counter=1
ledState=1
interval_delay=500
Counter=2
ledState=0
interval_delay=500
Counter=3
ledState=1
interval_delay=500
Counter=0
ledState=0
interval_delay=3000
Counter=1
ledState=1
interval_delay=500
Counter=2
ledState=0
interval_delay=500
Counter=3
ledState=1
interval_delay=500
Counter=0
ledState=0
interval_delay=3000
Counter=1
ledState=1
interval_delay=500
Counter=2
ledState=0
interval_delay=500
Counter=3
ledState=1
interval_delay=500
Counter=0
ledState=0
interval_delay=3000

Очень странный глюк? Кто не верит, может загрузить код и убедиться сам!

ven-til
Offline
Зарегистрирован: 13.02.2018

Глюка нет. Строка 12 решает.

А теперь вопрос, что мешает сделать так как написали в #24 или #25?

junior_developer
Offline
Зарегистрирован: 27.11.2017

Вы имеете в виду вот так?

const byte ledPin = 13; // пин светодиода
//bool blink_enable = 1;  // разрешены ли мигания
byte counter = 0; // счетчик
byte state_changes;
unsigned long long_delay = 1000; // большая длительность
unsigned long short_delay = 200; // и маленькая
bool ledState = 0; // состояние LED 
long previousMillis = 0; // предыдущее время
unsigned long interval_delay = short_delay ;

void  LED_blinking (byte state_changes) {// это начало функции для мигания

  

unsigned long currentMillis = millis();  // считываем время в переменную currentMillis
 
   if(currentMillis - previousMillis > interval_delay) {// если время прошло...

    
    previousMillis = currentMillis;  // сохраняем время последнего переключения
    counter++;      // увеличить счетчик на 1    
  ledState = !ledState;
    digitalWrite(ledPin, ledState);  // меняем состояние светодиода
      if (counter >= state_changes){
      interval_delay = long_delay;
       counter = 0; }
       else {interval_delay = short_delay;}
  
     Serial.print("Counter=");
     Serial.println(counter);
     Serial.print("ledState=");     
     Serial.println(ledState);
     Serial.print("interval_delay=");
     Serial.println(interval_delay);
     
    }
     
  }
void setup() {
Serial.begin(9400);
  // put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);
}

void loop() {
  // put your main code here, to run repeatedly:
LED_blinking(4);
}

А вот если запихнуть эту проверку сразу после

if(currentMillis - previousMillis > interval_delay)

то есть переделать код так

const byte ledPin = 13; // пин светодиода
//bool blink_enable = 1;  // разрешены ли мигания
byte counter = 0; // счетчик
byte state_changes;
unsigned long long_delay = 1000; // большая длительность
unsigned long short_delay = 200; // и маленькая
bool ledState = 1; // состояние LED 
long previousMillis = 0; // предыдущее время
unsigned long interval_delay = short_delay ;

void  LED_blinking (byte state_changes) {// это начало функции для мигания

  

unsigned long currentMillis = millis();  // считываем время в переменную currentMillis
 
   if(currentMillis - previousMillis > interval_delay) {// если время прошло...
       if (counter >= state_changes){
       interval_delay = long_delay;
        counter = 0; }
       else {interval_delay = short_delay;}
    
    previousMillis = currentMillis;  // сохраняем время последнего переключения
    counter++;      // увеличить счетчик на 1    
  ledState = !ledState;
    digitalWrite(ledPin, ledState);  // меняем состояние светодиода
      
  
     Serial.print("Counter=");
     Serial.println(counter);
     Serial.print("ledState=");     
     Serial.println(ledState);
     Serial.print("interval_delay=");
     Serial.println(interval_delay);
     
    }
     
  }
void setup() {
Serial.begin(9400);
  // put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, ledState);
}

void loop() {
  // put your main code here, to run repeatedly:
LED_blinking(4);
}

то получается, что кототкий интервал вначале программы повторяется 4 раза, а затем постоянно только 3 раза!
 

Counter=1
ledState=0
interval_delay=200
Counter=2
ledState=1
interval_delay=200
Counter=3
ledState=0
interval_delay=200
Counter=4
ledState=1
interval_delay=200
Counter=1
ledState=0
interval_delay=1000
Counter=2
ledState=1
interval_delay=200
Counter=3
ledState=0
interval_delay=200
Counter=4
ledState=1
interval_delay=200
Counter=1
ledState=0
interval_delay=1000
Counter=2
ledState=1
interval_delay=200
Counter=3
ledState=0
interval_delay=200
Counter=4
ledState=1
interval_delay=200
Counter=1
ledState=0
interval_delay=1000

Кто-нибудь знает, в чем может быть причина?

ven-til
Offline
Зарегистрирован: 13.02.2018

junior_developer пишет:

Кто-нибудь знает, в чем может быть причина?

на первом круге counter стартует с 0, а на следующих с 1.
В 19 и 20 строках установка длинного интервала и сброс в 0, и тут же в 24 ++.