Прошу помощи в алгоритме

uscr
Offline
Зарегистрирован: 17.08.2012

 Здравсвуйте. Пока жду детали для будущих веселий, решил поразвлечься с тем, что есть. А есть светодиоды. Я уже вдоволь намигался (в то мчисле плавно), поэтому решил написать программу, которая реализует один из любимейших моих эффектов - "бегущий огонёк". То есть 1 светодиод горит на полную, за и перед ним чуть менее ярко.

 

Нарисовал себе такую схему:

4 светодиода (больше у меня нет :( ), число - яркость для analogWrite(знаю, что подобраны плохо, но это прототип).

1 : 0-0-0-0
2 : 64-0-0-0
3 : 128-64-0-0
4 : 192-128-64-0
5 : 255-192-128-64
6 : 192-255-192-128
7 : 128-192-255-192
8 : 64-128-192-255
9 : 0-64-128-192
10: 0-0-64-128
11: 0-0-0-64
12: 0-0-0-0

Постепенно проходя в уме все этапы, начал писать программу:



 

//0 - not usable
byte leds_pin[4] = {4, 5, 6, 7};

int leds_level[4] = {64, 128, 192, 255};
byte led_now_level[4] = { 0, 0, 0, 0 };

int led_count = 4;
int levels_count = 3;

void setup() {
  for (int i=0; i<4; i++) {
    pinMode(leds_pin[i], OUTPUT);
  }
}

void fire_run() {
  //Пробегаемся по светодиодам
  for (int i=0; i<led_count; i++) {
    //Если ещё не горит, 
    if (led_now_level[i] == 0) {
      //а предыдущий светодиод существует и уже горит, то зажжём
      if ((i != 0) and (led_now_level[i-1] != 0)) {
        led_now_level[i] = leds_level[0];
      }
        //Больше не повторяем
        break;
      }
    }
  //Теперь пробегаем по известным уровням
    for (int i=0; i<=levels_count; i++) {
      //Если светодиод не горит и перед ним тоже не горит 
      //(проверка в серединке нужна, что бы не выйти за границы массива)
      //то грустно выходим
      if ((led_now_level[i] == 0) and (i!=levels_count) and (led_now_level[i+1] == 0)) {
        break;
      }
      //тут волшебство, которое будет правильно менять значения в led_now_level
    }
  
}

void fire_visualiser() {
//тут просто проходим по led_now_level и зажигаем светодиоды с нужной яркостью
}

void loop() {

}

Но сразу заметил 2 недостатка:
адский фарш из if'ов

программа, несмотря на намёк на настраиваемость изначально жёстко пишется под 4 светодиода. это становится очевидно, если посмотреть на мои проверки во второй части fire_run()

Решил, что нужно остановиться и спросить совета.

Не подскажете, оптимальный алгоритм для осуществления задуманного? А может быть есть готовые примеры с реализацией такого эффекта?

 

step962
Offline
Зарегистрирован: 23.05.2011

 Создайте один на всех массив яркостей:

#define maxLEDs  4 // число светодиодов в работе

#define maxIDX 10 // число уровней яркости в волне

int vPWM[maxIDX]={0,64,128,...}; // столько элементов, сколько нужно

запрограммируйте цикл, нечто вроде:

LED[0]=0;
LED[1]=1;
// ...
while(1) {
  for(i=0;i<nLEDs;i++) {
    if (LED[i]<maxIDX) LED[i]++;
    else LED[i]=0;
    AnalogWrite(номер вывода, vPWM[LED[i]]);
  }
}

и начинайте его оптимизировать (те же выводы тоже просятся в массив). Подробнее писать времени нет - уезжаю. Надеюсь, помощники еще подтянутся...