Ушел от delay, решил перейти на millis, но код не работает

Всем привет. Функция успешно работала и отображала время. Решил как все советуют уйти от delay и переделать все на millis.
Было:

void mode_display_time(){    //функция отображения времени
    int i = 0;
   
    while(i < 100) {
      now_time = tm.Hour*100 + tm.Minute; 
      
      int a = now_time/ 1000;
      int b = now_time % 1000/100;
      int c = now_time % 100/10;
      int d = now_time % 10;
      
                digitalWrite(DIGIT_1PIN,HIGH);
                digitalWrite(DIGIT_2PIN,LOW);
                digitalWrite(DIGIT_3PIN,LOW);
                digitalWrite(DIGIT_4PIN,LOW);
                show_number(a);
                delay(time_delay);
                digitalWrite(DIGIT_1PIN,LOW);
                digitalWrite(DIGIT_2PIN,HIGH);
                digitalWrite(DIGIT_3PIN,LOW);
                digitalWrite(DIGIT_4PIN,LOW);
                show_number(b);
                delay(time_delay);
                digitalWrite(DIGIT_1PIN,LOW);
                digitalWrite(DIGIT_2PIN,LOW);
                digitalWrite(DIGIT_3PIN,HIGH);
                digitalWrite(DIGIT_4PIN,LOW);
                show_number(c);
                delay(time_delay);
                digitalWrite(DIGIT_1PIN,LOW);
                digitalWrite(DIGIT_2PIN,LOW);
                digitalWrite(DIGIT_3PIN,LOW);
                digitalWrite(DIGIT_4PIN,HIGH);
                show_number(d);
                delay(time_delay);
                digitalWrite(DIGIT_1PIN,LOW);
                digitalWrite(DIGIT_2PIN,LOW);
                digitalWrite(DIGIT_3PIN,LOW);
                digitalWrite(DIGIT_4PIN,LOW);  
                i++;
     }
     display_digits_off();
     numMenu = 0;
}

Стало:

void mode_display_time(){    //функция отображения времени
    int i = 0;
   
    while(i < 100) {
      now_time = tm.Hour*100 + tm.Minute; 
      
      int a = now_time/ 1000;
      int b = now_time % 1000/100;
      int c = now_time % 100/10;
      int d = now_time % 10;
                if (millis() - previousMillis > time_delay) 
                {
                  previousMillis = millis();
                  digitalWrite(DIGIT_1PIN,HIGH);
                  digitalWrite(DIGIT_2PIN,LOW);
                  digitalWrite(DIGIT_3PIN,LOW);
                  digitalWrite(DIGIT_4PIN,LOW);
                  show_number(a);
                }
                if (millis() - previousMillis > time_delay) 
                {
                  previousMillis = millis();
                  digitalWrite(DIGIT_1PIN,LOW);
                  digitalWrite(DIGIT_2PIN,HIGH);
                  digitalWrite(DIGIT_3PIN,LOW);
                  digitalWrite(DIGIT_4PIN,LOW);  
                  show_number(b);            
                }
                
                if (millis() - previousMillis > time_delay) 
                {
                  previousMillis = millis();
                  digitalWrite(DIGIT_1PIN,LOW);
                  digitalWrite(DIGIT_2PIN,LOW);
                  digitalWrite(DIGIT_3PIN,HIGH);
                  digitalWrite(DIGIT_4PIN,LOW);
                  show_number(c);
                }
            
                if (millis() - previousMillis > time_delay) 
                {
                  previousMillis = millis();
                  digitalWrite(DIGIT_1PIN,LOW);
                  digitalWrite(DIGIT_2PIN,LOW);
                  digitalWrite(DIGIT_3PIN,LOW);
                  digitalWrite(DIGIT_4PIN,HIGH);
                  show_number(d);
                }
           
              if (millis() - previousMillis > time_delay) 
                {
                  previousMillis = millis();
                  digitalWrite(DIGIT_1PIN,LOW);
                  digitalWrite(DIGIT_2PIN,LOW);
                  digitalWrite(DIGIT_3PIN,LOW);
                  digitalWrite(DIGIT_4PIN,LOW);
                }  
                                i++;
     }
     display_digits_off();
     numMenu = 0;
}

