Выполнение кода во время задержки

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Доброго времени суток! Наверняка я не первый тут с таким вопросом, но всё же. 
Есть следующее железо: ардуино нано, реле (питает помпу) и датчик хола (у меня пока в место него обычная кнопка, для теста)

Задача следующая: вкл реле, дать ему поработать 25 сек, в это время считать количество срабатывания датчика хола (кнопки) и записывать его в переменную, затем выключить реле

Собственно вопрос: как сделать несколько процессов одновременно? Тот же delay "тормозит" мозги и паралельно ничего не сделать. То есть держать цифровой пин активным, считать инфу с датчика и записывать в переменную? Как сделать всё отдельно - знаю, а одновременно - увы.

Вот пример из того что сейчас работает просто через delay(), там нет работы с датчиком и тд. только вкл/выкл пин по таймеру. Не судите строго по качеству кода. Второй вечер разбираюсь что тут и как.

 

void start_filling() {
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   delay(25000);
   // (тут нужно пыполнить другой код пока идут 25 сек)
   digitalWrite(PIN_RELAY, LOW);
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print("Помпа ВЫКЛ.");
}


Благодарю! 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Сравните blink и blink without delay.

Второй делает именно то, что Вам нужно.

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Нашел примеры в которых в цикле мигают лампочкой. Но мне не нужен цикл. Эта часть кода - один из void`ов, которые запускаются при определённых условиях и должен выполниться лишь раз

-NMi-
Offline
Зарегистрирован: 20.08.2018

Если уж прям-прям с точностью до миллисекунд - смотри в сторону RtOs. Для AVR они есть.   :))

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Та не) +- трамвайная остановка тоже подойдёт. там супер точность не важна. главное сам момент одноразового выполнения кода во время работы таймера

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Ju4ka пишет:

Нашел примеры в которых в цикле мигают лампочкой. Но мне не нужен цикл. Эта часть кода - один из void`ов, которые запускаются при определённых условиях и должен выполниться лишь раз

Очень просто: после выполнения нужного Вам участка кода, поднимаете  флаг. А в цикле loop() проверяете, поднят ли флаг. Если да - пропускаете, если нет - выполняете.

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Дим-мычъ пишет:

Ju4ka пишет:

