При добавлении эффектов для адресной ленты, ленты перестала работать

MrFrevidens

✩✩✩✩✩✩✩
6 Янв 2025
1
0
Это проект для arduino nano, код писаслся с помощью arduino ide версии 2.3.4 (что бы не было про это вопросов)

ПРОБЛЕМА: я решил добавить разные эффекты для моего проекта с адресной лентой, но после добавления лента перестала светится. Точнее она светится но только при удержании кнопки увеличения яркости (см. часть описанием проекта). до этого лента работала нормально. Когда я закомментировал часть кода которая отвечала за эффекты то проблема пропала.

вот видео проблемы(сорян за качество)

КОД ПРОЕКТА: у моего скетча есть 3 вкладки LR_program_block, Buttons_Functions и Effects_functions. LR_program_block и Buttons_Functions написал полностью я, Effects_functions это считайте обрубок кода Гайвера с эффектам для WS2812b. вставил только нужные мне эффекты и все нужные для этого функции.

LR_program_block: сюда я вставил все "служебные переменные" из скетча Гайвера.
LR_program_block:
/*
╔════════════════════════════════════════╗
║            << Licht Ring >>            ║
╠════════════════════════════════════════╣
║ В данной программе с помощью HSV       ║
║ можно регулировать:                    ║
║  - яркость,                            ║
║  - насыщенность,                       ║
║  - цвет ленты.                         ║
║ Также можно:                           ║
║  - включать и выключать ленту,         ║
║  - выбирать различные эффекты.         ║
╚════════════════════════════════════════╝
*/
// [======= БИБЛИОТЕКИ =======]
#include <FastLED.h>        // библиотека для управления светодиодами
#include <GyverButton.h>    // библиотека для управления кнопками
#include <TimerMs.h>        // библиотека для задержек

// [------ параметры для светодиодной ленты ------]
#define LED_PIN 13                  // Пин, к которому подключена лента
#define NUM_LEDS 27                 // Количество светодиодов в ленте. в самом кольце 16 светодиодов, но при тэстах светодиодов было 27.
#define LED_TYPE WS2812B            // Тип светодиодов
#define COLOR_ORDER GRB             // Порядок для светодиодов в ленте (для WS2812B)

CRGB leds[NUM_LEDS];                // массив для управления светодиодами

// [------ переменные HSV ------]
byte hue = 0;                       // цвет
byte hue_memory;
byte saturation = 0;                // насыщенность
byte saturation_memory;
byte brightness = 128;              // яркость
byte brightness_memory;

byte update_step = 2;

// [------ переменные для эффектов ------] !!!НЕ ТРОГАТЬ А ТО ВСЁ ЭФФЕКТЫ СЛОМАЮТСЯ НАХУЙ!!!
int BOTTOM_INDEX = 0;                  // светодиод начала отсчёта
int TOP_INDEX = int(NUM_LEDS / 2);
int EVENODD = NUM_LEDS % 2;
int ledsX[NUM_LEDS][3];     //-ARRAY FOR COPYING WHATS IN THE LED STRIP CURRENTLY (FOR CELL-AUTOMATA, MARCH, ETC)

int thisdelay = 20;          //-FX LOOPS DELAY VAR
int thisstep = 10;           //-FX LOOPS DELAY VAR
int thishue = 0;             //-FX LOOPS DELAY VAR
int thissat = 255;           //-FX LOOPS DELAY VAR

int thisindex = 0;
int thisRED = 0;
int thisGRN = 0;
int thisBLU = 0;

int idex = 0;                //-LED INDEX (0 to LED_COUNT-1
int ihue = 0;                //-HUE (0-255)
int ibright = 0;             //-BRIGHTNESS (0-255)
int isat = 0;                //-SATURATION (0-255)
int bouncedirection = 0;     //-SWITCH FOR COLOR BOUNCE (0-1)
float tcount = 0.0;          //-INC VAR FOR SIN LOOPS
int lcount = 0;              //-ANOTHER COUNTING VAR

