ARDUINO Подсветка клавиатуры на WS2812. Не срабатывает case.

Oleg1979s

✩✩✩✩✩✩✩
9 Фев 2020
3
0
Всем привет. Хочу сделать сыну на 10 лет подарок - подарить свой стационарный комп. С ним есть очень не плохая клавиатура Logitech G11, но там сгорела подсветка. Примастерил я туда ленту на ws2812 и digispark attiny85, подключил кнопку. В ардуино я не силен, да и что-то не сильно получается. Скетч собрал на примерах Алекса и его скетчах. Короче код:
C:
#include "FastLED.h"          // библиотека для работы с лентой

#include "GyverButton.h"

#define LED_COUNT 12          // число светодиодов в кольце/ленте

#define LED_DT 1             // пин, куда подключен DIN ленты

int max_bright = 240;          // максимальная яркость (0 - 255)



#define BTN_PIN 0  // пин кнопки

#define MODE_AM 4    // количество режимов (от 0 до указанного)

GButton butt1(BTN_PIN);

byte mode = 0;       // переменная режима



volatile boolean changeFlag;



int BOTTOM_INDEX = 0;        // светодиод начала отсчёта

int TOP_INDEX = int(LED_COUNT / 2);

int EVENODD = LED_COUNT % 2;

struct CRGB leds[LED_COUNT];



int thisdelay = 60;          //  время задержки

int thissat = 255;           //-FX LOOPS DELAY VAR

int idex = 0;                //-LED INDEX (0 to LED_COUNT-1

int ihue = 0;                //-HUE (0-255)

//-----------------------------------------------

void setup()

{

  Serial.begin(9600);

  LEDS.setBrightness(max_bright);  // ограничить максимальную яркость

  LEDS.addLeds<WS2811, LED_DT, GRB>(leds, LED_COUNT);  // настройки для нашей ленты (ленты на WS2811, WS2812, WS2812B)





  colorWipe(10, 10, 255, 100); // blue плавное заполнение цветом





  LEDS.show();                     // отослать команду

pinMode(BTN_PIN, INPUT_PULLUP);                             // задаю пин на считывание

}

//-----------------------------------------------

void loop() {

   butt1.tick();             // обязательная функция отработки. Должна постоянно опрашиваться

  if (butt1.isPress()) {    // правильная отработка нажатия с защитой от дребезга

    // увеличиваем переменную номера режима. Если вышла за количество режимов - обнуляем

    if (++mode >= MODE_AM) mode = 0;

    // всё переключение в итоге сводится к оператору switch

    // переключение и вызов происходит только при нажатии!!!

}

  switch (mode) {

       case 0: ; break;                                                              // stop

       case 1: rainbow_fade(); break;                                   // плавная смена цветов всей ленты

       case 2: ; break;                                                               // stop остановка на выбранном цвете

       case 3: rainbowCycle(40);  break;        // кольцевой эффект радуги

  }

}

//-----------------------------плавное заполнение цветом-----------------------------------------

void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {

  for (uint16_t i = 0; i < LED_COUNT; i++) {

    setPixel(i, red, green, blue);

    FastLED.show();

    if (safeDelay(SpeedDelay)) return;

  }

}

//-------------------------плавная смена цветов всей ленты ------------------

void rainbow_fade() { 

  ihue++;

  if (ihue > 255) {

    ihue = 0;

  }

  for (int idex = 0 ; idex < LED_COUNT; idex++ ) {

    leds[idex] = CHSV(ihue, thissat, 255);

  }

  LEDS.show();

  if (safeDelay(thisdelay)) return;

}



//-------------------------------кольцевой эффект радуги---------------------------------------

void rainbowCycle(int SpeedDelay) {

  byte *c;

  uint16_t i, j;



  for (j = 0; j < 256 * 1; j++) { // 1 cycles of all colors on wheel

    for (i = 0; i < LED_COUNT; i++) {

      c = Wheel(((i * 256 / LED_COUNT) + j) & 255);

      setPixel(i, *c, *(c + 1), *(c + 2));

    }

    FastLED.show();

     if (safeDelay(SpeedDelay)) return;

  }

}