Нашел примеры в которых в цикле мигают лампочкой. Но мне не нужен цикл. Эта часть кода - один из void`ов, которые запускаются при определённых условиях и должен выполниться лишь раз

Очень просто: после выполнения нужного Вам участка кода, поднимаете  флаг. А в цикле loop() проверяете, поднят ли флаг. Если да - пропускаете, если нет - выполняете.

Не совсем понимаю как завязать это дело на времени.
Не могли бы вы показать пример на основе того кода что я оставил? Благодарю

nik182
Offline
Зарегистрирован: 04.05.2015

Объявляешь две булевых переменных флаги времени и выполнения. Флаги опускаешь - false. Ждёшь команды включения помпы. Вкючил помпу, поднял флаг -true помпа включена, запомнил время. Делаешь что нужно если флаг времени поднят, флаг выполнено опущен, в конце ставиш флаг выполено. Если флаг времени поднят проверяешь сколько времени прошло. Если (IF) меньше чем надо и не надо ещё раз что то делать то просто идёшь в начало цика. Если больше, выключаешь помпу, снимаешь флаги, ждёшь следующей команды включения помпы.

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Про идею с флагами всё понял, спасибо. Но как описать это в коде - не хватает опыта. Второй день постигаю всё это. Пожалуйста, дайте пример. Спасибо!

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Ju4ka пишет:

Доброго времени суток! Наверняка я не первый тут с таким вопросом, но всё же. 
Есть следующее железо: ардуино нано, реле (питает помпу) и датчик хола (у меня пока в место него обычная кнопка, для теста)

Задача следующая: вкл реле, дать ему поработать 25 сек, в это время считать количество срабатывания датчика хола (кнопки) и записывать его в переменную, затем выключить реле

Собственно вопрос: как сделать несколько процессов одновременно? Тот же delay "тормозит" мозги и паралельно ничего не сделать. То есть держать цифровой пин активным, считать инфу с датчика и записывать в переменную? Как сделать всё отдельно - знаю, а одновременно - увы.

Вот пример из того что сейчас работает просто через delay(), там нет работы с датчиком и тд. только вкл/выкл пин по таймеру. Не судите строго по качеству кода. Второй вечер разбираюсь что тут и как.

 

void start_filling() {
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   delay(25000);
   // (тут нужно пыполнить другой код пока идут 25 сек)
   digitalWrite(PIN_RELAY, LOW);
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print("Помпа ВЫКЛ.");
}
Благодарю! 

Ну если по ТЗ ТС то проще всего так :-)

uint16_t Counter;

void start_filling() {
   Counter=0;
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   delay(25000);   // (тут выпоняется  другой код пока идут 25 сек)
   
   if (Counter <= 25)
   {
		//делаем что то
   }
   digitalWrite(PIN_RELAY, LOW);
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print("Помпа ВЫКЛ.");
}

void yield()      // (тут выпоняется  другой код пока идут 25 сек)
{
	if(  )   // если кнопка  нажата
	{
		Counter++;
	}
}

 

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Я так понимаю в yield (знаю как он работает) у нас идёт таймер который раз в секунду добавляет +1 к значению, а в 11 строке условие по которому если меньше, или равно 25, то делаем нужный код. И таким образом через yield "обходим" ограничение работы с обычным "delay". Я верно понял? Просто хочу для себя понять, а не просто готовый код взять

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Ju4ka пишет:
Я так понимаю в yield (знаю как он работает) у нас идёт таймер который раз в секунду добавляет +1 к значению, а в 11 строке условие по которому если меньше, или равно 25, то делаем нужный код. И таким образом через yield "обходим" ограничение работы с обычным "delay". Я верно понял? Просто хочу для себя понять, а не просто готовый код взять

Нет.

yield() крутится как loop() пока delay(25000) отсчитывает свои 25 секунд и тормозит весь последующий код.

Если в в yield() нужен секундный таймер он делается на millis() 

Ju4ka
Offline
Зарегистрирован: 27.09.2022

То есть в 13 строке я пишу код и он будет исполнятся только пока идут те 25 сек, или нужный мне код нужно писать в yield? Если нужно писать в yield, то будет ли работать код написанный в 13 строке, или он будет ждать окончания delay?

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Ju4ka пишет:
То есть в 13 строке я пишу код и он будет исполнятся только пока идут те 25 сек, или нужный мне код нужно писать в yield? Если нужно писать в yield, то будет ли работать код написанный в 13 строке, или он будет ждать окончания delay?

Код в строке 13 выполнится после выхода из delay(25000) - то есть через 25 секунд.

Пока идут эти 25 секунд буде постоянно вызываться yield()  и в yield() уже тормозить нельзя. НИКАКИХ delay() там быть не должно.

Если в yield нужно что то проверять раз в секунду нужно использовать millis()

Примерно так:

void yield()
{
  static unsigned long previousMillis = 0;

  if ( millis() - previousMillis >= 1000) 
  {
    previousMillis = millis();
    // делаем тут что то раз в секунду но без delay()
  }
}

   

nik182
Offline
Зарегистрирован: 04.05.2015

Не надо delay. вместо него взять код из yield()

  if ( millis() - previousMillis >= 1000) 
  {
    previousMillis = millis();
    // делаем тут что то раз в секунду но без delay()
  }
вокруг него обернуть через  do while
 
  digitalWrite(PIN_RELAY, HIGH);
  TimeStartPomp=previousMillis= millis();
  do
    if ( millis() - previousMillis >= 1000) 
    {
      previousMillis = millis();
      // делаем тут что то раз в секунду но без delay()
    }
   while ( millis() - TimeStartPomp <=25000);
   digitalWrite(PIN_RELAY, LOW);

Не проверял, только идея.

 

 
Ju4ka
Offline
Зарегистрирован: 27.09.2022

сделал так: 
 

void start_test() {
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   delay(25000);
   if (Counter <= 25) {
	  digitalWrite(PIN_RELAY, LOW);
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("Помпа ВЫКЛ.");}
}

void yield()
{
  static unsigned long previousMillis1 = 0;

  if ( millis() - previousMillis1 >= 1000) 
  {
    previousMillis1 = millis();
    Counter++;
  }

  static unsigned long previousMillis2 = 0;

  if ( millis() - previousMillis2 >= 10) 
  {
    previousMillis2 = millis();
    btn2.tick();
    if (btn2.click()) {return_counter++;} 
  }

}

Но весь процесс останавливается на lcd.print("Помпа ВКЛ."); и всё. Больше на дисплее информация не появляется 

Ju4ka
Offline
Зарегистрирован: 27.09.2022

ругается на 
 



error: 'TimeStartPomp' was not declared in this scope
    TimeStartPomp=previousMillis= millis();
    ^~~~~~~~~~~~~

и

error: 'previousMillis' was not declared in this scope
    TimeStartPomp=previousMillis= millis();
                  ^~~~~~~~~~~~~~

сам код следующий: 
 

void start_test() {
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   digitalWrite(PIN_RELAY, HIGH);
   TimeStartPomp=previousMillis= millis();
   do
    if ( millis() - previousMillis >= 10) 
    {
      previousMillis = millis();
      btn2.tick();
       if (btn2.click()) {return_counter++;} 
    }
    while ( millis() - TimeStartPomp <=25000);
    digitalWrite(PIN_RELAY, LOW);
    oborotu();
}

 

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Ju4ka пишет:

ругается на 
 



error: 'TimeStartPomp' was not declared in this scope
    TimeStartPomp=previousMillis= millis();
    ^~~~~~~~~~~~~

и

error: 'previousMillis' was not declared in this scope
    TimeStartPomp=previousMillis= millis();
                  ^~~~~~~~~~~~~~

сам код следующий: 
 

void start_test() {
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   digitalWrite(PIN_RELAY, HIGH);
   TimeStartPomp=previousMillis= millis();
   do
    if ( millis() - previousMillis >= 10) 
    {
      previousMillis = millis();
      btn2.tick();
       if (btn2.click()) {return_counter++;} 
    }
    while ( millis() - TimeStartPomp <=25000);
    digitalWrite(PIN_RELAY, LOW);
    oborotu();
}

 

 

конечно ругается. таймеры то в 0 не выставил. сейчас код выглядит так:
 

void start_test() {
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   digitalWrite(PIN_RELAY, HIGH);
   static unsigned long TimeStartPomp = 0;
   static unsigned long previousMillis = 0;
   TimeStartPomp=previousMillis= millis();
   do
    if ( millis() - previousMillis >= 10) 
    {
      previousMillis = millis();
      btn2.tick();
       if (btn2.click()) {return_counter++;} 
    }
    while ( millis() - TimeStartPomp <=25000);
    digitalWrite(PIN_RELAY, LOW);
    oborotu();
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Переменные надо описывать до использования. Для кнопки взял титановый велосипед.

https://github.com/Klapautsiy/titanium-bicycle-for-button/releases/tag/B...

#include <Button.h>

#define PIN_RELAY 5
unsigned long TimeStartPomp, previousMillis;

Button test;

void setup() {
  pinMode( PIN_RELAY, OUTPUT); 
 

  test.NO(); // N.O. Normal Open

  test.pullUp();

  test.duration_bounce       (  50);
  unsigned long duration_check = 200;
  test.duration_click_Db     (duration_check);
  test.duration_inactivity_Up(duration_check);
  test.duration_press        ( 500);

  test.button(18); // arduino pins connected to button


}

void loop() {
  if (test.event_click_Up     (0) == 1) { //При отпускании кнопки после нажатия начинается цикл
  digitalWrite(PIN_RELAY, HIGH);
  TimeStartPomp = previousMillis = millis();
  do
    if ( millis() - previousMillis >= 1000)
    {
      previousMillis = millis();
      // делаем тут что то раз в секунду но без delay()
    }
  while ( millis() - TimeStartPomp <= 25000);
  digitalWrite(PIN_RELAY, LOW);

}
}

 

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Сильно палками не стукайте, но сейчас код такой:

#define _LCD_TYPE 1
#define PIN_RELAY 7
#include <EncButton.h>
EncButton<EB_TICK, 9> btn4(INPUT_PULLUP);  // yes
EncButton<EB_TICK, 8> btn3(INPUT_PULLUP);  // no
EncButton<EB_TICK, 2> btn2(INPUT_PULLUP);
EncButton<EB_TICK, 3> btn1(INPUT_PULLUP);  // enter

#include <LCD_1602_RUS_ALL.h>
LCD_1602_RUS lcd(0x20, 16, 2);

uint16_t return_counter;

void setup() {
    pinMode(PIN_RELAY, OUTPUT);
    lcd.init();           // инициализация
    lcd.backlight();      // включить подсветку
    lcd.setCursor(0, 0);   
    lcd.print("Тестер турбинок");
    delay(500);
    lcd.setCursor(0, 1);  
    lcd.print("и редуктора ЗУ");
    delay(1000);
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("тут что-то будет");
    lcd.setCursor(1, 1);
    lcd.print("Версия ПО: 1.0");
    delay(3000);
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("Начать тест?");
}

void loop() {
    btn1.tick();
    if (btn1.click()) {start_test_info();} 
}

void start_test_info() {
       lcd.clear();
       lcd.setCursor(0, 0);
       lcd.print("Заполнение...");
       delay(1000);
       lcd.setCursor(0, 1);
       lcd.print("Ожидайте...");
       delay(500);
       start_filling();
       lcd.clear();
       lcd.setCursor(0, 0);
       lcd.print("Готово");
       lcd.write(33);
       delay(1000);
       lcd.setCursor(0, 1);
       lcd.print("Начинаем тест...");
       delay(2000);
       start_test();
}

void start_test() {
   digitalWrite(PIN_RELAY, HIGH);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("Помпа ВКЛ.");
   digitalWrite(PIN_RELAY, HIGH);
   static unsigned long TimeStartPomp = 0;
   static unsigned long previousMillis = 0;
   TimeStartPomp=previousMillis= millis();
   do
    if ( millis() - previousMillis >= 10) 
    {
      previousMillis = millis();
      btn2.tick();
       if (btn2.click()) {return_counter++;} 
    }
    while ( millis() - TimeStartPomp <=25000);
    digitalWrite(PIN_RELAY, LOW);
    oborotu();
}

void start_filling() {
  digitalWrite(PIN_RELAY, HIGH);
  delay(15000);
  digitalWrite(PIN_RELAY, LOW);

}

void oborotu() {

       lcd.clear();
       lcd.setCursor(1, 0);
       lcd.print("Оборотов: ");
       lcd.write(return_counter);
}   

И оно работает! И я даже понимаю почему! (сам удивлён)

Всем огромное спасибо! 

nik182
Offline
Зарегистрирован: 04.05.2015

74 строка как задумано?

Ju4ka
Offline
Зарегистрирован: 27.09.2022

она выключается на 77. на самом деле +- немного это не важно. главное что бы всегда было одинаково 

nik182
Offline
Зарегистрирован: 04.05.2015

Не понятно зачем. Раз в секунду за 25 секунд будет 25. Или тут будет что то другое?

Ju4ka
Offline
Зарегистрирован: 27.09.2022

nik182 пишет:

74 строка как задумано?

по факту там не кнопка, а будет датчик хола. кнопка там для удобного теста в протеусе

(железо ещё не доехало)

Ju4ka
Offline
Зарегистрирован: 27.09.2022

там раз в 10 мс опрашивается кнопка (которая датчик хола) и если она активна - то пишет +1 в счётчик, а через 25 сек помпы выкл и всё что насчитало за 25 сек выводит на дисплей

 

nik182
Offline
Зарегистрирован: 04.05.2015

А зачем датчик Холла по времени? Если считать обороты, то наоборот надо ловить фронты датчика через прерывание и считать их в прерывании. Совсем не внутри цикла. Тогда можно по второй кнопке можно отключать помпу и выходить из цикла раньше в случае необходимости через return. 

Ju4ka
Offline
Зарегистрирован: 27.09.2022

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

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

    while ( millis() - TimeStartPomp <=25000);

тот же delay(), тока вид сбоку

nik182
Offline
Зарегистрирован: 04.05.2015

Но мы в нутри этого делея и можем его в любой момент прервать.

Ju4ka
Offline
Зарегистрирован: 27.09.2022

Вот-вот. То что мне и нужно было!

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

nik182 пишет:
Но мы в нутри этого делея и можем его в любой момент прервать.

внимательно посмотри на строчку, которую я написал.  В каком мы нутре?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
void delay(unsigned long ms)
{
	uint32_t start = micros();

	while (ms > 0) {
		yield();
		while ( ms > 0 && (micros() - start) >= 1000) {
			ms--;
			start += 1000;
		}
	}
}
void yield(void) __attribute__ ((weak, alias("__empty")));

Код выше скопирован из исходников - yield объявлена как weak ...

Переобъявляем yield и получаем активность внутри delay ..

https://wokwi.com/projects/343926146113471058

Главное не переусердствовать - delay вызывается не только в вашем коде, но и внутри Arduino Core и многих библиотек. Ваш код из yield будет срабатывать на все эти вызовы !!!

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Помогать ТС'у прикрутить костыли к его изначально ошибочной конструкции , это такой тонкий троллинг ?

Kakmyc
Offline
Зарегистрирован: 15.01.2018
boolean testFlag = 0;

void start_test_info() {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Заполнение...");
    delay(1000);
    lcd.setCursor(0, 1);
    lcd.print("Ожидайте...");
    delay(500);
    start_filling();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Готово");
    lcd.write(33);
    delay(1000);
    lcd.setCursor(0, 1);
    lcd.print("Начинаем тест...");
    delay(2000);
    // start_test();
    testFlag = 1;
}

void start_test() {
    digitalWrite(PIN_RELAY, HIGH);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Помпа ВКЛ.");
    digitalWrite(PIN_RELAY, HIGH);
    if (millis() - TimeStartPomp >= 25000) {
        lcd.setCursor(0, 0);
        lcd.print("Помпа ВЫКЛ");
        digitalWrite(PIN_RELAY, LOW);
        testFlag = 0;
    }

    btn2.tick();
    if (btn2.click()) {
        return_counter++;
    }
    oborotu();
}



void loop() {
if(/*условие на старт теста*/ && testFlag == 0) {
start_test_info();
TimeStartPomp = millis();
}

if(testFlag == 1) {
start_test();
}

}

 

nik182
Offline
Зарегистрирован: 04.05.2015

DetSimen пишет:

внимательно посмотри на строчку, которую я написал.  В каком мы нутре?


Мы в внутри от do до while. И самое главное отличие нам не нужен йелд, что бы что то делать дополнительно, а следовательно мы можем прервать этот delay в любой момент, если потребуется.

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

АААААА, там do-while, это значит, что это я тупой спрасони.  Прошу пардону. 

nik182
Offline
Зарегистрирован: 04.05.2015

Kakmyc пишет:

А зачем на каждом прохождение лупа вызывать обороты?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

nik182 пишет:
Kakmyc пишет:

А зачем на каждом прохождение лупа вызывать обороты?

Я так захотел , потому что.
Захоти не вызывать и не вызывай.

nik182
Offline
Зарегистрирован: 04.05.2015

Komandir пишет:
Главное не переусердствовать - delay вызывается не только в вашем коде, но и внутри Arduino Core и многих библиотек. Ваш код из yield будет срабатывать на все эти вызовы !!!

И ещё из yield нельзя прервать delay. А свой delay из do while можно. И внутри своего можно резвиться как угодно.

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

Аппаратный счетчик-самое простое решение как по мне

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Ju4ka пишет:

Собственно вопрос: как сделать несколько процессов одновременно?

https://arduino.ru/forum/programmirovanie/upravlenie-neskolkimi-protsess...

SLKH
Offline
Зарегистрирован: 17.08.2015

SergeiL пишет:

 


void yield()      // (тут выпоняется  другой код пока идут 25 сек)
{
	if(  )   // если кнопка  нажата
	{
		Counter++;
	}
}

 

Подсунуть ТСу с его представлениями о программировании yield'ы - садизм.

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

SLKH пишет:

SergeiL пишет:

 


void yield()      // (тут выпоняется  другой код пока идут 25 сек)
{
	if(  )   // если кнопка  нажата
	{
		Counter++;
	}
}

 

Подсунуть ТСу с его представлениями о программировании yield'ы - садизм.

Так так у него был поставлен вопрос. Это самое простое и короткое решение для его кода. Меньше всего переделок.

На Амперке мы уже обсуждали как можно использовать делай с возможностью выхода из него по решению из yield()

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Ju4ka пишет:
Дим-мычъ пишет:

Ju4ka пишет:

Нашел примеры в которых в цикле мигают лампочкой. Но мне не нужен цикл. Эта часть кода - один из void`ов, которые запускаются при определённых условиях и должен выполниться лишь раз