// [------ задержки для эффектов ------]
TimerMs rainbow_loop_delay(20);
TimerMs pulse_one_color_all_rev_delay(15);
TimerMs rainbow_vertical_delay(50);
TimerMs new_rainbow_loop_delay(5);
TimerMs rgb_propeller_delay(25);
TimerMs ems_lightsONE_delay(40);
TimerMs ems_lightsALL_delay(40);
TimerMs matrix_delay(50);
TimerMs fade_vertical_delay(60);
TimerMs radiation_delay(60);
TimerMs sin_bright_wave_delay(35);
TimerMs random_color_pop_delay(35);


// [------ параметры для кнопок ------]
// значение в скобках это пин к которому подключена кнопка

GButton light_up_button(2);         // увеличения яркости
GButton light_down_button(3);       // уменьшение яркости

GButton contrast_up_button(5);      // увеличение контраста
GButton contrast_down_button(6);    // уменьшение контраста

GButton color_up_button(8);         // изменение оттенка
GButton color_down_button(9);       // изменение оттенка

GButton switch_button(11);          // вкл/выкл лента
boolean switch_flag = true;

GButton effects_button(12);         // переключение эффектов
byte led_mode = 0;
byte led_mode_memory = 1;

boolean effect_flag = false;


boolean HSV_switch_permission = true;           // если true то можно настраивать цвет ленты, если false то нельзя
boolean efffects_switch_permission = false;     // если true то можно менять эффекты, если false то нельзя

void setup() {
  // <--- инициализация ленты --->
  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  update_leds(hue, saturation, brightness);

  // <--- антидребезг для кнопок --->
  light_up_button.setDebounce(30);
  light_down_button.setDebounce(30);

  contrast_up_button.setDebounce(30);
  contrast_down_button.setDebounce(30);

  color_up_button.setDebounce(30);
  color_down_button.setDebounce(30);

  switch_button.setDebounce(80);

  effects_button.setDebounce(80);


  // <--- таймер для кнопок --->
  light_up_button.setStepTimeout(30);
  light_down_button.setStepTimeout(30);

  contrast_up_button.setStepTimeout(30);
  contrast_down_button.setStepTimeout(30);

  color_up_button.setStepTimeout(30);
  color_down_button.setStepTimeout(30);

  switch_button.setClickTimeout(500);

  effects_button.setClickTimeout(500);

  // <--- таймер --->
  rainbow_loop_delay.start();
  pulse_one_color_all_rev_delay.start();
  rainbow_vertical_delay.start();
  new_rainbow_loop_delay.start();
  rgb_propeller_delay.start();
  ems_lightsONE_delay.start();
  ems_lightsALL_delay.start();
  matrix_delay.start();
  fade_vertical_delay.start();
  radiation_delay.start();
  sin_bright_wave_delay.start();
  random_color_pop_delay.start();

  // <--- отладка --->
  Serial.begin(9600);
}

void loop() {
  // <--- обновление кнопок --->
  update_buttons();

  // <--- оборобатывание кнопок --->
  handle_brightness_up();
  handle_brightness_down();

  handle_contrast_up();
  handle_contrast_down();

  handle_color_up();
  handle_color_down();

  handle_switch();

  //handle_effects();

  // <--- отладка --->
  Serial.print(hue);
  Serial.print(",");
  Serial.print(saturation);
  Serial.print(",");
  Serial.println(brightness);
}
Buttons_Functions: тут находятся функции для управления кнопок. самое главное тут это функция handle_effects() в которой есть реализация смены эффектов.(из за которых вся проблема:rolleyes:)
Buttons_Functions:
// [======= ФУНКЦИИ КНОПОК =======]

// Функция для обновления светодиодов
void update_leds(byte h, byte s, byte b) {
  fill_solid(leds, NUM_LEDS, CHSV(h, s, b));
  FastLED.show();
}

