Счетчик millis()

Тема в разделе "Arduino & Shields", создана пользователем FlameWind, 19 июл 2016.

Метки:
  1. FlameWind

    FlameWind Нерд

    А как тогда опознать что выпал желаемый цвет?
     
  2. DIYMan

    DIYMan Guest

    А зачем опознавать? Судя по вводным - достаточно достичь всех цветов по трём каналам для светика, и тогда считается, что fade закончено. Причём неважно, какие значения для какого канала переданы как окончательные.

    Ещё вопрос: fade делать только вверх, вниз не надо?
     
  3. FlameWind

    FlameWind Нерд

    Конечно в обе стороны.
    Так я для этого и делал сравнения в рандомайзере, чтобы знать когда выпадет сплошной цвет, чтобы его подольше держать.
    Выпал цвет - бледно зеленый (175, 255, 115), держим его секунду. А если выпал насыщенный фиолетовый (253, 0, 237), то держим его 5 секунд.
     
  4. DIYMan

    DIYMan Guest

    Вот, навскидку накидал класс фейдера:
    Код (C++):
    class Fader
    {
        public:
            Fader() : _started(false), _done(false){}
           
            // фейдинг до указанных значений
            void fadeTo(byte r, byte g, byte b)
            {
                _rsrc = _r = r;
                _gsrc =_g = g;
                _bsrc = _b = b;
               
                _started = true;
                _done = false;
            }
           
            // возвращает текущие высчитанные значения фейдинга
            void current(byte& r, byte& g, byte& b)
            {
                r = (_rsrc - _r) + 1;
                g = (_gsrc - _g) + 1;
                b = (_bsrc - _b) + 1;
            }
           
            // мы в процессе фейдинга?
            bool inProcess()
            {
                return _started;
            }
           
            // мы закончили работу
            bool isDone()
            {
                return _done;
            }
           
            // обновляем
            void update()
            {
                if(!_started)
                    return;
               
                if(_r > 0)
                    --r;
               
                if(_g > 0)
                    --_g;
                   
                if(_b > 0)
                    --_b;
                   
                _done = (!_r && !_g && !_b);
                _started = !_done;
            }
           
        private:
       
            byte _r, _g, _b, _rsrc, _gsrc, _bsrc;
            bool _started, _done;
    };
    Использовать можно так:
    Код (C++):

    Fader fader;

    void loop()
    {
        fader.update(); // обновляем фейдер
       
        if(!fader.inProcess())
        {
            // ещё не запускали фейдинга
            fader.fadeTo(255,0,0);
        }
        else
        {
            // фейдинг запущен, смотрим, завершился ли он
            if(fader.isDone())
            {
                // работу закончили, можно запускать следующий фейдинг
            }
            else
            {
                // ещё работаем, устанавливаем для светиков уровни на каналах
                byte r,g,b;
                fader.current(r,g,b);
               
                analogWrite(rPin,r);
                analogWrite(gPin,g);
                analogWrite(bPin,b);
            }
        }
    }
     
    А остальную логику уже докрутить, как надо. Можно несколько фейдеров одновременно. Можно в класс фейдера добавить что надо, типа задержки между сменой значения на канале. Можно - добавить пропорциональный расчёт сменяемого на каналах значения, чтобы все каналы менялись с пропорциональными интервалами, а не тупо по единичке. Да много чего можно припилить ещё ;)

    Код не проверял - чисто идея.
     
  5. FlameWind

    FlameWind Нерд

    Если не по единичке, то будет видно что скачкообразно прибавляется.
    Фэйдеры-то и сейчас нормально работают. У меня затык в таймере ожидания перед новой рандомизацией =)
    Как его заставить срабатывать только после того как появился флаг?
     
  6. DIYMan

    DIYMan Guest

    Наверное, проверять этот самый флаг и если он не взведён - обновлять переменную этого таймера в millis(), чтобы он не начал тикать, пока флаг не взведён ;)
     
  7. FlameWind

    FlameWind Нерд

    Код (C++):

    if (AllDone and Solid) {
       curSolidTime = millis();
       if (curSolidTime - prevSolidTime >= SolidDelay) {
        prevSolidTime = curSolidTime;
        Randomizer(Min, Max);
       }
      }
    Покажите пальцем где косяк? =) Я же вроде начала тикания засунул внутрь условия.
     
  8. DIYMan

    DIYMan Guest

    Где устанавливается prevSolidTime ;)?
     
  9. FlameWind

    FlameWind Нерд

    Вобщем сделал через i++; if (i > 100) и тд...
     
  10. FlameWind

    FlameWind Нерд

    Если кому интересно, вот как решил задачу. Через пень-колоду, но зато работает.
    Код (C++):
     
    boolean RegStamp = true; // Ввел флаг штамп времени
      if (RDone && GDone && BDone) {
        AllDone = true;
        if (RegStamp) { prevRegTime = millis(); } // Записываем текущее время если флаг
        RegStamp = false;
      }

      if (AllDone and !Solid) {
       uint16_t curRegTime = millis();  // Считаем таймер только внутри IF
       if (curRegTime - prevRegTime >= RegDelay) {  // Достигли интервала
         RegStamp = true; // Включаем флаг снова
         Randomizer(Min, Max);
        }
      }