Очень просто: после выполнения нужного Вам участка кода, поднимаете  флаг. А в цикле loop() проверяете, поднят ли флаг. Если да - пропускаете, если нет - выполняете.

Не совсем понимаю как завязать это дело на времени. Не могли бы вы показать пример на основе того кода что я оставил? Благодарю

Вчера не ответил, спал уже почти...

Вот пример с одним флагом



#define Sens A0
unsigned long last_millis = 0;
unsigned long last0_millis = 0;
int timer = 0;
bool Pomp_flg = false;

void setup() {
  pinMode(Sens, INPUT_PULLUP);
  Serial.begin(9600);
  delay(300);
}

void loop() {
  if ((millis() - last_millis) >= 10)  {
    last_millis = millis();
    if ((!digitalRead(Sens)) && !Pomp_flg) { //если была
      Pomp_flg = true; //нажата кнопка
      Serial.println("ON");//включили помпу
    }
    if (Pomp_flg)
      timer++;
    if (timer == 2500) {
      timer = 0;
      Pomp_flg = false;
      Serial.println("OFF"); //выключили помпу
    }
  }

  //остальной код
  if ((millis() - last0_millis) >= 1000)  {
    last0_millis = millis();
    Serial.println("Rabotaet osnovnoi kod");
  }
}

