Отображение нескольких эффектов в быстром светодиоде

led

Я хочу реализовать три эффекта, которые отображаются каждые 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;
    }
}

Я перечислил код эффектов (думаю, это не имеет значения).

, 👍1

Обсуждение

покажите нам, что вы пробовали до сих пор, у вас есть какой-то код, работающий для одного из эффектов (или 3 из них ?) чтобы мы знали, чего ожидать ? кроме того, если ваши 3 эффекта срабатывают каждые 5 секунд, не можем ли мы назвать это одним большим эффектом с 3 различными действиями, которые срабатывают каждые 5 секунд ?, @Neil

Выполняются ли эти эффекты на разных светодиодных полосах одновременно или последовательно на одной и той же светодиодной полосе?, @chrisl

Последовательно на одной и той же светодиодной полосе., @Marco Svizzeri

Значит, вы не хотите иметь несколько эффектов одновременно, как вы написали в своем вопросе? Или вы делите светодиодную ленту на разные части, которые должны отображать соответствующий эффект одновременно? Я не понимаю, как должен выглядеть конечный результат, @chrisl

Если вы намереваетесь показывать каждый эффект последовательно в течение некоторого интервала времени (глядя на код, можно предположить, что это так), то в коде нет ничего плохого, за исключением того, что выполнение эффекта будет длиться дольше этого интервала времени. Если это не ваше намерение, то я не понимаю вашего вопроса по тем же причинам, о которых упоминал @chrisl., @Peter Paul Kiefer


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.

Пожалуйста, имейте в виду, что я не тестировал приведенный выше код. Могут возникать синтаксические ошибки :)

,