TeensyDMX and FastLED - cant get them to work simultaneously

Status
Not open for further replies.

LasseBakHansen

New member
Hi All,

I am currently setting up my new project to drive some WS2815 LED strips using incoming DMX data.

I'm using the TeensyDMX library to read the incoming DMX data, and driving the FastLED from the incoming values.

I know the setup is working as i have used the BasicReceive example and working perfectly - the serial monitor is correctly showing any change in channel 1 data and channel 10, 11 & 12.

I have also created a super basic "moving dot" sketch for driving the LEDs with FastLED, this also works perfectly.

However, when i come to add the "moving dot" sketch into the BasicReceive sketch to use the values to change the dots colour, it doesnt work - the lights flicker int he right direction like its trying to do the moving dot (but they do change colour according to DMX data), and serial monitor does show the right values however after a significant lag and erratic. Its seems that the teensy is unable to drive the WS2815 LEDs and ALSO receive the serial data at the same time.

I have included the code below:

Code:
#include <FastLED.h>
#define DATA_PIN  8

#define NUM_LEDS_PER_STRIP 72
#define NUM_STRIPS 1
#define NUM_LEDS   NUM_LEDS_PER_STRIP  
CRGB leds[NUM_LEDS_PER_STRIP * NUM_STRIPS];

volatile byte r1 = 255;
volatile byte g1 = 255;
volatile byte b1 = 0;


#include <cstring>
#include <TeensyDMX.h>
namespace teensydmx = ::qindesign::teensydmx;

// Create the DMX receiver on Serial1.
teensydmx::Receiver dmxRx{Serial1};

// The last value on the channel, for knowing when to print a change
// (Example 1).
uint8_t lastValue = 0;

// Buffer in which to store packet data (Example 2).
uint8_t packetBuf[3]{0};

// The last values received on channels 10-12, initialized to zero.
uint8_t rgb[3]{0};

void setup() {
  
  // Serial initialization, for printing things
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {
    // Wait for initialization to complete or a time limit
  }
  Serial.println("Starting BasicReceive.");

  // Turn on the LED, for indicating activity
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWriteFast(LED_BUILTIN, HIGH);

  // Start the receiver
  dmxRx.begin();

  // Print the first values
  lastValue = dmxRx.get(1);
  Serial.printf("Channel 1: %d\n", lastValue);

  // Note: If this reads < 3 bytes then the other values will stay at zero
  // (because 'rgb' was initialized to zero, above)
  dmxRx.readPacket(rgb, 10, 3);
  Serial.printf("RGB: %d %d %d\n", rgb[0], rgb[1], rgb[2]);


FastLED.addLeds<NUM_STRIPS, WS2812B,DATA_PIN,GRB>(leds, NUM_LEDS_PER_STRIP);

  
}

void loop() {
  // The following two examples print values when they change

  // Example 1. Get the current value of channel 1.
  // This will return zero for no data (and also for data that's zero)
  uint8_t v = dmxRx.get(1);
  if (v != lastValue) {
    lastValue = v;
    Serial.printf("Channel 1: %d\n", v);
  }

  // Example 2. Read channels 10-12.
  // A return of -1 means no data, and a value < 3 means that there was data,
  // but the received packet wasn't large enough to contain channels 10-12
  int read = dmxRx.readPacket(packetBuf, 10, 3);
  if (read == 3) {
    if (memcmp(packetBuf, rgb, 3) != 0) {
      memcpy(rgb, packetBuf, 3);
      Serial.printf("RGB: %d %d %d\n", rgb[0], rgb[1], rgb[2]);
    }
  }



  for(int dot = 0; dot < NUM_LEDS; dot++) { 
            leds[dot].r = rgb[0];
            leds[dot].g = rgb[1];
            leds[dot].b = rgb[2];
            FastLED.show();
            
            // clear this led for the next time around the loop
            leds[dot].r = 0;
            leds[dot].g = 0;
            leds[dot].b = 0;
            delay(50);
        }
}
 
You could do a quick test and add

__disable_irq();

before FastLED.show();

and

__enable_irq();

after. In my experiments it has shown that the WS2815 strips are very timing sensitive.
 
Status
Not open for further replies.
Back
Top