P.S Это как вставить код , что был вначале темы


#define Sens A0
unsigned long last_millis = 0;
unsigned long last0_millis = 0;
int timer = 0;
bool Pomp_flg = false;

void setup() {
  pinMode(Sens, INPUT_PULLUP);
  Serial.begin(9600);
  delay(300);
}

void loop() {
  if ((millis() - last_millis) >= 10)  {
    last_millis = millis();
    if ((!digitalRead(Sens)) && !Pomp_flg) { //если была
      Pomp_flg = true; //нажата кнопка
      Serial.println("ON");//включили помпу
     // здесь код до паузы
     //  digitalWrite(PIN_RELAY, HIGH);
     //  lcd.clear();
     //  lcd.setCursor(0, 0);
     //  lcd.print("Помпа ВКЛ.");
    }
    if (Pomp_flg)
      timer++;
    if (timer == 2500) {
      timer = 0;
      Pomp_flg = false;
      Serial.println("OFF"); //выключили помпу      
     // здесь код после паузы
     //  digitalWrite(PIN_RELAY, LOW);
     //  lcd.clear();
     //  lcd.setCursor(0, 1);
     // lcd.print("Помпа ВЫКЛ.");
    }
  }

  //остальной код
  if ((millis() - last0_millis) >= 1000)  {
    last0_millis = millis();
    Serial.println("Rabotaet osnovnoi kod");
  }
}

 

