ArtNet - WS2812/WS2815 - different output pins

Hello all,

currently we're designing a controllerbox based on Arduino Mega 2560 with ethernet shield. The Controller must be able to send out three different WS2812/WS2815 streams. Every data stream is connected to 5 meter WS2815 Led Tape (60led/m). Data is transmitting via ArtNet Unicast to Arduinos IP 2.30.1.1. Universes 1+2 are sending to outPin 11, universes 3+4 to outPin 12 and universes 5+6 to outPin 13. We had created following code:

/*

This example will receive multiple universes via Artnet and control a strip of ws2811 leds via 

Adafruit's NeoPixel library: https://github.com/adafruit/Adafruit_NeoPixel

This example may be copied under the terms of the MIT license, see the LICENSE file for details

*/



#include <Artnet.h>

#include <Ethernet.h>

#include <EthernetUdp.h>

#include <SPI.h>

#include <Adafruit_NeoPixel.h>



// Neopixel settings

const int numLeds0 = 300; // change for your setup
const int numLeds1 = 300; // change for your setup
const int numLeds2 = 300; // change for your setup

const int numberOfChannels0 = numLeds0 * 3; // Total number of channels you want to receive (1 led = 3 channels)
const int numberOfChannels1 = numLeds1 * 3; // Total number of channels you want to receive (1 led = 3 channels)
const int numberOfChannels2 = numLeds2 * 3; // Total number of channels you want to receive (1 led = 3 channels)

const byte dataPin0 = 11;
const byte dataPin1 = 12;
const byte dataPin2 = 13;

const bool showleds0 = true;
const bool showleds1 = true;
const bool showleds2 = true;

Adafruit_NeoPixel leds0 = Adafruit_NeoPixel(numLeds0, dataPin0, NEO_GRB + NEO_KHZ800);
//Adafruit_NeoPixel leds1 = leds0;
//Adafruit_NeoPixel leds2 = leds0;
Adafruit_NeoPixel leds1 = Adafruit_NeoPixel(numLeds1, dataPin1, NEO_GRB + NEO_KHZ800);
//Adafruit_NeoPixel leds0 = leds1;
//Adafruit_NeoPixel leds2 = leds1;
Adafruit_NeoPixel leds2 = Adafruit_NeoPixel(numLeds2, dataPin2, NEO_GRB + NEO_KHZ800);



// Artnet settings

Artnet artnet;

const int startUniverse0 = 1; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as 0.
const int startUniverse1 = 3;
const int startUniverse2 = 5;


// Check if we got all universes

const int maxUniverses0 = numberOfChannels0 / 512 + ((numberOfChannels0 % 512) ? 1 : 0);
const int maxUniverses1 = numberOfChannels1 / 512 + ((numberOfChannels1 % 512) ? 1 : 0);
const int maxUniverses2 = numberOfChannels2 / 512 + ((numberOfChannels2 % 512) ? 1 : 0);

bool universesReceived0[maxUniverses0];
bool universesReceived1[maxUniverses1];
bool universesReceived2[maxUniverses2];

bool sendFrame = 1;

int previousDataLength0 = 0;
int previousDataLength1 = 0;
int previousDataLength2 = 0;

long count = 0;


// Change ip and mac address for your setup

byte ip[] = {2, 30, 1, 1};

byte mac[] = {0x08, 0xE9, 0xE5, 0x00, 0x69, 0xEC}; // make sure this is different than any other mac address in your network



void setup()

{

  Serial.begin(57600);

  artnet.begin(mac, ip);

  if(showleds0)
    leds0.begin();
  if(showleds1)
    leds1.begin();
  if(showleds2)
    leds2.begin();

  for(int i=0 ; i < 1 ; i++ )
  {
    initTest();
    delay(500);
  }



  // this will be called for each packet received

  artnet.setArtDmxCallback(onDmxFrame);

}



void loop()

{

  // we call the read function inside the loop

  artnet.read();

}



void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)

