Часы с прерыванием

Ain777

✩✩✩✩✩✩✩
14 Авг 2020
10
0
Всем привет! Есть библиотека таймера GyverTimer, на её основе делаю часы с отображением даты. Есть функция проверки заряда батарейки, если низкий то начинает "пищать" пищалка в течении 5 секунд. Проблема в том что после пищалки эти 5 секунд не учитываются потому как запускается цикл while.
Вопрос: Как обойти проблему, чтобы после срабатывания пищалки время работало правильно?
C++:
if (tmr.isReady()){
      seconds++;
      if(seconds > 59){
      mins ++;
      if (mins > 59) {
        mins = 0;
        hrs++;
        if (hrs > 23) {
             hrs = 0;
             day++;
          for(int i = 0; i < 11; i++){
            if(leap_years[i] == year) year_flag = true;
            else year_flag = false;
          }
            if (year_flag && mounth == 02 && day == 29) {day = 1; mounth = 3;}
            else if ((mounth == 1 || mounth == 3 || mounth == 5 || mounth == 7 || mounth == 8 || mounth == 10 || mounth == 12) && day > 31) {day = 1; mounth++;}
            else if ((mounth == 4 || mounth == 6 || mounth == 9 || mounth == 11) && day > 30) {day = 1; mounth++;}
            else mounth++;
          if(mounth > 12){
            mounth = 1;
            year++;
          }
         }
      }
      }
      disp.displayClockTwist(hrs, mins, 35);
    }
Пищалка:
 Now = millis();
while (millis () - Now < 5000) {
            tone(piezo_pin, 500);
            delay(500);
            noTone(piezo_pin);
            delay(250);
        }
 

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

★★★★★★★
14 Авг 2019
4,185
1,280
Москва
Привяжи все к абсолютным значениям millis например. Но пищать тогда, когда у тебя батарейка сдыхает так себе идея
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,281
947
58
Марий-Эл
Так себе идея делать такие часы.
Но для общего развития пойдёт.
Когда произошла аварийная ситуация, нужно поднять флаг и обнулить переменную - счётчик. (предопределённые ранее)
В цикле, где происходит счёт секунд, если флаг поднят, врубаешь пищалку и делаешь инкремент переменной.
Если переменная равна 5, сбрасываешь флаг и вырубаешь пищалку. Что бы сигнал был прерывистый, можно в ветке, которая следит за пищанием
инвертировать выход. При каждом приращении счётчика. Нужно только не забыть выключить. И сигнал будет с секундным интервалом правда.



@Старик Похабыч, У меня старый смартфон при понижении заряда ниже порогового врубал сигнал и выводил на экран красивую картинку. После чего погибал с бульканьем в динамиках.
 

Ain777

✩✩✩✩✩✩✩
14 Авг 2020
10
0
@Эдуард Анисимов, это я как пример, устройство которое задумано, много чего делает. Просто добавил как дополнение часы. Как я понимаю ты предлагаешь нечто такое:
Пример:
boolean flag = false;
unsigned long tmr; //Таймер
unsigned long buzzer_timer = 5000;
float bat; //Перемернная батарейки