// Функция для обновления состояний кнопок
void update_buttons() {
  light_up_button.tick();
  light_down_button.tick();
  contrast_up_button.tick();
  contrast_down_button.tick();
  color_up_button.tick();
  color_down_button.tick();
  switch_button.tick();
  effects_button.tick();
}

// Функция для увеличения яркости          
void handle_brightness_up() {
  if (light_up_button.isStep() && HSV_switch_permission == true) {
    brightness = min(255, brightness + update_step);       // увеличение яркости на 2
    update_leds(hue, saturation, brightness);
  }
}

// Функция для о уменьшения яркости
void handle_brightness_down() {
  if (light_down_button.isStep() && HSV_switch_permission == true) {
    brightness = max(0, brightness - update_step);         // уменьшение яркости на 2
    update_leds(hue, saturation, brightness);
  }
}

// Функция для увеличения контраста
void handle_contrast_up() {
  if (contrast_up_button.isStep() && HSV_switch_permission == true) {
    saturation = min(255, saturation + update_step);       // увеличение контраста на 2
    update_leds(hue, saturation, brightness);
  }
}

// Функция для уменьшения контраста
void handle_contrast_down() {
  if (contrast_down_button.isStep() && HSV_switch_permission == true) {
    saturation = max(0, saturation - update_step);         // уменьшение контраста на 2
    update_leds(hue, saturation, brightness);
  }
}

// Функция для изменения цвета
void handle_color_up() {
  if (color_up_button.isStep() && HSV_switch_permission == true) {
    hue = hue + update_step;                                     // увеличение оттенка на 2
    update_leds(hue, saturation, brightness);
  }
}

// Функция для изменения цвета
void handle_color_down() {
  if (color_down_button.isStep() && HSV_switch_permission == true) {
    hue = hue - update_step;                                    // уменьшение оттнека на 2
    update_leds(hue, saturation, brightness);
  }
}

// Функция для обработки кнопки включения/выключения ленты
void handle_switch() {
  if (switch_button.isPress()) {
    if (switch_flag == true) {
      // Выключение ленты
      hue_memory = hue;
      saturation_memory = saturation;
      brightness_memory = brightness;

      hue = 0;
      saturation = 0;
      brightness = 0;

      update_leds(hue, saturation, brightness);

      HSV_switch_permission = false;
      switch_flag = false;
    } else {
      // Включение ленты
      hue = hue_memory;
      saturation = saturation_memory;
      brightness = brightness_memory;

      update_leds(hue, saturation, brightness);

      HSV_switch_permission = true;
      switch_flag = true;
    }
  }
}
// функция для переключения эффектов  

void handle_effects() {
  if (effects_button.isSingle() && efffects_switch_permission == true) {
   
    led_mode++;
    led_mode_memory++;
    if(led_mode == 13) {
      led_mode = 1;
      led_mode_memory = 1;
    }
  }

  if(effects_button.isDouble() ) {

    if(effect_flag = false) {
      // переключение в режим эффектов
      hue_memory = hue;
      saturation_memory = saturation;
      brightness_memory = brightness;


      hue = 0;
      saturation = 0;
      brightness = 0;

      led_mode = led_mode_memory;

      effect_flag = true;
      efffects_switch_permission = true;

      switch(led_mode){
        case 0: update_leds(hue, saturation, brightness);
        case 1: rainbow_loop(); thisstep = 10; break;
        case 2: pulse_one_color_all_rev(); thishue = 0; break;
        case 3: rainbow_vertical(); thisstep = 15; break;
        case 4: new_rainbow_loop(); break;
        case 5: rgb_propeller(); thishue = 0; break;
        case 6: ems_lightsONE(); thishue = 0; break;
        case 7: ems_lightsALL(); thishue = 0; break;
        case 8: matrix(); thishue = 95; break;
        case 9: fade_vertical(); thishue = 180; break;
        case 10: radiation(); thishue = 95; break;
        case 11: sin_bright_wave(); thishue = 180; break;
        case 12: random_color_pop(); break;
      }
    }
    } else {
      // переключение в режим цвета
      led_mode = 0;

      effect_flag = false;
      efffects_switch_permission = false;

      hue = hue_memory;
      saturation = saturation_memory;
      brightness = brightness_memory;

      switch(led_mode){
      case 0: update_leds(hue, saturation, brightness);
    }
  }
}