{

  sendFrame = 1;
  count++;
  bool activeOut0 = false;
  bool activeOut1 = false;
  bool activeOut2 = false;

  // set brightness of the whole strip 

  if (universe == 15)
  {
    leds0.setBrightness(data[0]);
    leds0.show();

    leds1.setBrightness(data[0]);
    leds1.show();

    leds2.setBrightness(data[0]);
    leds2.show();
  }

  // Store which universe has got in

  if ((universe >= startUniverse0) && (universe < (startUniverse0 + maxUniverses0)))
  {
    activeOut0 = true;
    
    //if ((universe - startUniverse0) < maxUniverses0)
      universesReceived0[universe - startUniverse0] = 1;
  }
  if ((universe >= startUniverse1) && (universe < (startUniverse1 + maxUniverses1)))
  {
    activeOut1 = true;
    //leds1 = Adafruit_NeoPixel(numLeds1, dataPin1, NEO_GRB + NEO_KHZ800);
    //leds1.begin();
    
    //if ((universe - startUniverse1) < maxUniverses1)
      universesReceived1[universe - startUniverse1] = 1;
  }
  if ((universe >= startUniverse2) && (universe < (startUniverse2 + maxUniverses2)))
  {
    activeOut2 = true;
    
    //if ((universe - startUniverse2) < maxUniverses2)
      universesReceived2[universe - startUniverse2] = 1;
  }



  for (int i = 0 ; i < maxUniverses0 ; i++)
  {
    if (universesReceived0[i] == 0)
    {
      //Serial.println("Broke");
      //sendFrame = 0;
      break;
    }
  }



  // read universe and put into the right part of the display buffer

  for (int i = 0; i < length / 3; i++)
  {
    if ((activeOut0 && showleds0))
    {
      int led = i + (universe - startUniverse0) * (previousDataLength0 / 3);

      if (led < numLeds0)
        leds0.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
    }

    if (activeOut1 && showleds1)
    {
      int led = i + (universe - startUniverse1) * (previousDataLength1 / 3);

      if (led < numLeds1)
        leds1.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
    }

    if (activeOut2 && showleds2)
    {
      int led = i + (universe - startUniverse2) * (previousDataLength2 / 3);

      if (led < numLeds2)
        leds2.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
    } 
  }

  if(showleds0)
    previousDataLength0 = length;     
  if(showleds1)
    previousDataLength1 = length;
  if(showleds2)
    previousDataLength2 = length;

  if (sendFrame)
  {
    if(activeOut0 && false)
    {
      leds0.show();
      memset(universesReceived0, 0, maxUniverses0);
    }
    if(activeOut1)
    {
      leds1.show();
      memset(universesReceived1, 0, maxUniverses1);
    }
    if(activeOut2 && false)
    {
      leds2.show();
      memset(universesReceived2, 0, maxUniverses2);
    }
    
  }

}


void initTest()
{

  int waitTime = 333;
  
  if(showleds0)
  {
    for (int i = 0 ; i < numLeds0 ; i++)
      leds0.setPixelColor(i, 127, 0, 0);

    leds0.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds0 ; i++)
      leds0.setPixelColor(i, 0, 127, 0);

    leds0.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds0 ; i++)
      leds0.setPixelColor(i, 0, 0, 127);

    leds0.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds0 ; i++)
      leds0.setPixelColor(i, 0, 0, 0);

    leds0.show();
  }

  if(showleds1)
  {
    for (int i = 0 ; i < numLeds1 ; i++)
      leds1.setPixelColor(i, 127, 0, 0);

    leds1.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds1 ; i++)
      leds1.setPixelColor(i, 0, 127, 0);

    leds1.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds1 ; i++)
      leds1.setPixelColor(i, 0, 0, 127);

    leds1.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds1 ; i++)
      leds1.setPixelColor(i, 0, 0, 0);

    leds1.show();
  }

  if(showleds2)
  {
    for (int i = 0 ; i < numLeds2 ; i++)
      leds2.setPixelColor(i, 127, 0, 0);

    leds2.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds2 ; i++)
      leds2.setPixelColor(i, 0, 127, 0);

    leds2.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds2 ; i++)
      leds2.setPixelColor(i, 0, 0, 127);

    leds2.show();

    delay(waitTime);

    for (int i = 0 ; i < numLeds2 ; i++)
      leds2.setPixelColor(i, 0, 0, 0);

    leds2.show();
  }

}

The sketch is based on topic: Arduino Forum

First and second universes are transmitting smooth on pin 11, from 3rd universe refreshing stucks more and more up to blackout. Maybe it becomes overlays, depends on callback-function "Artnet.read". But we think this function schouldnt executed separatly for every pin. We are not sure and a bit desperated meanwhile.

Thank You
Matthias