Receiving Multiple DMX Universes?

NewLinuxFan

Well-known member
Is there a simple way to receive multiple universes of DMX without having to use Artnet? In the near future (November), I only need to receive 2 universes per Teensy.

Maybe one of the DMX libraries can do this by naming different variables for different Serial ports? It's unclear to me if TeensyDMX always uses "packetbuf" or if that can be specified as "packetbuf1" and "packetbuf2" for "dmxRX1" and "dmxRX2" using Serial1 and Serial2 for example.

I don't have much experience reading library code and have never written a library. Symbols like :: and -> look like gibberish to me. :) I suppose there's a first time for everything, and I'm not too old to learn new things... Hopefully the learning curve is manageable.
 
TeensyDMX supports multiple receivers by defining each with a different serial port, so it is possible. I suggest checking out the BasicReceive example as a starting point.
 
Thanks! It looks like you might be the person who wrote the library. If I'm understanding correctly, the get function does not use a buffer variable and draws from the most recent DMX packet, but the readPacket function does use a specified buffer variable.
 
Yes, that’s me. :)

Your description is correct. Check out the TeensyDMX.h header for documentation for each function.
 
Yes, that’s me. :)

Your description is correct. Check out the TeensyDMX.h header for documentation for each function.
So I finally got around to it, and receiving 2 universes works great on the Teensy 4.0 with Octo shield (setRX and jumper to an unused pin). However, on the Teensy 4.1 with Octo shield it occasionally glitches, even with only 1 universe. Not sure if there's a basic fix for this. If not, I better buy a bunch of 4.0's...
 
I’m not sure what “glitch” means here. Also, there’s no code, so I don’t know what’s happening. It could be your code and not the library. There’s a gazillion factors.
 
I’d love to help, but there isn’t any information other than the project “occasionally glitches.” The cause could be anything, and not necessarily the DMX library.
 
Hi Shawn, I really appreciate you taking a look. I wrote the simplest code for recreating the issue (below). It runs great on Teensy 4.0 even as low as 150MHz. But on the Teensy 4.1 I see glitches on my 8 x 18 test setup that seem to increase with more LED's (additional pretend ones in code), more DMX channels (requires increasing RX buffer sizes), and lower clock speed. The issue does not seem to be specific to 2 universes because I've seen it with code that only uses 1 universe. For some reason I always have to set buffer size to 1 more than packet size and start value to 0 for start address of 1.

C:
#include <cstring>
#include <TeensyDMX.h>
namespace teensydmx = ::qindesign::teensydmx;
teensydmx::Receiver dmxRx1{Serial1};
teensydmx::Receiver dmxRx2{Serial6};
uint8_t packetBuf1[513] {0};
uint8_t packetBuf2[513] {0};
int read;
int i;

#include <OctoWS2811.h>
const int ledsPerStrip = 300;
DMAMEM int displayMemory[ledsPerStrip * 6];
int drawingMemory[ledsPerStrip * 6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);

void setup() {
  dmxRx1.begin();
  dmxRx2.begin();
  //Serial6.setRX(1); /// For Teensy 4.0 with jumper wire.  Comment out for Teensy 4.1
  leds.begin();
  leds.show();
}

void loop() {
  read = dmxRx1.readPacket(packetBuf1, 0, 513);
  if (read != -1) {
    for (i = 0; i < ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[1], packetBuf1[2], packetBuf1[3]);}
    for (i = ledsPerStrip; i < 2*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[4], packetBuf1[5], packetBuf1[6]);}
    for (i = 2*ledsPerStrip; i < 3*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[7], packetBuf1[8], packetBuf1[9]);}
    for (i = 3*ledsPerStrip; i < 4*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[10], packetBuf1[11], packetBuf1[12]);}   
  }
  read = dmxRx2.readPacket(packetBuf2, 0, 513);
  if (read != -1) {
    for (i = 4*ledsPerStrip; i < 5*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[1], packetBuf2[2], packetBuf2[3]);}
    for (i = 5*ledsPerStrip; i < 6*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[4], packetBuf2[5], packetBuf2[6]);}
    for (i = 6*ledsPerStrip; i < 7*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[7], packetBuf2[8], packetBuf2[9]);}
    for (i = 7*ledsPerStrip; i < 8*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[10], packetBuf2[11], packetBuf2[12]);}
  }
  leds.show();
}
 
Here's the test setup with basic DMX circuits (2 isolated in's with daisy chain outs, and 2 outs). The power wires are soldered on the wrong end for convenience, but this doesn't affect signal quality with a small number of LED's.

20240213_211031_resized.jpg
 
It still glitches (freeze points with skips) on the Teensy 4.1. I also tried >= 12 and >= 1 with same result. Maybe it will just be a mystery to not worry about. I can use Teensy 4.0 at 528 MHz for longevity in case of heat, since it looks reliable at 150 MHz.
 
You must use at least "13" because you can't read index 12 (packetBuf[12]) without there being at least 13 valid bytes in the array. read >= 13 is correct, but read != -1 is not, and neither is comparing to "1" or "12" or anything less than "13".

Instead of leds.show() at the end of loop(), try this:
C++:
// Declare these where you declare the program variables:
elapsedMillis ledTimer;
constexpr uint32_t kFrameRate = 60;  // Try 30 as well

void loop() {
  //...
  if (ledTimer >= 1000/kFrameRate) {
    leds.show();
    ledTimer = 0;
  }
}
 
Last edited:
Thanks again. Unfortunately it did not remove the glitches. I went back to >= 13 for both instances. Tried 30 and 60 framerates. Also tried matching the framerate of the controller (40 fps) and one less at 39.

And thanks for making that library. Even in 2024, some of us are still using DMX. On the Teensy 4.1 the library does work well for DMX to PWM purposes.
 
I’m stumped as to why the Teensy 4.1 is behaving differently than the Teensy 4.0. Are you using the exact same code on both of them?
 
Last edited:
I’ve got one more thing for you to try:
C++:
void loop() {
  bool doShow = false;

  read = dmxRx1.readPacket(packetBuf1, 0, 513);
  if (read >= 13) {
    for (i = 0; i < ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[1], packetBuf1[2], packetBuf1[3]);}
    for (i = ledsPerStrip; i < 2*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[4], packetBuf1[5], packetBuf1[6]);}
    for (i = 2*ledsPerStrip; i < 3*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[7], packetBuf1[8], packetBuf1[9]);}
    for (i = 3*ledsPerStrip; i < 4*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf1[10], packetBuf1[11], packetBuf1[12]);}  

    doShow = true;
  }

  read = dmxRx2.readPacket(packetBuf2, 0, 513);
  if (read >= 13) {
    for (i = 4*ledsPerStrip; i < 5*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[1], packetBuf2[2], packetBuf2[3]);}
    for (i = 5*ledsPerStrip; i < 6*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[4], packetBuf2[5], packetBuf2[6]);}
    for (i = 6*ledsPerStrip; i < 7*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[7], packetBuf2[8], packetBuf2[9]);}
    for (i = 7*ledsPerStrip; i < 8*ledsPerStrip; i++)
    {leds.setPixel(i, packetBuf2[10], packetBuf2[11], packetBuf2[12]);}

    doShow = true;
  }

  if (doShow) {
    leds.show();
  }
}

I’ve re-coupled incoming DMX with leds.show(), but this time it’s not called continuously, only when there’s data.
 
Try to use DMX libraries like TeensyDMX. While TeensyDMX may not inherently support multiple universes on different serial ports out of the box, modify the library code to achieve this. Look for the code handling DMX reception, creating new variables for packet buffer and adjusting to read from the appropriate serial port for each universe.
 
Back
Top