В общем время перестало отображаться, полазил по форумам, решения как такого не нашел, кроме если делать какие-то искусственные задержки типа for или вообще serial.println добавить, ну в общем не правильно все это. Как исправить мой код, что бы работало все с миллис??? Это отображение цифр на 7 сегментом индикаторе. Если слишком гемморно, все верну обратно в delay. СПАСИБО

нет ребята, всё не так

Может есть ссылка, как лучше реализовать?

А в чем цель этого переключения?

@maksmkv , Вы сами понимаете код который написали?
Можете объяснить, зачем употреблены те или иные конструкции?
В частности, опишите назначение строк: 11, 13, 20, 22, 30, 32, 40, 42, 50 и 52. И как эти строки взаимодействуют между собой?

в каждом случае использования миллис переменная

должна быть отдельная!

А так у вас все пять условий пересекаются.

И, кстати, где вы хоть раз запоминаете previousMillis ???

Так в лоб не получится. Раньше все делалось в один проход цикла, теперь в каждом проходе цикла (если момент настал) будет выполняться только первый if. До остальных дело не дойдет. Работа с миллисом таки отличается от работы с делеями.
Нужно делать примерно так:

  1. завести флаг выполнения, флаг поднят - пришло время, флаг опущен - ничего не делать
  2. завести счетчик, по значению которого будет выполняться тот или иной if
  3. по миллису только поднимать поднимать флаг
  4. если флаг поднят, выполнять соответствующий if, опускать флаг и увеличивать счетчик на единицу

Примерно так

Спойлер
void mode_display_time()
{ // функция отображения времени
  int i = 0;

  while (i < 100)
  {
    now_time = tm.Hour * 100 + tm.Minute;

    int a = now_time / 1000;
    int b = now_time % 1000 / 100;
    int c = now_time % 100 / 10;
    int d = now_time % 10;
    static bool flag = false;
    static byte count = 0;

    if (millis() - previousMillis > time_delay)
    {
      previousMillis = millis();
      flag = true;
    }

    if (flag)
    {
      digitalWrite(DIGIT_1PIN, LOW);
      digitalWrite(DIGIT_2PIN, LOW);
      digitalWrite(DIGIT_3PIN, LOW);
      digitalWrite(DIGIT_4PIN, LOW);

      switch (count)
      {
      case 0:
        show_number(a);
        break;
      case 1:
        show_number(b);
        break;
      case 2:
        show_number(c);
        break;
      case 3:
        show_number(d);
        break;
      case 4:
        break;
      }

      flag = false;
      if (++count >= 5)
      {
        count = 0;
      }
      i++;
    }
  }
  display_digits_off();
  numMenu = 0;
}

1 лайк

Или под if подвесить switch case.

А, сорри, я опоздал ))

1 лайк

Да честно, понять понимаю, но как говорится в голове сложилось, а на деле оказалось не так.

СПАСИБО, да тут совсем всё по другому. Я так полагаю о таких приемах в книгах не пишут, это только практикой доходит или так же когда-то подсказали более опытные?? СПАСИБО за реализацию. Пойду исправлять у себя. А это только часть кода, но логика уже ясна.

Не, все проще, чтоб понять цифровую логику и программирование, необходим нужный склад ума.
Как мой зять говорит : мне пофиг какой язык программировать.

Да вроде небольшой опыт имеется в JS, С#, DELPHI, но вот именно реализация аппаратного программирования - тут немного другое. Одно дело формочки накидать, а другое обработка кнопок, отображение символов и прочее.

это шутка такая или пятничное?

Беда, че…
Я сам с этого начинал, ученье - свет.!

Че это?
Delphi эт обычный паскаль, очень даже норм в нашей жизни

Java маразм все перевести в объекты, ну моё мнение.
И да, для примера: мне ооп тяжело даётся, но например для других C просто невозможный язык.

да я к тому, что никаких языков не знаю, при этом фигни практически не пишу )))
PS а если бы знал?

Тупик :slight_smile:
Мозг должен развиваться :slight_smile:

Да, при этом подл “практикой” нужно подразумевать следующее:
Представить себе, что микроконтроллер - это Вы, после чего попытаться выполнить имеющуюся программу. Например, если бы Вы это сделали, то самостоятельно обнаружили бы, что из всех блоков if(millis()… всегда будет выполняться только первый.

а счетчик i будет работать как задумано?

А что с ним станется? После отработки цикла - выход из процедуры, как было в варианте ТС