Buttons_Functions: эта та часть кода которую я стырил у Гайвера. Единственое что я менял это delay() на TimerMS.(будет забавно если из за этого вся проблема🤔) ВСЁ! Всё остольное я не трогал. у меня есть претположение что вместе с эффектами я добавил какуето функцию которая мешает моему коду обновлять ленту.
Effects_functions:
// [======= ФУНКЦИИ ЭФФЕКТОВ =======]

void rainbow_loop() {  //-m3-LOOP HSV RAINBOW
  if (rainbow_loop_delay.tick()) {
    idex++;
    ihue = ihue + thisstep;
    if (idex >= NUM_LEDS) {
      idex = 0;
    }
    if (ihue > 255) {
      ihue = 0;
    }
    leds[idex] = CHSV(ihue, thissat, 255);
    LEDS.show();
  }
}


void ems_lightsONE() {  //-m7-EMERGENCY LIGHTS (TWO COLOR SINGLE LED)
  if (ems_lightsONE_delay.tick()) {
    idex++;
    if (idex >= NUM_LEDS) {
      idex = 0;
    }
    int idexR = idex;
    int idexB = antipodal_index(idexR);
    int thathue = (thishue + 160) % 255;
    for (int i = 0; i < NUM_LEDS; i++) {
      if (i == idexR) {
        leds[i] = CHSV(thishue, thissat, 255);
      } else if (i == idexB) {
        leds[i] = CHSV(thathue, thissat, 255);
      } else {
        leds[i] = CHSV(0, 0, 0);
      }
    }
    LEDS.show();
  }
}


void ems_lightsALL() {  //-m8-EMERGENCY LIGHTS (TWO COLOR SOLID)
  if (ems_lightsALL_delay.tick()) {
    idex++;
    if (idex >= NUM_LEDS) {
      idex = 0;
    }
    int idexR = idex;
    int idexB = antipodal_index(idexR);
    int thathue = (thishue + 160) % 255;
    leds[idexR] = CHSV(thishue, thissat, 255);
    leds[idexB] = CHSV(thathue, thissat, 255);
    LEDS.show();
  }
}


void pulse_one_color_all_rev() {  //-m11-PULSE SATURATION ON ALL LEDS TO ONE COLOR
  if (pulse_one_color_all_rev_delay.tick()) {
    if (bouncedirection == 0) {
      isat++;
      if (isat >= 255) {
        bouncedirection = 1;
      }
    }
    if (bouncedirection == 1) {
      isat = isat - 1;
      if (isat <= 1) {
        bouncedirection = 0;
      }
    }
    for (int idex = 0; idex < NUM_LEDS; idex++) {
      leds[idex] = CHSV(thishue, isat, 255);
    }
    LEDS.show();
  }
}


void fade_vertical() {  //-m12-FADE 'UP' THE LOOP
  if (fade_vertical_delay.tick()) {
    idex++;
    if (idex > TOP_INDEX) {
      idex = 0;
    }
    int idexA = idex;
    int idexB = horizontal_index(idexA);
    ibright = ibright + 10;
    if (ibright > 255) {
      ibright = 0;
    }
    leds[idexA] = CHSV(thishue, thissat, ibright);
    leds[idexB] = CHSV(thishue, thissat, ibright);
    LEDS.show();
  }
}