byte * Wheel(byte WheelPos) {

  static byte c[3];



  if (WheelPos < 85) {

    c[0] = WheelPos * 3;

    c[1] = 255 - WheelPos * 3;

    c[2] = 0;

  } else if (WheelPos < 170) {

    WheelPos -= 85;

    c[0] = 255 - WheelPos * 3;

    c[1] = 0;

    c[2] = WheelPos * 3;

  } else {

    WheelPos -= 170;

    c[0] = 0;

    c[1] = WheelPos * 3;

    c[2] = 255 - WheelPos * 3;

  }



  return c;

}

// ------------------переменная ---------------

boolean safeDelay(int delTime) {

  uint32_t thisTime = millis();

  while (millis() - thisTime <= delTime) {

    if (changeFlag) {

      changeFlag = false;

      return true;

    }

  }

  return false;

}

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 < LED_COUNT; i++ ) {

    setPixel(i, red, green, blue);

  }

  FastLED.show();

}
Проблема в том, что кода запущен "кольцевой эффект радуги" case 3, то больше на кнопку не реагирует и вернутся на case 0 не получается. Я не понимаю как сделать прерывания. Вообще, хотел сделать скетч типа такого: перелистывание режимов по клику (плавная смена цветов всей ленты, радуга, белый цвет ну может еще что-то), нажал и удержал - плавно сменяется цвет всей клавиатуры, отпустил - остановилось на выбранном цвете, двойной клик плюс удерживание - смена яркости. Но я такое не осилю. Пробовал примеры GyverButton, но что-то не получается. Пожалуйста, помогите.
 
Изменено:

Oleg1979s

✩✩✩✩✩✩✩
9 Фев 2020
3
0
@Oleg1979s, отдельно rainbowCycle() работает?
Да, работает.
Короче, понял, что я упустил при переделке скетча "Куча эффектов для WS2812b" - удалил прерывания и припаял провод кнопки не к там. Новый скетч:
C:
#include "FastLED.h"          // библиотека для работы с лентой
#define BTN_PIN 2  // пин кнопки с прерыванием INT0
#define LED_COUNT 12          // число светодиодов в кольце/ленте
#define LED_DT 1             // пин, куда подключен DIN ленты
int max_bright = 250;          // максимальная яркость (0 - 255)
int bright = 140;          // максимальная яркость white (0 - 255)
byte num_modes = 5;         // количество режимов (от 0 до указанного)
volatile byte ledMode = 0;       // переменная режима
volatile uint32_t btnTimer;
volatile byte modeCounter;
volatile boolean changeFlag;
struct CRGB leds[LED_COUNT];
// ---------------переменные-----------
int thisdelay = 60;          //  время задержки
int thissat = 255;           //-SATURATION  (0-255)
int idex = 0;                //-LED INDEX (0 to LED_COUNT-1
int ihue = 0;                //-HUE  (0-255)
//-----------------------------------------------
void setup()
{
  Serial.begin(9600);
  LEDS.setBrightness(max_bright);  // ограничить максимальную яркость
  LEDS.addLeds<WS2811, LED_DT, GRB>(leds, LED_COUNT);  // настройки для нашей ленты (ленты на WS2811, WS2812, WS2812B)
  colorWipe(10, 10, 255, 100); // blue плавное заполнение цветом
  LEDS.show();                     // отослать команду
  pinMode(BTN_PIN, INPUT_PULLUP);                             // задаю пин на считывание
  attachInterrupt(0, btnISR, FALLING);  // прерывание при смене значения на порту с HIGH на LOW
}
//-----------------------------------------------
void loop() {
  switch (ledMode) {                                        // выбор режимов
       case 0: delay (50); break;                                                              // stop
       case 1: rainbow_fade(); break;                                   // плавная смена цветов всей ленты
       case 2: delay (50); break;                                                               // stop остановка на избранном цвете
       case 3: rainbowCycle(40);  break;        // кольцевой эффект радуги
       case 4: colorWipe(bright-10, bright, bright, 100);  break; // белый цвет ленты
  }
}
//-------------------------------------------
void btnISR() {
  if (millis() - btnTimer > 250) {
    btnTimer = millis();  // защита от дребезга
    if (++modeCounter >= num_modes) modeCounter = 0;
    ledMode = modeCounter;    // получаем новый номер следующего режима

    changeFlag = true;
  }
}