Gromozeka
Offline
Зарегистрирован: 06.10.2022

С millis для систем которые не планируется выключать - т.е они работают месяцами будет баг если не учитывать что раз в несколько 10-ков часов в том же Nano (там по разному) будет wraping т.е. millis возвращает число миллисекунд со старта - и размерность переполнится. Читал, что в Nano что-то вроде от 54 часов до 7 дней вроде в разных версиях. 

Поэтому если наступит переполнение - от новые данные millis после перехода из-за переполнения на 0 - будут всегда меньше старых если те взяты непосредственно перед переполнением. Система никогда не дождется той самой 1 секунды и залипнет в том состоянии которое было перед этой ситуацией. Стоит дописать проверку - что если после число меньше чем перед - то учесть число остатка или (если не важна точность) число миллисекунд перед обнулить. 

Такой баг будет не всегда, отследить будет трудно, система будет зависать раз в случайное число дней (или недель). 

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

опять великое переполнение миллис )))

Gromozeka
Offline
Зарегистрирован: 06.10.2022

ua6em пишет:

опять великое переполнение миллис )))

В 32 битной системе максимум 

4294967295/1000 = 4294967 секунд / 60 = 71582  минут /60  = 1193 часа / 24 = 49 суток. 

Я полагаю, что конроль за такими вещами как температура в комнате с использованием котла на газе или палетах -будет работать на большей территории России в течении 4-6 месяцев в зависимости от региона. Вероятность что вы не отключите нагрев котла вас не пугает? 

 

-NMi-
Offline
Зарегистрирован: 20.08.2018

Ну, йоптЭ, приведи пример в коде, кто_ж мешает то, Апсудим, чО. Ни_ачкуешЪ???

Gromozeka
Offline
Зарегистрирован: 06.10.2022

-NMi- пишет:

Ну, йоптЭ, приведи пример в коде, кто_ж мешает то, Апсудим, чО. Ни_ачкуешЪ???

Хорошая попытка но нет. Сам все сам. 

-NMi-
Offline
Зарегистрирован: 20.08.2018

Это изначально было очевидно.    ))))))))))))))))))))

Gromozeka
Offline
Зарегистрирован: 06.10.2022

-NMi- пишет:

Это изначально было очевидно.    ))))))))))))))))))))

Да - ты победитель, теперь все?