ARDUINO задержка без delay помогите.

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
А потому что ты не выложил свой код. А так мы больше угадываем и каждый пишет СВОЙ верный ответ. И гадать так можно до посинения.
 

Александр Симонов

★★★★✩✩✩
2 Авг 2018
727
208
Да может оно и так, да вот уже набралось 26 постов, но как говорили ( да посмотри, почитай) , а ответа так и не нашлось . Не кому не в обиду!
Похабыч предложил самое простое элегантное решение. Только он чуть-чуть ошибся в коде, правильно будет так:
C++:
if (temp <24) btnTimer = millis();

if ((millis() - btnTimer) > 2000) {
    digitalWrite(13, HIGH);
}
В btnTimer храним время, когда в последний раз температура была ниже пороговой (и постоянно обновляем это время). Соответственно, диод надо зажигать, если прошло больше ХХХ мс с этого времени.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
@Александр Симонов, Да, занят совсем другим не самым простым кодом и опчатки летят горой. Спасибо. А в коде там и прерывания на датчики. и вывод на экран каждый цикл.. там жопа.. и без пол литры не разобраться.

@Sascha., Вы не обижайтесь и не бросайте это дело. Понимание придет с практикой.
 

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
@Александр Симонов,
Ай да теска,ай да МОЛОДЕЦ !
Дорогие Вы мои, если бы Вы знали сколько я искал этот ответ!
Всем СПАСИБО!
Наконец то нашел форум где реально помогли, а то куда не сунешься , одно только хамство.
 

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
Доброго дня. Снова прошу помочь. Подсказка от Александра Симонова меня очень порадовала, но уткнулся в новый тупик, голова уже просто кипит.
Суть в том, что в данном коде нужен контроль температуры с задержкой. Если температура ниже 24 градуса пин 13 HIGH, пин 5 LOW, иначе температура выше 24 градусов пин 13 LOW , пин 5 HIGH. И при этом между переключениями должна быть задержка 2 секунды.
С оператором IF, все отлично получилось по подсказке Александра, а вот с оператором ELSE, тупик.
C++:
if (temp < 24) btnTimer = millis();

if  (millis() - btnTimer >= 2000)
{
    digitalWrite(13, HIGH);
    digitalWrite(5, LOW);
}
 else
{
    (temp > 24 ) ; 
    digitalWrite(13, LOW);
    digitalWrite(5, HIGH);
}
Александр Симонов
Александр к Вам вопрос, я не где не нашел объяснения такой конструкции оператора IF, после скобок прописываем btnTimer = millis(); и наш таймер хранит последнее время градуса ниже порогового, это с практики или я еще от этого далекий, просветите.
 

bort707

★★★★★★✩
21 Сен 2020
3,066
914
уткнулся в новый тупик
потому что не сами додумались, а получили готовенькое
Суть в том, что в данном коде нужен контроль температуры с задержкой. Если температура ниже 24 градуса пин 13 HIGH, пин 5 LOW, иначе температура выше 24 градусов пин 13 LOW , пин 5 HIGH. И при этом между переключениями должна быть задержка 2 секунды.
нужно ввести переменную состояния. Если темп ниже 24 - состояние, скажем, 1, а если выше = 0

А дальше все просто - на каждом ходе заново считываем состояние и сравниваем с предыдущим. Если состояние изменилось - запускаем таймер задержки (запоминаем миллис)
Вот и все, остальное легко написать на основе кода что дал @Александр Симонов
 

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
C++:
bool temp1 = (temp < 23);
bool temp2 = (temp > 23);
if (temp1 ) btnTimer = millis();

if  (millis() - btnTimer >= 2000)
{
    digitalWrite(13, HIGH);
    digitalWrite(5, LOW);
}   

  else
 
 if (temp2 )  btnTimer = millis();
  
 {
 if (millis() - btnTimer >= 2000) ;
 
    digitalWrite(13, LOW); 
    digitalWrite(5, HIGH);
 }
Не уверен, что правильно.
 

bort707