void radiation() {  //-m16-SORT OF RADIATION SYMBOLISH-
  if (radiation_delay.tick()) {
    int N3 = int(NUM_LEDS / 3);
    int N6 = int(NUM_LEDS / 6);
    int N12 = int(NUM_LEDS / 12);
    for (int i = 0; i < N6; i++) {  //-HACKY, I KNOW...
      tcount = tcount + .02;
      if (tcount > 3.14) {
        tcount = 0.0;
      }
      ibright = int(sin(tcount) * 255);
      int j0 = (i + NUM_LEDS - N12) % NUM_LEDS;
      int j1 = (j0 + N3) % NUM_LEDS;
      int j2 = (j1 + N3) % NUM_LEDS;
      leds[j0] = CHSV(thishue, thissat, ibright);
      leds[j1] = CHSV(thishue, thissat, ibright);
      leds[j2] = CHSV(thishue, thissat, ibright);
    }
    LEDS.show();
  }
}


void sin_bright_wave() {  //-m19-BRIGHTNESS SINE WAVE
  if (sin_bright_wave_delay.tick()) {
    for (int i = 0; i < NUM_LEDS; i++) {
      tcount = tcount + .1;
      if (tcount > 3.14) {
        tcount = 0.0;
      }
      ibright = int(sin(tcount) * 255);
      leds[i] = CHSV(thishue, thissat, ibright);
      LEDS.show();
    }
  }
}


void rainbow_vertical() {  //-m23-RAINBOW 'UP' THE LOOP
  if (rainbow_vertical_delay.tick()) {
    idex++;
    if (idex > TOP_INDEX) {
      idex = 0;
    }
    ihue = ihue + thisstep;
    if (ihue > 255) {
      ihue = 0;
    }
    int idexA = idex;
    int idexB = horizontal_index(idexA);
    leds[idexA] = CHSV(ihue, thissat, 255);
    leds[idexB] = CHSV(ihue, thissat, 255);
    LEDS.show();
  }
}


void random_color_pop() {  //-m25-RANDOM COLOR POP
  if (random_color_pop_delay.tick()) {
    idex = random(0, NUM_LEDS);
    ihue = random(0, 255);
    one_color_all(0, 0, 0);
    leds[idex] = CHSV(ihue, thissat, 255);
    LEDS.show();
  }
}


void rgb_propeller() {  //-m27-RGB PROPELLER0
  if (rgb_propeller_delay.tick()) {
    idex++;
    int ghue = (thishue + 80) % 255;
    int bhue = (thishue + 160) % 255;
    int N3 = int(NUM_LEDS / 3);
    int N6 = int(NUM_LEDS / 6);
    int N12 = int(NUM_LEDS / 12);
    for (int i = 0; i < N3; i++) {
      int j0 = (idex + i + NUM_LEDS - N12) % NUM_LEDS;
      int j1 = (j0 + N3) % NUM_LEDS;
      int j2 = (j1 + N3) % NUM_LEDS;
      leds[j0] = CHSV(thishue, thissat, 255);
      leds[j1] = CHSV(ghue, thissat, 255);
      leds[j2] = CHSV(bhue, thissat, 255);
    }
    LEDS.show();
  }
}


void matrix() {  //-m29-ONE LINE MATRIX
  if (matrix_delay.tick()) {
    int rand = random(0, 100);
    if (rand > 90) {
      leds[0] = CHSV(thishue, thissat, 255);
    } else {
      leds[0] = CHSV(thishue, thissat, 0);
    }
    copy_led_array();
    for (int i = 1; i < NUM_LEDS; i++) {
      leds[i].r = ledsX[i - 1][0];
      leds[i].g = ledsX[i - 1][1];
      leds[i].b = ledsX[i - 1][2];
    }
    LEDS.show();
  }
}


void new_rainbow_loop() {  //-m88-RAINBOW FADE FROM FAST_SPI2
  if (new_rainbow_loop_delay.tick()) {
    ihue -= 1;
    fill_rainbow(leds, NUM_LEDS, ihue);
    LEDS.show();
    delay(thisdelay);
  }
}