//-----------------------------плавное заполнение цветом-----------------------------------------
void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
  for (uint16_t i = 0; i < LED_COUNT; i++) {
    setPixel(i, red, green, blue);
    FastLED.show();
    if (safeDelay(SpeedDelay)) return;
  }
}
//-------------------------плавная смена цветов всей ленты ------------------
void rainbow_fade() {  
  ihue++;
  if (ihue > 255) {
    ihue = 0;
  }
  for (int idex = 0 ; idex < LED_COUNT; idex++ ) {
    leds[idex] = CHSV(ihue, thissat, 255);
  }
  LEDS.show();
  if (safeDelay(thisdelay)) return;
}
//-------------------------------кольцевой эффект радуги---------------------------------------
void rainbowCycle(int SpeedDelay) {
  byte *c;
  uint16_t i, j;

  for (j = 0; j < 256 * 1; j++) { // 1 cycles of all colors on wheel
    for (i = 0; i < LED_COUNT; i++) {
      c = Wheel(((i * 256 / LED_COUNT) + j) & 255);
      setPixel(i, *c, *(c + 1), *(c + 2));
    }
    FastLED.show();
     if (safeDelay(SpeedDelay)) return;
  }
}

byte * Wheel(byte WheelPos) {
  static byte c[3];

  if (WheelPos < 85) {
    c[0] = WheelPos * 3;
    c[1] = 255 - WheelPos * 3;
    c[2] = 0;
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    c[0] = 255 - WheelPos * 3;
    c[1] = 0;
    c[2] = WheelPos * 3;
  } else {
    WheelPos -= 170;
    c[0] = 0;
    c[1] = WheelPos * 3;
    c[2] = 255 - WheelPos * 3;
  }
  return c;
}
// ------------------переменная ---------------
boolean safeDelay(int delTime) {
  uint32_t thisTime = millis();
  while (millis() - thisTime <= delTime) {
    if (changeFlag) {
      changeFlag = false;
      return true;
    }
  }
  return false;
}

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 < LED_COUNT; i++ ) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}
Все как бы работает. В Digispark прерывание работает только на втором пине PB2/INT0 (если считать от 0). Правда иногда при нажатии отрабатывает не правильно switch. Например: работает case 2, нажимаю кнопку чтобы эффект остановился на нужном цвете, а срабатывает не case3, а case4 запуская радугу. Но так не всегда. Хотелось бы еще регулировку яркости, но не знаю как сделать. И не нравится, что есть case 0: delay (50); break;, но без него стартовый синий цвет сразу переходит на case 1: rainbow_fade(); break; // плавная смена цветов всей ленты. А мне нужно чтобы стартовый синий не менялся, пока первый раз не нажмешь кнопку.
 
Изменено:

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
замените на

case 0: setAll(0, 0, 250); break;

и будет синий цвет при старте
 

Oleg1979s

✩✩✩✩✩✩✩
9 Фев 2020
3
0
замените на

case 0: setAll(0, 0, 250); break;

и будет синий цвет при старте
Он тогда всегда будет при переключении case. Пока что и так нравится, только антидребезг плохо работает - перескакивает case на несколько пунктов. Может кондер припаять на 100nf?