void loop(){
    if (millis() - tmr > 1000) { 
      seconds++;
      if(flag == tue){
          buzzerVoid();
      }
      if(seconds > 59){
      mins ++;
      if (mins > 59) {
        mins = 0;
        hrs++;
        if (hrs > 23) {
             hrs = 0;
             day++;
          for(int i = 0; i < 11; i++){
            if(leap_years[i] == year) year_flag = true;
            else year_flag = false;
          }
            if (year_flag && mounth == 02 && day == 29) {day = 1; mounth = 3;}
            else if ((mounth == 1 || mounth == 3 || mounth == 5 || mounth == 7 || mounth == 8 || mounth == 10 || mounth == 12) && day > 31) {day = 1; mounth++;}
            else if ((mounth == 4 || mounth == 6 || mounth == 9 || mounth == 11) && day > 30) {day = 1; mounth++;}
            else mounth++;
          if(mounth > 12){
            mounth = 1;
            year++;
          }
         }
      }
      }
      disp.displayClockTwist(hrs, mins, 35);
    }
}
void buzzerVoid(){
    Now = millis();
    flag = true;
    tmr = 0;
    while (millis () - Now < buzzer_timer) {
            tone(piezo_pin, 500);
            delay(500);
            noTone(piezo_pin);
            delay(250);
        }

}
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,281
947
58
Марий-Эл
Нет.
buzzerVoid();
Подвесит опять всё. Использовать задержки нельзя.
И ещё одна нехорошая вещь. Если я не ошибаюсь
tone(piezo_pin, 500);
использует прерывание, которое использует таймер. У тебя могут пересечься функции используещее это прерывание.
Не нужно использовать пьезопищалку. Геммор лишний. Лучше использовать вот такую штуку
1602323011871.png
Ей достаточно подать питание, она начнёт пищать.
А учше это делать на BluePill.
Там таймеров столько, что на всю жизнь хватит.
Достаточно подключить пищалку к таймеру и запрограммировать его.
В таймер можно прописать сколько раз пищать, длительность писков и пауз.
А запуск производится просто запуском таймера. Он сам остановится когда надо.
Да и часы там встроенные прямо на кристалле.
 
Изменено:

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

★★★★★★★
14 Авг 2019
4,185
1,280
Москва
функция tone может принимать не только пин и частоту, но еще и длительность сигнала. Тогда не нужны будут delay . Там будут другие вопросы, как сделать 3 раза писка с промежутком в 0.5 сек. Но это тоже решаемо
 

Ain777

✩✩✩✩✩✩✩
14 Авг 2020
10
0
Нет.
buzzerVoid();
Подвесит опять всё. Использовать задержки нельзя.
И ещё одна нехорошая вещь. Если я не ошибаюсь
tone(piezo_pin, 500);
использует прерывание, которое использует таймер. У тебя могут пересечься функции используещее это прерывание.
Не нужно использовать пьезопищалку. Геммор лишний. Лучше использовать вот такую штуку
Посмотреть вложение 16969
Ей достаточно подать питание, она начнёт пищать.
Ок, а как лучше цикл записать через for, ещё чтобы учесть 5 секунд? Спасибо за подсказку по поводу tone.

функция tone может принимать не только пин и частоту, но еще и длительность сигнала. Тогда не нужны будут delay . Там будут другие вопросы, как сделать 3 раза писка с промежутком в 0.5 сек. Но это тоже решаемо
Думаю лучше без tone. Только осталось додуматься как сделать цикл на 5 секунд, без задержки, потому как while все задерживает.
 

bort707

★★★★★★✩
21 Сен 2020
2,894
860
осталось додуматься как сделать цикл на 5 секунд, без задержки,
не надо цикл делать вообще. Ни for, ни while...
У тебя и так в программе есть цикл - называется loop() - вот в нем и проверяй время, пока 5 секунд не пройдет
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
То ли я совсем того, но всё же каким образом переменная flag может стать истиной. Если уж часть кода постить, то наверное лучше выкинуть в отдельный листинг, который хотя бы работает.....
Если совсем заклинило, то мне кажется до Вас пытаются донести нечто подобное (не не факт):
Сразу в самом начале loop проверяешь флаг дохлой батарейки, далее, если батарейка подыхает, то надо включить пищалку и запомнить её время включения, но сделать это надо ровно один раз.
При следующем цикле loop должен уже проверять сколько времени пищит бузер и соответственно делать с ним манипуляции, ну чтоб не просто 5 секунд подряд пищал, а пищал как задумано, с паузами.
А вот после 5ти секунд надо просто отключить бузер и сделать так, чтобы эти условия никогда не запускались, допустим сказать что батарейка в нормальном состоянии, тогда loop более не будет трогать бузер.
Это будет нормально работать, если flag проверяется один раз, допустим в цикле setup.
Я как понимаю, проект грандиозный, раз в таймере предусмотрена работа более 1 года...