//------------------------------------- UTILITY FXNS --------------------------------------
//---SET THE COLOR OF A SINGLE RGB LED
void set_color_led(int adex, int cred, int cgrn, int cblu) {
  leds[adex].setRGB(cred, cgrn, cblu);
}

//---FIND INDEX OF HORIZONAL OPPOSITE LED
int horizontal_index(int i) {
  //-ONLY WORKS WITH INDEX < TOPINDEX
  if (i == BOTTOM_INDEX) {
    return BOTTOM_INDEX;
  }
  if (i == TOP_INDEX && EVENODD == 1) {
    return TOP_INDEX + 1;
  }
  if (i == TOP_INDEX && EVENODD == 0) {
    return TOP_INDEX;
  }
  return NUM_LEDS - i;
}

//---FIND INDEX OF ANTIPODAL OPPOSITE LED
int antipodal_index(int i) {
  int iN = i + TOP_INDEX;
  if (i >= TOP_INDEX) {
    iN = (i + TOP_INDEX) % NUM_LEDS;
  }
  return iN;
}

//---FIND ADJACENT INDEX CLOCKWISE
int adjacent_cw(int i) {
  int r;
  if (i < NUM_LEDS - 1) {
    r = i + 1;
  } else {
    r = 0;
  }
  return r;
}

//---FIND ADJACENT INDEX COUNTER-CLOCKWISE
int adjacent_ccw(int i) {
  int r;
  if (i > 0) {
    r = i - 1;
  } else {
    r = NUM_LEDS - 1;
  }
  return r;
}

void copy_led_array() {
  for (int i = 0; i < NUM_LEDS; i++) {
    ledsX[i][0] = leds[i].r;
    ledsX[i][1] = leds[i].g;
    ledsX[i][2] = leds[i].b;
  }
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
  leds[Pixel].r = red;
  leds[Pixel].g = green;
  leds[Pixel].b = blue;
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}

void one_color_all(int cred, int cgrn, int cblu) {       //-SET ALL LEDS TO ONE COLOR
  for (int i = 0 ; i < NUM_LEDS; i++ ) {
    leds[i].setRGB( cred, cgrn, cblu);
  }
}

void one_color_allHSV(int ahue) {    //-SET ALL LEDS TO ONE COLOR (HSV)
  for (int i = 0 ; i < NUM_LEDS; i++ ) {
    leds[i] = CHSV(ahue, thissat, 255);
  }
}

ОПИСНИЕ ПРОЕКТА: суть проекта сделать а-ля лампу ночник с 2 режимами. В первом режиме можно просто менять цвет в цветовом пространстве HSV. Во втором режиме переключать эффекты. Присутствуют 8 кнопок. 2 для изменения оттенка, 2 для изменения нассыщености , 2 для изменения контраста, 1 для вкл/выкл а у последьней очень интересный функционал. При одинарном клике происходит переключение эффектов. При двойном переключение между первым и вторым режимом.(см. чуть выше)
вот видео со всем функционалом кроме помледней кнопки

да уж, проект вроде легкий а такая проблема случилась 😬
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
505
149
Единственое что я менял это delay() на TimerMS.(будет забавно если из за этого вся проблема🤔)
Было бы нагляднее, если в коде остался в комметариях исходный вариант с delay
Пока не очевидно, как можно заменить delay() не трогая остальной код.

Часто для поиска ошибок используют вывод в Serial в ключевых (или спорных) местах алгоритма, и смотрят по до какой точки доходит выполнение и с какими параметрами, а до куда нет. Попробуйте сами.
 

Сотнег

★★★★★★★
15 Янв 2020
4,463
1,524
@MrFrevidens,
чтобы эффекты рисовались без нажатия кнопок нужно, чтобы функция handle_effects() вызывалась не только там, где обрабатывается нажатие кнопок.

К слову, там, где обрабатывается нажатие кнопок, вообще не должно быть вызовов update_leds.