обходим delay();

exez
exez аватар
Offline
Зарегистрирован: 04.04.2015

Собственно возникла примерно такая проблема. Чтоб обойти делай заводим переменную unsigned long, пишем в нее значение millis() и потом сравниваем с неким значением.

А если таких отслеживаний надо делать 10шт приходится заводить 10 переменных, которые жрут память + не сильно удобно каждый раз думать где бы записать в переменную миллис чтоб оно потом не считывадлсь второй раз.

Подскажите плиз как правильно делать в таких случаях :)

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

я для таких случаев сделал функцию

boolean smartdelay (uint32_t interval, uint8_t i) {
  static uint32_t previousMillis[8];
  static boolean sw[8];
  switch (sw[i]) {
    case 0:
        previousMillis[i] = millis();
        sw[i] = 1;
      break;
    case 1:
      if (millis() - previousMillis[i] >= interval) {
        previousMillis[i] = millis();
        sw[i] = 0;
      }
      break;
  }
  return sw[i];
}

 

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

exez пишет:
Чтоб обойти делай заводим переменную unsigned long, пишем в нее значение millis() и потом сравниваем с неким значением.
Это общее решение вопроса. Ты можешь поделить millis на 1000 и еще на 60, и считать секунды и минуты. Завести десяток байтовых переменных, и не сравнивать, а декрементировать их, по достижению 0 - событие.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015
Logik
Offline
Зарегистрирован: 05.08.2014

Обычно для не критических таемингов от 10мсек до 1минуты использую чтото типа такого.  (прям из живого проекта). 

enum{
  TIMER_CURS=0,
  TIMER_BRIGHTESS,
  TIMER_JOYSTICK,
  TIMER_SCREAN,
  TIMER_GET_PARAMS,
  
  COUNT_TIMER   //количество таймеров не более 15
} TIMERS_ID;

/* Временные интервалы таймеров в порядке их следования в TIMERS_ID */
word TimerPeriod[COUNT_TIMER]={20,200,20,50,300};
/* Последние срабатывания  таймеров */
word TimerArr[COUNT_TIMER];
word TimersMasck=_BV(TIMER_JOYSTICK)|_BV(TIMER_SCREAN)|_BV(TIMER_GET_PARAMS);
word TimerRepeat=_BV(TIMER_JOYSTICK)|_BV(TIMER_SCREAN)|_BV(TIMER_GET_PARAMS);
word Timer;

boolean TimerProcess(void)
{
    word Now=millis();
    boolean f=false;
    word r=1;
    for(byte i=0;i<COUNT_TIMER;i++,r<<=1)
    {
      if(TimersMasck&r) //маска в 1 значить активен
      {
        if((Now-TimerArr[i])>TimerPeriod[i])
        {
          if(TimerRepeat&r)
            TimerArr[i]=Now;    //периодические таймер перезапускаем
          else
            TimersMasck&=~r;    //непериодические таймер останавливаем
          Timer|=r;             //таймер сработал

          return true;
          //f=true;
        }
      }
    }
  return f;
}

void  TimerRun(byte timer)
{
  bitSet(TimersMasck,timer);
  TimerArr[timer]=millis();
}

boolean IsTimerRun(byte timer)
{
  return TimersMasck & _BV(timer);
}

boolean IsTimerSet(byte timer)
{
  word r=_BV(timer);
  if(Timer&r)
  { 
    Timer&=~r;  
    return true;
  }
  return false;  
}

 Экономно, гибко,  16 таймеров хватает всегда, т.е. не было у меня случая чтоб мало было. Заодно просто решает одну "скользкую" проблему - выравнивает нагрузку. В каждом цикле loop только одно срабатывание таймера, остальные отложатся на следующий (решается в строках 37,38). Без этого возможны очень противные проблемы, возникающие редко при неудачных совпадениях и потому трудно исправимые.