Code help Artnet two universe

I would be glad if you could help me on this code, the problem is, 3-channel x 170 = 510 DMX channels in this software. 2x512 how I can do this by modifying the software. I want to use to connect more LEDs. So how do I edit 2 as Artnet.

In short, if you want to edit 2 universe as ArtNet

Meanwhile sorry for my bad english.

Thank you.

/*
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 numLeds = 240; // change for your setup
const int numberOfChannels = numLeds * 3; // Total number of channels you want to receive (1 led = 3 channels)
const byte dataPin = 2;
Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ800);

// Artnet settings
Artnet artnet;
const int startUniverse = 0; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as 0.

// Check if we got all universes
const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
bool universesReceived[maxUniverses];
bool sendFrame = 1;
int previousDataLength = 0;

// Change ip and mac address for your setup
byte ip[] = {192, 168, 2, 2};
byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};

void setup()
{
  //Serial.begin(115200);
  artnet.begin(mac, ip);
  leds.begin();
  initTest();

  // 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;
  // set brightness of the whole strip 
  if (universe == 15)
  {
    leds.setBrightness(data[0]);
    leds.show();
  }

  // Store which universe has got in
  if ((universe - startUniverse) < maxUniverses)
    universesReceived[universe - startUniverse] = 1;

  for (int i = 0 ; i < maxUniverses ; i++)
  {
    if (universesReceived == 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++)
  {
    int led = i + (universe - startUniverse) * (previousDataLength / 3);
    if (led < numLeds)
      leds.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
  }
  previousDataLength = length;     
  
  if (sendFrame)
  {
    leds.show();
    // Reset universeReceived to 0
    memset(universesReceived, 0, maxUniverses);
  }
}

void initTest()
{
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 127, 0, 0);
  leds.show();
  delay(500);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 127, 0);
  leds.show();
  delay(500);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 0, 127);
  leds.show();
  delay(500);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 0, 0);
  leds.show();
}

Have you got enough RAM?

Hi

i am using arduino mega, I use a different product than the case of not enough RAM.

Thank you

Exactly how many Neopixel LED's do you want to control. The example you posted seems pretty much all you need once you have entered the correct values in the required places as it handles multi universes.

const int numLeds = 240; // change for your setup

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

// Change ip and mac address for your setup
byte ip[] = {192, 168, 2, 2};
byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};

Riva:
Exactly how many Neopixel LED's do you want to control. The example you posted seems pretty much all you need once you have entered the correct values in the required places as it handles multi universes.

const int numLeds = 240; // change for your setup

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

// Change ip and mac address for your setup
byte ip[] = {192, 168, 2, 2};
byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};

Hello,
I want to control 340 LEDs, each led by the 3 channels that have 1020 channels need them. If the universe of 512 channels 1, 2 univers I have I need. How do I make an arrangement.
I'm sorry for my english corrupt
Thank you.

I think I will post some code that outputs one whole universe, rather than use the bloaty neopixel code, my code just allows you to fill an array (WSData[512]), and then call the WS2812() function when it is ready.
It is blocking code (it needs to be), but very fast and code efficient.

Does anyone here know how much Ram the ArtNet library uses ?

I think this line...
leds.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
.. means that there is one array for the incoming data, and another array that holds the neopixel data

Why ?

Why cant you just cream off the universe(s) you need and put them straight into the output array without using a middle-man ?

Am I reading this right or wrong here ? Riva ? AWOL ?

@mcnobby
I know little to nothing about artnet as I still live in the world of serial DMX but reading the notes on the artnet library example posted it seems you simply need to set/check the lines I listed and your good to go.
As to the arrays I don't know what order artnet sends the RGB data in compared to the order the Neopixels need them so guessing that maybe the order needs translating and an Neopixel overall brightness applying.

I want to get started on a multi-universe artnet to WS adaptor very soon
Having read about Artnet and taken some advice I am wondering the following...

Is the number of universes really dictating the amount of ram required ?

  1. Read&Buffer Artnet packet data into an array, eg data[buffer=0][packetsize]

  2. Change buffer to 1

  3. Output data[buffer=0][512ChannelsOnly] directly onto the WS output pin
    (the output pin is related to the universe value that is detailed inside the packet)

  4. Read&Buffer Artnet packet data into an array, eg data[buffer=1][packetsize]

  5. Change buffer to 0

  6. Output data[buffer=1][512ChannelsOnly] directly onto the WS output pin
    (the output pin is related to the universe value that is detailed inside the packet)

  7. go back to 1

So effectively, artnet read will bounce back and forth between buffer0 and buffer1, although there could be more than 2 universes being output (say 8) but still only ever using the same buffers, thus saving ram

Once the data has been output to the WS devices it is not needed anymore
The only downside to this is that sequential universes are output as sequential packets over artNet, so the time between packets may be minimal, and perhaps too short to process the 512 byte "WS Write" (which is about 5ms)

Your idea works okay as long as the length of neopixel strips daisy chained together is no larger than one universe (512 / 3) else you will maybe break the data output chain while waiting for next universe to load and tag on the end. I know you like hitting the metal on AVR but maybe something like this would be better suited to something like the Teensy3.2 with 64K RAM

Riva, I was thinking about putting the universes onto different pin outputs, so I would intentionally end each universe anyway (but good point !)

I have worked out a way of adapting my WS2812 code so I can output 2 streams of WSdata (on separate pins), rather than do one after another, do TWO TOGETHER ! why not ?? The ASM code fits (only just) into an 800KHz bit rate... perhaps that would be a good one to publish once tested

I havent finished getting blood out of the AVR stone yet, once it is dry I will upgrade.. still loads of flexibility to go !

mcnobby:
Riva, I was thinking about putting the universes onto different pin outputs, so I would intentionally end each universe anyway (but good point !)

Then the only potential problem might be visual as LED panels/strings will not update at exactly the same time if your using a ping-pong buffer method.
If your reading 2x universes and outputting at the same time on same/separate pins then SRAM is the potential problem.

Riva:
Then the only potential problem might be visual as LED panels/strings will not update at exactly the same time if your using a ping-pong buffer method.
If your reading 2x universes and outputting at the same time on same/separate pins then SRAM is the potential problem.

Its all a balancing act... but you are quite correct :slight_smile:

I have managed to get 2 universes of WS2812 from a Nano+ENC28J60 ethernet module

Once the artNet/sACN packet has been read in, use the data immediately to write to the WS leds (the buffer data is not needed any more)
Read the next packet in (from the next universe) and once again output the data to the WS (on a different pin to the original packet)

You could add more and more universes writing to different pins each time, without using any more ram !

I stopped at 2 universe as I found the third universe became a bit glitchy and inconsistent

I dont think it is possible to output both universes to the same pin if you have little ram

mcnobby:
You could add more and more universes writing to different pins each time, without using any more ram !

I stopped at 2 universe as I found the third universe became a bit glitchy and inconsistent

I dont think it is possible to output both universes to the same pin if you have little ram

Sorry for last reply have been AFK for a couple of weeks.

Kudos to getting the multi universe going without using extra ram but this makes me wonder what is going wrong when you add 3+ universes as it (theoretically) should all just work the same.

Riva:
Kudos to getting the multi universe going without using extra ram but this makes me wonder what is going wrong when you add 3+ universes as it (theoretically) should all just work the same.

Thanks

I wish I knew, I have tried many things, it could be the limit of the ENC28j60
A real shame, because I could probably get up to 6 universes out @25Hz using this method

I have even tried isolating it and just trying to read the 3rd universe on its own... still glitchy !

Alternatively, it could be my pc/software

A friend says you can have thousands of universes pouring out of Jinx, but maybe for some reason mine is stumbling at the 3rd...

I shall spend more time with it and hopefully find a solution, failing that.. 2 universe isnt too bad to play with, i'm always just that bit more greedy and not content with a minimum.. push to the max I say !!

Cheers Riva

I made some progress

mcnobby:
I made some progress

Looking good, maybe another potential commercial product?

I was thinking about this 3rd universe problem and wonder if the led write routine is not quite quick enough compared to the Ethernet data delivery speed and by the third universe your starting to get some packet loss (hence the flickering). Not sure if the loss would be by the ENC28j60 or the arduino not reading data quick enough from it.

That is a good thought Riva, but I removed everything and just left the processing of Universe 3 packet, it seems that there is either not enough ram/buffer in the ENC to hold more than 2 packets, or the Nano code cannot cope with it all (lack of ram again), I have tried several solutions, like reducing/increasing no of connections, buffer sizes, .flush(), .maintain() etc, but its is always the same.

Third universe appears maybe twice a second, If i add a fourth universe that might appear once a second.. diminishing returns

I wont give up completely on getting more data out
the LED write is probably the least of my problems, 510 byte @ 800khz = approx 1ms

One thing I did find out was that before a LED write is done, you must cli(), otherwise the data is corrupted (I think there is an interrupt in the ethernet library kicking off somewhere.. perhaps I should make the buffer[] volatile ??

Bob

Do you use your own code for accessing the ENC28j60 or one of the pre-built libraries you can get? Maybe the problem would go away with a better library?

I am using UIPEthernet library, it works ok for me. I think there are 3 to choose from (I read somewhere)

With a better understanding of what is going on behind the scenes I might be able to squeeze it a little, but the learning curve would be steep !