★★★★★★✩
21 Сен 2020
3,066
914
Не уверен, что правильно.
совсем нет. Оно даже компилироваться не будет

И идею вы не вполне поняли. Главное - это сравнить состояния
(temp < 23)
сейчас и на прошлом круге программы. А где вы такое делаете? - нигде
 

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
Компилируется нормально, только не работает это , да.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Сдается мне тут в корне неверный подход к удержанию температуры. Если @Sascha хочет таким образом избавиться от частого переключения... То надо почитать про гистерезис
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
Сдается мне тут в корне неверный подход к удержанию температуры. Если @Sascha хочет таким образом избавиться от частого переключения... То надо почитать про гистерезис
В точку попали. Может направите где почитать?
Тогда еще про усреднение и среднеквадратическое отклонение почитать. Где почитать спросите у гугла, он добрый и знает.
Ну и до кучи, если задача о поддержании температуры, то не мешало бы почитать про PID-регуляторы и их реализацию. Там в общем-то ничего сложного, но задачу поддержания регулируемой величины можно решить значительно лучше чем через тот же вариант bang-bang. :)
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Если грубо, то не делают границу четко на 24 градуса. если надо держать температуру 24, то приходят к некому соглашению, что 24.5 еще устроит, а 25 уже нет. И 23.5 уже устроит, а 23 уже нет. вот это градус называется гистерезис. И включать обогрев надо тогда, когда температура упадет до 23-х, а выключать когда превысит 25. И никаких заморочек со временем не нужно
 

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
почитать про PID-регуляторы
Это лишнее, здесь такой точности не нужно.
называется гистерезис
Это я тоже понимаю и пид регулятор понимаю, мне интересно как все это программно выполнять, уж больно закручена эта наука программирование, но интересна.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Я выше достаточно подробно написал.
Выключать нагрев при превышении верхнего порога, а включать когда значение температуры ниже нижнего порога. Все. Никаких задержек по времени.
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
Это лишнее, здесь такой точности не нужно.
Да я не особо про точность, а по большей мере по усреднению данных и отфильтровыванию случайных ошибок с датчика. Но дело ваше, хотя пид штука простая :)
 

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
C++:
if ((temp>23 ) && (temp>23.5))
{
    digitalWrite(13, HIGH);
    digitalWrite(5, LOW);
}   
else
 
if ((temp<23 ) && (temp <22.5))
{
     digitalWrite(13, LOW); 
     digitalWrite(5, HIGH);
}
И что всё, вот так просто можно решить?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Вот это извините бред ((temp>23 ) && (temp>23.5)) Если температура выше 23 и выше 23.5 это все равно что температура выше 23.5
То же по второму условию
Температура величина непрерывная. Я бы так оставил:
C++:
if (temp>23.5)
{
    digitalWrite(13, HIGH);
    digitalWrite(5, LOW);
}  
if (temp <22.5)
{
     digitalWrite(13, LOW);
     digitalWrite(5, HIGH);
}
Большинство задач решаются очень просто. а начинающие программисты (сам был таким) могут нагородить.. ну как у вас в коде. С прерываниями каждую миллисекунду и прочими плясками с бубном.
Вот вам вопрос: неужели есть такая необходимость опрашивать датчики 1000 раз в секунду ? вам нужно включение с точностью 0,001 ? или устроит 0.1 ?
 
  • Лойс +1
Реакции: Sascha.

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
опрашивать датчики 1000 раз в секунду
То, что прерывание один раз в миллисекунду взято из стандартного кода для датчика протока, я добавил лишь функцию pulsesi () ; и таким методом решил проблему сохранения в eeprom переменную liters. Так же добавил кнопку, для сброса eeprom. Как то так.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
Да, много шума из ничего. @Sascha., а Вам не приходило в голову, что перед началом изготовления какой-нибудь программы управления чем-либо, нужно хотя бы минимальную математическую модель составить? Любая система инерционна, @Старик Похабыч Вам для разъяснения подсказал про гистерезис, но это - частности, решив которые (вот незадача!) Вы ненамного приблизились к решению задачи. Задачи инерционных систем, при наличии обратной связи, как у Вас, решаются с использованием дифференциалов, ну, чтобы проще было - скоростей изменений величины и её соответствия среднему необходимому показателю. Причём, как правильно подсказал @kDn, ошибки в обратной связи тоже необходимо устранять, иначе будете дёргать мощный потребитель со скоростью несколько раз в миллисекунду плодя помехи и без особой реакции.
EEPROM - уязвимый элемент в данном перечне, так как имеет ограниченный ресурс перезаписей.
 

