В цикле "if...." не выполняются манипуляции с millis()

Понадобилось поиграться с написанием примитивного таймера. Скетч:

//UNO

//Блок мах7219
#define pin_din A2
#define pin_clk A0
#define pin_cs A1
int full_time;
int seconds;
int minutes;
unsigned long sec_break;
int tys;  // Тысячи
int sot; // Сотни
int des; // Десятки
int edi; // Единицы
#define tire B00000001
#include <LedControl.h>   //Подключение библиотеки max7219 
LedControl lc_max7219 = LedControl(pin_din, pin_clk, pin_cs, 1);
//______________________________________
//Блок энкодера
#include <Arduino.h>
#include <GyverIO.h>
#include <EncButton.h>
#define enc_B 7 // пин В энкодера
#define enc_A 6 // пин А энкодера
#define enc_but 5 // пин кнопки энкодера
EncButton eb_enc(enc_B, enc_A, enc_but, INPUT_PULLUP); // пины энкодера настройки
int enc_but_val=0;
int enc_val=0;


//______________________________________

void setup()
{
  Serial.begin(115200);
  //Блок мах7219  
  pinMode(pin_din, OUTPUT);
  pinMode(pin_clk, OUTPUT);
  pinMode(pin_cs, OUTPUT);
  //Инициализация индикаторов с выравниванием яркости
  lc_max7219.shutdown(0, false);     //Выводим из спящего режима
  lc_max7219.setIntensity(0, 4);      //Яркость дисплея на 4. Всего возможных режимов яркости от 0 до 15
  lc_max7219.clearDisplay(0);       //Очистить дисплей
  lc_max7219.setRow(0, 4 , tire);    //Индикация "-"
  lc_max7219.setRow(0, 3 , tire);    //Индикация "-"
  //______________________________________

  //Блок энкодера
  //Предустановки энкодера (значения по умолчанию энкодера)
  eb_enc.setBtnLevel(LOW);
  eb_enc.setClickTimeout(500);
  eb_enc.setDebTimeout(50);
  eb_enc.setHoldTimeout(600);
  eb_enc.setStepTimeout(200);
  eb_enc.setTimeout(1000);
  eb_enc.setEncReverse(0);
  eb_enc.setEncType(EB_STEP4_LOW);
  eb_enc.setFastTimeout(30);
  eb_enc.counter = 0;
  //______________________________________

}

void loop() 
{
  eb_enc.tick();
  //Нажатие кнопки
  if (eb_enc.press()) 
  {
    enc_but_val++;
    if (enc_but_val==4) {enc_but_val=1;}
  }  
  //Крутим влево, уменьшаем
  if (eb_enc.left())
  {
    enc_val--;
    if(enc_val<0) {enc_val=0;}
  }  
  //Крутим вправо, увеличиваем   
  if (eb_enc.right()) 
  {
    enc_val++;
    if(enc_val>60) {enc_val=60;}
  } 
  //Настройка минут 
  if (enc_but_val==1) 
  {
    minutes=enc_val;
    full_time=minutes*60+seconds;
    //Индикация настройки минут
    des = minutes % 100 / 10;
    edi = minutes % 10;
    lc_max7219.setDigit(0, 6, des, false);
    lc_max7219.setDigit(0, 5, edi, false);   
  }
   //Настройка секунд  
  if (enc_but_val==2)
  {
    seconds=enc_val;
    full_time=minutes*60+seconds;
    //Индикация настройки секунд
    des = seconds % 100 / 10;
    edi = seconds % 10;
    lc_max7219.setDigit(0, 2, des, false);
    lc_max7219.setDigit(0, 1, edi, false);  
  }
  //Запуск таймера
  if (enc_but_val==3) 
  {
    if ((millis()-sec_break)>999)
    {
      full_time--;
      minutes=abs(full_time/60);
      seconds=full_time-minutes*60;
      //Индикация 
      des = minutes % 100 / 10;
      edi = minutes % 10;
      lc_max7219.setDigit(0, 6, des, false);
      lc_max7219.setDigit(0, 5, edi, false);  
      des = seconds % 100 / 10;
      edi = seconds % 10;
      lc_max7219.setDigit(0, 2, des, false);
      lc_max7219.setDigit(0, 1, edi, false); 
      sec_break=millis(); 
    }
  }  
  Serial.print (enc_but_val);
  Serial.print (" ");
  Serial.println (full_time); 
}
  

Столкнулся вот с чем: все, что должно выполняться при значении кнопки энкодера==1 или 2 (настройки с энкодера), выполняется. А при значении кнопки энкодера==3 (режим обратного отсчета) НЕ выполняется цикл с millis(). Если закомментировать строки 108,109 и 126 (то есть, перенести цикл с millis() в луп напрямую без условия значения кнопки==3), то цикл с millis() начинает нормально выполняться. Где нарушил логику - не могу понять. Заранее спасибо за помощь!

Ну а enc_but_val точно равно 3? Проверял?

Если нажать кратко, то имеется описанная проблема: enc_but_val точно равно 3, а обратного отсчета нет. Если нажать подольше, то таймер начинает нормально срабатывать. Получается, просто ждем ту самую секунду?

Смотри что там у гувера при долгом удержании.

Ага, вечером посмотрю. Спасибо за наводку. :slight_smile:

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

Для того чтобы работало правильно, по кнопке надо только выставлять флаг запуска таймера. А сам таймер должен быть в основной части ЛУП, а не внутри условия.

Я тоже так подумал, но вроде бы так быть не должно.
Вот тут при событии нажатия кнопки он меняет enc_but_val. Дальше кнопка никакого участия принимать не должна.

