Отображение нескольких эффектов в быстром светодиоде
Я хочу реализовать три эффекта, которые отображаются каждые 5 секунд. Я знаю, что использование delay ()
- это не очень хороший метод, поэтому я хочу использовать milis()
. Периоды длительности эффектов отличаются друг от друга. Как я могу гарантировать "независание" или отображение 2 или 3 эффектов одновременно? Должен ли я измерять время проявления каждого эффекта и на его основе корректировать интервалы или есть другое решение? А ты как думаешь?
ПРАВКА:
Вот мой код:
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
i++;
switch (i){
case 1:
meteorRain(0xff,0xff,0xff,10, 64, true, 30); // efekt spadającej gwiazdy
Serial.print("meteorrain: ");
Serial.print(previousMillis);
Serial.print("\n");
break;
case 2:
colorWipe(0x90,0x90,0x90, 50);
colorWipe(0x00,0x00,0x00, 50);
Serial.print("colorwipe: ");
Serial.print(previousMillis);
Serial.print("\n");
break;
case 3:
MyEffect();
Serial.print("My effect: ");
Serial.print(previousMillis);
Serial.print("\n");
break;
}
if (i>3) i=0;
}
}
Я перечислил код эффектов (думаю, это не имеет значения).
@Marco Svizzeri, 👍1
Обсуждение1 ответ
Я бы взглянул на быстрый пример Марка Кригсмана "DemoReel100". В этом примере показано, как делегировать несколько функций.
Во-первых, я немного объясню этот пример: Вы настраиваете массив указателей на функции плюс переменную для текущего индекса.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
uint8_t gCurrentPatternNumber = 0;
Все функции (радуга
, жонглирование
и т. Д.) Просто должны работать с вашим массивом светодиодов []
, Который вы передали FastLED.addLeds()
в вашей настройке ()
- Я предполагаю, что ваши функции уже удовлетворяют этому требованию. Но: Все функции должны иметь один и тот же список аргументов (в данном случае: они должны быть определены как void rainbow() { светодиоды[x] = CHSV(a,b,c); }
), поэтому вам может потребоваться обернуть их в другую функцию.
Затем в своем цикле вы вызываете свои функции эффекта следующим образом, вызывая nextPattern()
каждые 10 секунд:
void loop()
{
// Вызовите функцию текущего шаблона один раз, обновив массив светодиодов
gPatterns[gCurrentPatternNumber]();
// отправьте массив "светодиодов" на фактическую светодиодную ленту
FastLED.show();
// вставьте задержку, чтобы сохранить умеренную частоту кадров
FastLED.delay(1000/FRAMES_PER_SECOND);
// делайте некоторые периодические обновления
EVERY_N_SECONDS( 10 ) { nextPattern(); } // периодически меняйте шаблоны
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
EVERY_N_SECONDS
-это макрос, определенный в библиотеке FastLED; он в основном делает то, что вы делали с текущими миллионами
, предыдущими миллионами
и интервалом
(также есть EVERY_N_MILLISECONDS
и некоторые другие связанные макросы).
Это пример до сих пор, теперь нам нужно работать с разным "временем переключения эффектов".
Самым простым методом в коде было бы найти наибольший общий коэффициент всех времен переключения-допустим, вы хотите, чтобы эффект rainbow()
длился 10 секунд, эффект juggle ()
- 15, а эффект bpm ()
- 5 секунд. Все эти времена переключения кратны 5, поэтому мы определяем это как задержку переключения: КАЖДЫЕ 5 секунд(5)
. Теперь, чтобы увеличить время выполнения, мы просто помещаем эти функции несколько раз в массив:
SimplePatternList gPatterns = { rainbow, rainbow, juggle, juggle, juggle, bpm };
Есть еще один способ, который дает вам возможность напрямую устанавливать продолжительность эффекта. Во-первых, нам нужен массив длительностей той же длины, что и наш массив функций эффекта, и переменная, чтобы запомнить, где мы находимся в длительности:
SimplePatternList gPatterns = { rainbow, juggle, bpm };
int[] gPatternDurations = { 10, 13, 73 };
int effectDurationLeft = gPatternDurations[0];
Затем мы уменьшим "разрешение переключателя эффектов" до 1 секунды и добавим немного логики в вызов nextPattern ()
:
EVERY_N_SECONDS( 1 ) {
if( effectDurationLeft == 0 ) {
nextPattern();
effectDurationLeft = gPatternDurations[gCurrentPatternNumber];
} else {
effectDurationLeft -= 1;
}
}
Теперь вы можете установить длительность шаблона, отредактировав массив gPatternDurations.
Пожалуйста, имейте в виду, что я не тестировал приведенный выше код. Могут возникать синтаксические ошибки :)
- Питание светодиодной ленты - Сколько ампер?
- Несколько условий оператора if
- Светодиоды: разница между общим анодом и общим катодом
- Светодиод L продолжает гореть
- Улучшенное циклическое переключение цветов RGB.
- Плавное мигание светодиодов
- Остановить мигание светодиодов
- FastLED - Как управлять определенными светодиодами
покажите нам, что вы пробовали до сих пор, у вас есть какой-то код, работающий для одного из эффектов (или 3 из них ?) чтобы мы знали, чего ожидать ? кроме того, если ваши 3 эффекта срабатывают каждые 5 секунд, не можем ли мы назвать это одним большим эффектом с 3 различными действиями, которые срабатывают каждые 5 секунд ?, @Neil
Выполняются ли эти эффекты на разных светодиодных полосах одновременно или последовательно на одной и той же светодиодной полосе?, @chrisl
Последовательно на одной и той же светодиодной полосе., @Marco Svizzeri
Значит, вы не хотите иметь несколько эффектов одновременно, как вы написали в своем вопросе? Или вы делите светодиодную ленту на разные части, которые должны отображать соответствующий эффект одновременно? Я не понимаю, как должен выглядеть конечный результат, @chrisl
Если вы намереваетесь показывать каждый эффект последовательно в течение некоторого интервала времени (глядя на код, можно предположить, что это так), то в коде нет ничего плохого, за исключением того, что выполнение эффекта будет длиться дольше этого интервала времени. Если это не ваше намерение, то я не понимаю вашего вопроса по тем же причинам, о которых упоминал @chrisl., @Peter Paul Kiefer