Конфликт FastLED и IrRemote

Blackmamba3356
Offline
Зарегистрирован: 19.10.2017

Всем добрый вечер. 
Столкнулся с такой ситуацией, скорее всего, мне просто не хватает опыта, но...

Сделал простую гирлянду на диодах WS2812B, написал несколько режимов и управление переключениями режимов с ИК пульта. Ситуация такая, пока в массиве CRGB указано 5-6 диодов, все в порядке, как только количество диодов становится 8 и больше, данные с пульта начинают идти некорректно.

Возможно, в моем скетче что-то криво, но, смысл такой, что с 5 диодами все работает так, как я задумал, как только ставить больше, начинаются чудеса. 

Скетч и скриншоты того, что происходит при разных значениях количества диодов прилагаю.
Очень надеюсь на коллективный разум. неверные значения, при каждом нажатии одной и  той же кнопки, значения разные.Верные значения

#include "IRremote.h"
#include "FastLED.h"
#define DATA_PIN    12
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    5

#define FRAMES_PER_SECOND  120
IRrecv irrecv(2); // указываем вывод, к которому подключен приемник
decode_results results;
CRGB leds[NUM_LEDS];

int x = 0;
uint8_t gHue = 0;
int BRIGHTNESS = 150;


void setup() {
  
  delay(2000); // 3 second delay for recovery
  irrecv.enableIRIn(); // запускаем прием
  Serial.begin(9600); // выставляем скорость COM порта
   // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);


  
}
void loop()
{
  
   FastLED.setBrightness(BRIGHTNESS); 
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  EVERY_N_MILLISECONDS( 20 ) { gHue++; }
  FastLED.show();
  reader ();
  
}
void reader() // Функция считывания с приемника
{
  if (irrecv.decode(&results)) // получили результат с приемника
  { 
    if(results.value == 0xFF20DF) 
    {
      x=1; // присваиваем значение переменной
    }
    if(results.value == 0xFFA05F)
    {
      x=2; // Режим 2
    }
    if(results.value == 0xFF609F)
    {
      x=3; // Режим 3
    }
    if(results.value == 0xFFE01F)
    {
      x=4; // Режим 4
    }
     if(results.value == 0xFF02FD)
    {
      x=5; // Выключение
    }
     if(results.value == 0xFF3AC5)
    {
        BRIGHTNESSPLUS (); // Увеличение яркости
    }
    if(results.value == 0xFFBA45)
    {
        BRIGHTNESSMINUS (); // Увеличение яркости
    }
  
     switch (x) // Сравниваем значение Х 
     {
       case 1:
      rainbow(); // Включаем режим 1
      break;
      case 2: 
      confetti(); // Включаем режим 2
      break; 
      case 3:
      sample2(); // Включаем режим 3
      break;
      case 4:
      OrangeRed(); // Красно-оранжевый
      break; 
      case 5:
      Shutdown(); // Включаем режим 4
      break;
     }
     delay(300);
     irrecv.resume(); // Ждем следущей команды
     Serial.println (x); 
      Serial.println (BRIGHTNESS); // Выводим в серийный порт значение переменной Х
      Serial.println( results.value, HEX );
  }
  else // Если данные не пришли,
  { 
    switch (x) //  сравниваем значение переменной Х и включаем:
     {
      case 1:
      rainbow(); // Включаем режим 1
      break;
      case 2: 
      confetti(); // Включаем режим 2
      break; 
      case 3:
      sample2(); // Включаем режим 3
      break;
      case 4:
      OrangeRed(); // Включаем режим 4
      break; 
      case 5:
      Shutdown(); // Включаем режим 4
      break;
     }
  }
}

void rainbow() // режим 1
{
   fill_rainbow( leds, NUM_LEDS, gHue, 7);
}
void confetti() // Режим 2
{
   fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
}
void sample2() // Режим 3
{
   leds[0] = CRGB::Blue;
   leds[1] = CRGB::Blue;
   leds[2] = CRGB::White;
   leds[3] = CRGB::Red;
   leds[4] = CRGB::Red;
   FastLED.show();
}

 void OrangeRed() // Режим 4
 {
  fill_solid( leds, NUM_LEDS,CRGB::OrangeRed);
 }

void BRIGHTNESSPLUS() // Функция увеличения яркости
{
 if (BRIGHTNESS < 255)
 {
  BRIGHTNESS = BRIGHTNESS + 5;
 }
}

void BRIGHTNESSMINUS() // Функция уменьшения яркости
{
 if (BRIGHTNESS > 0)
 {
  BRIGHTNESS = BRIGHTNESS - 5;
 }
}
void Shutdown()
{
  fadeToBlackBy( leds, NUM_LEDS, 3); // Плавное выключение ленты
 // fill_solid( leds, NUM_LEDS,CRGB::Black);
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Есть у меня новогодняя коробочка с пиксельной гирляндой, фастледом и irremote...  Тоже были проблемы с непонятными кодами. Не помню уж в чем там конкретно дело было, но в камментах я себе написал, что чем длиннее луп, тем больше приходит битых пакетов. А у вас там и дилеи и вывод в serial на 9600.

Так же, можно предположить, что у вас фастледом при выводе на 2812 запрещаются прерывания, а их использует irremote.

Ну и, в финале хочу отметить, что вижу ваш фастлед, нацеленным на, скорее всего, программную эмуляцию SPI. Попробуйте переключится на использование хардварной SPI/USART шины : https://github.com/FastLED/FastLED/wiki/SPI-Hardware-or-Bit-banging

 

Blackmamba3356
Offline
Зарегистрирован: 19.10.2017

Большое спасибо за наводку. Раньше шерстил документацию FastLED, но так и не дошел до этой главы. Похоже, проблема именно в прерываниях. Буду думать. 
 

Blackmamba3356
Offline
Зарегистрирован: 19.10.2017

Использование хардварного SPI не помогает. Очевидно, проблему sadman41 определил правильно. Проблема в том, что WS2812 блокирует прерывания на момент формирования и отправки пакета. МОжет. у кого-нибудь, есть мысли, как обойти эту проблему?

sadman41
Offline
Зарегистрирован: 19.10.2016

Закомментируйте FastLed.show() и сразу узнаете, он ли гадит.

Или сообщите адрес - я вам свою мигалку дам, проверите.

Blackmamba3356
Offline
Зарегистрирован: 19.10.2017

Адрес: Blackmamba3356@gmail.com

На счет FastLED.show, пробовал закомментить, но в скетче есть команды, которые заставляют диоды загораться без этой команды. Если пришлете, буду благодарен