А зачем опознавать? Судя по вводным - достаточно достичь всех цветов по трём каналам для светика, и тогда считается, что fade закончено. Причём неважно, какие значения для какого канала переданы как окончательные. Ещё вопрос: fade делать только вверх, вниз не надо?
Конечно в обе стороны. Так я для этого и делал сравнения в рандомайзере, чтобы знать когда выпадет сплошной цвет, чтобы его подольше держать. Выпал цвет - бледно зеленый (175, 255, 115), держим его секунду. А если выпал насыщенный фиолетовый (253, 0, 237), то держим его 5 секунд.
Вот, навскидку накидал класс фейдера: Код (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); } } } А остальную логику уже докрутить, как надо. Можно несколько фейдеров одновременно. Можно в класс фейдера добавить что надо, типа задержки между сменой значения на канале. Можно - добавить пропорциональный расчёт сменяемого на каналах значения, чтобы все каналы менялись с пропорциональными интервалами, а не тупо по единичке. Да много чего можно припилить ещё Код не проверял - чисто идея.
Если не по единичке, то будет видно что скачкообразно прибавляется. Фэйдеры-то и сейчас нормально работают. У меня затык в таймере ожидания перед новой рандомизацией =) Как его заставить срабатывать только после того как появился флаг?
Наверное, проверять этот самый флаг и если он не взведён - обновлять переменную этого таймера в millis(), чтобы он не начал тикать, пока флаг не взведён
Код (C++): if (AllDone and Solid) { curSolidTime = millis(); if (curSolidTime - prevSolidTime >= SolidDelay) { prevSolidTime = curSolidTime; Randomizer(Min, Max); } } Покажите пальцем где косяк? =) Я же вроде начала тикания засунул внутрь условия.
Если кому интересно, вот как решил задачу. Через пень-колоду, но зато работает. Код (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); } }