А вот тут полностью согласен!

Это немного странно. По нажатию кнопки просто меняется ее значение: 1-2-3-1-2-3… При 1 или 2 никаких же траблов нету. А когда она равна 3 - прикол с циклом millis(). Ну, вечером покопаюсь. Спасибо.

Да! И еще: обратный отсчет начинается, если третье нажатие кнопки продолжительное. И удерживать нее не надо: продолжительно нажать и отпустить. По-видимому, просто ждем от millis() прошествие 1 секунды.

Блин, вы не знаете своего кода?

//UNO

//Блок мах7219
#define pin_din A2
#define pin_clk A0
#define pin_cs A1
int full_time;
int seconds;
int minutes;
unsigned long sec_break;
bool timer_started = false;
#define tire B00000001
#include <LedControl.h>
LedControl lc_max7219 = LedControl(pin_din, pin_clk, pin_cs, 1);
//______________________________________
//Блок энкодера
#include <Arduino.h>
#include <GyverIO.h>
#include <EncButton.h>
#define enc_B 7
#define enc_A 6
#define enc_but 5
EncButton eb_enc(enc_B, enc_A, enc_but, INPUT_PULLUP);
int enc_but_val=0;
int enc_val=0;

//______________________________________

void setup()
{
Serial.begin(115200);
//Блок мах7219
pinMode(pin_din, OUTPUT);
pinMode(pin_clk, OUTPUT);
pinMode(pin_cs, OUTPUT);
lc_max7219.shutdown(0, false);
lc_max7219.setIntensity(0, 4);
lc_max7219.clearDisplay(0);
lc_max7219.setRow(0, 4 , tire);
lc_max7219.setRow(0, 3 , tire);
//______________________________________

//Блок энкодера
eb_enc.setBtnLevel(LOW);
eb_enc.setClickTimeout(500);
eb_enc.setDebTimeout(50);
eb_enc.setHoldTimeout(600);
eb_enc.setStepTimeout(200);
eb_enc.setTimeout(1000);
eb_enc.setEncReverse(0);
eb_enc.setEncType(EB_STEP4_LOW);
eb_enc.setFastTimeout(30);
eb_enc.counter = 0;
//______________________________________

}

void updateDisplay() {
int des = minutes % 100 / 10;
int edi = minutes % 10;
lc_max7219.setDigit(0, 6, des, false);
lc_max7219.setDigit(0, 5, edi, false);

des = seconds % 100 / 10;
edi = seconds % 10;
lc_max7219.setDigit(0, 2, des, false);
lc_max7219.setDigit(0, 1, edi, false);
}

void loop()
{
eb_enc.tick();

//Нажатие кнопки
if (eb_enc.press())
{
enc_but_val++;
if (enc_but_val == 4) {
enc_but_val = 1;
timer_started = false;
}

if (enc_but_val == 3) {
sec_break = millis();
timer_started = true;
} else {
timer_started = false;
}
}

// Режим настройки минут
if (enc_but_val == 1)
{
if (eb_enc.left())
{
enc_val--;
if(enc_val < 0) { enc_val = 0; }
}
if (eb_enc.right())
{
enc_val++;
if(enc_val > 60) { enc_val = 60; }
}

minutes = enc_val;
full_time = minutes * 60 + seconds;
updateDisplay();
}

// Режим настройки секунд
if (enc_but_val == 2)
{
if (eb_enc.left())
{
enc_val--;
if(enc_val < 0) { enc_val = 0; }
}
if (eb_enc.right())
{
enc_val++;
if(enc_val > 60) { enc_val = 60; }
}

seconds = enc_val;
full_time = minutes * 60 + seconds;
updateDisplay();
}

// Режим обратного отсчета
if (enc_but_val == 3 && timer_started)
{
if (full_time > 0) {
if ((millis() - sec_break) >= 1000)
{
full_time--;
minutes = full_time / 60;
seconds = full_time % 60;
updateDisplay();
sec_break = millis();
}
} else {
timer_started = false;
}
}

Serial.print(enc_but_val);
Serial.print(" ");
Serial.print(full_time);
Serial.print(" ");
Serial.print(minutes);
Serial.print(":");
Serial.println(seconds);
}

флаг в помощь, дополнительные улучшения от ии бонусом)))

!!!

Вечером попробую. В случае успеха - с меня литр!

PS: C ИИ не делиться! Обойдется :slight_smile:

Мда-а-а. Как говаривал поэт: «Если это присказка, значит сказка – дрянь»

2 лайка

У вас ведь есть диагностический вывод.

Вы говорите, что в Serial стабильно выводится 3 но при этом не считается время?

Именно так и было. Попробовал вариант, любезно предоставленный Бабосом - все заработало штатно. Как я для себя решил после изучения его скетча, в моем исходном варианте были противоположные приоритеты в расстановке циклов “if …“. Возможно, дело в этом. Но еще я попрокачиваю ситуацию, чтоб окончательно уяснить всё.

@Sonologist , Вы по специальности невропатолог?
С какой целью Вы размещаете на форуме темы с названиями, которые сразу хочется отправить в корзину?

Деду отправь)))

Как ты его «изучить» смог? Там же каша одна.

Каша-не каша, а работает. Мне надо было сравнить то, что я наваял (с траблами) и бабосово произведение, которое работает. Кое в чем разобрался, но не до конца (прошу гуру не пинать: я не программист). Хочу поиграться (типа что будет, если каки-то строки закомментировать).

Так спросил бы у ИИ всеми сейчас любимыми. Бабос именно его код и выдаёт тут как ретранслятор.