Sascha.

✩✩✩✩✩✩✩
15 Авг 2020
39
2
Вам не приходило в голову
Всем доброго дня. Я так понимаю Вы рассуждаете, как человек сточивший зубы в этой науке, я описывал в раннем посте, что это первый в моей жизни код, догадываюсь что не все там гладко, но не ошибается тот, кто не чего не делает. Для того и пытается человек что то познать, для того и общаемся на форумах, а не там где все знатоки, за что и благодарен вам , что помогаете, подсказываете, на путь истины направляете. Весь этот код работает, все ,что задумывал выполняет, сейчас и изучаю что бы улучшить и понять поболее.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
Речь-то шла не о том... О какой "науке" Вы говорите? О "кодировании" (некоторые называют это - программированием)? Тогда советую почитать, что это такое. Программирование позволяет перенести некоторую логику на систему, которая будет эту логику применять. Программист может и не быть специалистом в области, программу по автоматизации которой он пишет, но тогда ему должно быть поставлено корректное ТЗ.
Если речь шла о направлении управления технологическими процессами, то факт Вашего первого знакомства с программированием вообще отношения не имеет к делу. С программированием как раз помочь проблем нет. Но достигнете ли Вы цели? Код будет правильный, работать будет, но что он будет делать, если Вы, до написания этого кода не озаботились ознакомлением с автоматизируемой предметной областью?
 

Arhat109

★★★★✩✩✩
9 Июн 2019
473
203
Рекомендую такой макрос:
C:
#define everyMillis(interval, action) \
{                                     \
  static unsigned long t = 0UL;       \
  if( millis() - t > (interval) )     \
  {                                   \
    { action; }                       \
    t = millis();                     \
  }                                   \
}
Сильно упрощает жизнь с разными "блин без делей" .. :)
Применение примитивно:
C:
everyMillis(1000,
{
   pinOut(pinLed, 1-digitalRead(pinLed));
   analogWrite(pwm12, analogRead(pin54)>>4);
});

// или так:
everyMillis(1000, blink() );
То есть вставляем или прямо внутрь блок кода в фигурных скобках (а-ля js) или вызов функции, но .. без завершающей точки с запятой.

В частности, для включения/выключения с гистерезисом можно изменить так:

C:
// вариант макроса для флага состояния и времени гистерезиса:
// 1. статические переменные локальны внутри блока (у каждого - свои!) макроса и не доступны извне!
// 2. вн. переключатель "f" разрешает фиксировать время начала отсчета только 1 раз!
// 3. отсчет интервала начинается от момента вызова с условием flag=true
#define gistMillis(flag, interval, action) \
{                                          \
  static unsigned long t = 0UL;            \
  static unsigned char f = 0;              \
  if( flag && !f ){ t = millis(); f=1; }   \
  if( millis() - t > (interval) )          \
  {                                        \
    { action; }                            \
    t = millis();                          \
    f = 0;                                 \
  }                                        \
}
// применение:
void devOn(){ /* функция включения чего надо */ }
void devOff(){ /* тут выключаем чего надо */ }

void loop(void){
    // .. тут что-то делаем свое, личное
    gistMillis( devTemprature < 23.0, 2000, devOn() );  // включаем с задержкой 2сек.
    gistMillis( devTemprature > 23.0, 2000, devOff() ); // выключаем через 2сек.
   
    // .. вариант гистерезиса по значению:
    gistMillis( devTemprature < 23.0, 0, devOn() );  // включаем сразу.
    gistMillis( devTemprature > 25.0, 0, devOff() ); // выключаем тоже.
}
 
Изменено: