FastLED causes serial data corruption, thoughts?

I'm using an HC-12 module with the SoftwareSerial library as a way to control LEDs (overkill, I'm aware :D), but whenever I use FastLED.show() or FastLED.delay() anywhere in my code around 30% of the serial data recieved by the arduino is corrupted. If i remove these terms the problem does not persist, but the LEDs are obviously not driven.

It seems to me that this is caused by FastLED's interrupts occuring in the middle of serial transfer. I have read the FastLED page for intterupts, and tried #define FASTLED_ALLOW_INTERRUPTS 0 and #define FASTLED_INTERRUPT_RETRY_COUNT 1, but these seem to have no effect.

I know the sent data is correct, as it's recieved perfectly without any fastLED code. The data used to be much larger, but right now it is only 1 character, and the corruption still occurs.

Any ideas? I'm very stuck!

The relevant code (with irrelevant parts cut out):

#include <SoftwareSerial.h>
#define FASTLED_INTERRUPT_RETRY_COUNT 1
#include <FastLED.h>
SoftwareSerial HC12(5, 6); // HC-12 TX Pin, HC-12 RX Pin
CRGB leds[96];
CRGBPalette16 currentPalette = RainbowColors_p;
TBlendType    currentBlending;
  
void setup() {
  //Serial Setup
  Serial.begin(9600);                   // Serial port to computer
  HC12.begin(9600);                     // Serial port to HC12

  //FastLED Setup
  FastLED.addLeds<WS2811, A5, GRB>(leds, 96).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness(64);
  currentPalette = RainbowColors_p;
  currentBlending = LINEARBLEND;
}


void loop() {
  //Get character from hc-12
  static char dataRecord = '0';
  noInterrupts();   //Disable interrupts while getting character
  while (HC12.available()) {        // If HC-12 has data
    dataRecord = HC12.read();
  }
  interrupts();   //Re-enable interrupts
  
  //String prints to terminal and stores to prevent repeats
  static char printChar = '0';
  if(dataRecord != printChar){
    printChar = dataRecord;
    Serial.println(printChar);
  }


  static uint8_t startIndex = 0;
  if(dataRecord == '0' || dataRecord == '1' || dataRecord == '2' || dataRecord == '3' ||dataRecord == '4' || dataRecord == '5'){  //stops refresh when erronious data is recieved
    startIndex = startIndex + 1; //Changes motion speed
    FillLEDs(startIndex);
    FastLED.delay(10);
  }
  //Mode-dependant loop
  if(dataRecord == '0'){
    currentPalette = CRGBPalette16(CRGB::Black);
  }
  else if(dataRecord == '1'){
    (...)
}

void FillLEDs(uint8_t colorIndex)
{
    uint8_t brightness = 255;
    
    for( int i = 0; i < 96; i++) {
        leds[i] = ColorFromPalette(currentPalette, colorIndex, brightness, currentBlending);
        colorIndex += 3;
    }
}

#include <SoftwareSerial.h>Uh-oh

TheMemberFormerlyKnownAsAWOL:
#include <SoftwareSerial.h>Uh-oh

What's wrong with SoftwareSerial? I'm running the program on a Nano which i believe only has one real serial interface.

FastLED has critical timing, so disables interrupts during the time the display is updated.
That's going to play havoc with software serial timing.
Hardware serial should be fine.

TheMemberFormerlyKnownAsAWOL:
FastLED has critical timing, so disables interrupts during the time the display is updated.
That's going to play havoc with software serial timing.
Hardware serial should be fine.

I switched to the proper serial and the problems are less severe but still exist, usually missing a few characters. Any ideas at all?

I had this problem as well and ended up solving it by only calling .show() once for all updates that happened at the end of loop() and then only IF changes happened (ie, absolutely minimised the calls to show()) and setting the serial speed as fast as it can go to minimise the time to transfer messages.

As it turns out, there is an extraordinarily elegant (Read:Hacky) solution.

I'm sending the required data 5 times and it averages out.

I am at the absolute maximum baud of my module (115200), I call show() only once at the end of my program loop and never call FastLED.delay (has show built in), i'm using hardware serial, I'm disabling the FastLED interrupts, and I've tried everything i can think of that still has the receiver be in its RX only mode, so I just reduced the serial timeout to 10ms and discard known erronious data and its not failed to get through yet.

No matter what, calling show() or delay() at any point in the program cases the serial data transfer to fail intermittently.

If you happen to have the same issue and found this thread, there isnt an elegant way, swallow your ego or you will be up at 5am dreaming 'Just one more recompile!'. :stuck_out_tongue:

zelanious:
If you happen to have the same issue and found this thread, there isnt an elegant way, swallow your ego or you will be up at 5am dreaming 'Just one more recompile!'. :stuck_out_tongue:

There is an elegant way (at least for HardwareSerial).

Sender sends 1 character / byte and waits for reply from receiver.
2)
When receiver receivers character, it echoes it back to sender.
3)
Back to (1) till message completed.