E1.31 sACN Ethernet DMX Performance help - 6 Universe Limit improvements?

Hi everybody, hope you´re fine. I just wanne play around with the "Mega Pixel E1.31" software but i can´t get anything out. Just the Test was working but no sACN. I can ping the node. i´m using the teensy 3,2 and the wiz820io with adapter board. Maybe someone has an ideal. thanks.
 
Hi everybody, hope you´re fine. I just wanne play around with the "Mega Pixel E1.31" software but i can´t get anything out. Just the Test was working but no sACN. I can ping the node. i´m using the teensy 3,2 and the wiz820io with adapter board. Maybe someone has an ideal. thanks.

Post your code and I can take a look
 
@crees
it´s your original code. the MegaPixel_E1.31. just the ip was changed.





// E1.31 Receiver and pixel controller by Chris Rees (crees@bearrivernet.net) for the Teensy 3.2 This code was modified from
// Andrew Huxtable base code. (andrew@hux.net.au)
// This code may be freely distributed and used as you see fit for non-profit
// purposes and as long as the original author is credited and it remains open
// source
//
// Please configure your Lighting product to use Unicast to the IP the device is given from your DHCP server
// Multicast is not currently supported at the moment


// You will need the, Teensy utility installed with the added Ethernet One Socket and FastLed Libraries from:
// https://www.pjrc.com/teensy/teensyduino.html
// https://github.com/mrrees/MegaPixel-One-Socket-Ethernet
// https://github.com/FastLED/FastLED/releases
//
// Please note the one socket library may throw errors in compiling. The error was in realation to the chip speed detection and using the
// correct SPI speed.
//
// The Teensy with the Octows2811 and FastLED will allow up to 5440 Pixels (32 Universes) to run. One thing to note is if you desire
// high frame rates your pixel count must not exceed over 680 Pixels per Octo Pin. The reason why is the ammount of time to write out to
// these LED's takes time to shift from one LED to the next. The more LED's per SPI or Octo Pin the more time it takes and the less frame
// rate you will acheive. In the Pixel Controller Wolrd 680 per SPI port is the desired balance. For the Teensy this is a perfect balance
// any more pixels and memory starts to become an issue. Those who whish to push more pixels per port can do so but must sacrifice the
// fastLED and or Octows2811 libraries to free up buffer space.. but your on your own and we welcome you to share your improved methods
// with the community!


// in the code structure there is some serial feedback. Please note enableing serial feedback will interrupt with the pixel performance
// and will slow it down. use only for debugging and omit during production run.

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#define USE_OCTOWS2811
#include<OctoWS2811.h>
#include<FastLED.h>
#include <EEPROM.h>


//*********************************************************************************


// enter desired universe and subnet (sACN first universe is 1)
#define DMX_SUBNET 0
//#define DMX_UNIVERSE 1 //**Start** universe


// Set a different MAC address for each controller IMPORTANT!!!! you can change the last value but make sure its HEX!...
byte mac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x21 };

//DEFINES for at Compile time.
//Leave this alone. At current a full e1.31 frame is 636 bytes..
#define ETHERNET_BUFFER 636 //540 is artnet leave at 636 for e1.31
#define NUM_LEDS_PER_STRIP 240 //170
#define NUM_STRIPS 8


///GLOBALS
int unsigned DMX_UNIVERSE = 1; //**Start** universe 1, 9, 17, 25, 33, 41
int unsigned UNIVERSE_COUNT = 32; //How Many Universes 8, 8, 8, 4, 8, 8
int unsigned UNIVERSE_LAST = 32; // List the last universe typically its sequencially from start but does not have to. 8, 16, 24, 28, 32, 40
int unsigned CHANNEL_COUNT = 510; //max channels per dmx packet
byte unsigned LEDS_PER_UNIVERSE = 170; // Max RGB pixels

//
int unsigned NUM_LEDS = UNIVERSE_COUNT * LEDS_PER_UNIVERSE; // with current fastLED and OctoWs2811 libraries buffers... do not go higher than this - Runs out of SRAM

///



//***********************************************************
// BEGIN Dont Modify unless you know what your doing below
//***********************************************************

// Define the array of leds

CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];

// Pin layouts on the teensy 3:
// OctoWS2811: 2,14,7,8,6,20,21,5


unsigned char packetBuffer[ETHERNET_BUFFER];
int c = 0;
float fps = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

EthernetUDP Udp;

void setup() {

//byte ipadd[4] ; //Variable to store data read from EEPROM.
//unsigned int eeAddress = 39; //EEPROM address to start reading from
//EEPROM.get( eeAddress, ipadd );

//*******************************************************
// ethernet interface ip address
//IPAddress ip(ipadd[0], ipadd[1], ipadd[2], ipadd[3]); //IP address of ethernet shield
IPAddress ip(192, 168, 0, 10); //IP address of ethernet shield

//IPAddress mip(192,168,0,255); //multicast IP
//*******************************************************

// E1.31 is UDP. One socket library will only allow one protocol to be defined.




//WIZNET RESET AND INITIALIZE
pinMode(9, OUTPUT);
digitalWrite(9, LOW); // reset the WIZ820io
delay(10);
digitalWrite(9, HIGH); // reset the WIZ820io

//SD CARD INITIALIZE
//pinMode(10, OUTPUT); // For SD Card Stuff
//digitalWrite(10, HIGH); // de-select WIZ820io
//pinMode(4, OUTPUT); //SD Card Stuff
//digitalWrite(4, HIGH); // de-select the SD Card

//Serial Port Stuff
Serial.begin(115200);
delay(10);


// Using different LEDs or colour order? Change here...
// ********************************************************
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
LEDS.setBrightness(255); //value should be 0-255 Very Bright after 100 default is 50 to save on current and eyes!
// ********************************************************
Serial.println("setup");
//pins 3,4,22 are to the RGB Status LED

// ********************************************************
//Ethernet.init(1); //-> 1 Socket with 16k RX/TX buffer for ethernet3

Ethernet.begin(mac,ip);

//int success = Udp.beginMulticast(mip, 5568);
//Serial.print( "begin, success: " );
//Serial.println( success );

Udp.begin(5568);

//DEFINE AND Turn Framing LED OFF
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
//DEFINE AND TURN STATUS LED ON
pinMode(3, OUTPUT);

digitalWrite(3, LOW);
delay(1000);
//Turn Status LED OFF
digitalWrite(3, HIGH);
// ********************************************************
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
Serial.println(F_BUS);

//Once the Ethernet is initialised, run a test on the LEDs
initTest();
}



static inline void fps2(const int seconds){
// Create static variables so that the code and variables can
// all be declared inside a function
static unsigned long lastMillis;
static unsigned long frameCount;
static unsigned int framesPerSecond;

// It is best if we declare millis() only once
unsigned long now = millis();
frameCount ++;
if (now - lastMillis >= seconds * 1000) {
framesPerSecond = frameCount / seconds;

Serial.print("FPS @ ");
Serial.println(framesPerSecond);
frameCount = 0;
lastMillis = now;
}

}

static inline void pixelrefresh(const int syncrefresh){
// Create static variables so that the code and variables can
// all be declared inside a function
static unsigned long frametimestart;
static unsigned long frametimeend;
static unsigned long frametimechk;
static unsigned long frameonce;
unsigned long now = micros();


//start frame time
frametimestart = now;

//Serial.println(frametimechk)
//If we have framed no need to frame again update time to most recent
if (syncrefresh == 1){
frametimeend = frametimestart;
frameonce = 1;
}

//If we havent framed this will increment via time and at some point will be true,
//if so we need to frame to clear out any buffer and the hold off untill
//we receive our next valid dmx packet. We use the pixel protocol to get a general rule of timing to compare to.

frametimechk = frametimestart - frametimeend;
// num leds time 30us + 300us reset to simulate the time it would take to write out pixels.
//this should help us not loop to fast and risk premature framing and jeopordize ethernet buffer
if (frametimechk >= (NUM_LEDS * 30) + 300){
frametimeend = frametimestart;


if (frameonce == 1){
LEDS.show();
Serial.println ("Partial framing detected");
frameonce = 0;
}

}

}



void sacnDMXReceived(unsigned char* pbuff, int count) {
static unsigned long uniloopcount;
if (count > CHANNEL_COUNT) count = CHANNEL_COUNT;
byte b = pbuff[113]; //DMX Subnet
if ( b == DMX_SUBNET) {
b = pbuff[114]; //DMX Universe
byte s = pbuff[111]; //sequence
static unsigned long ls; // Last Sequence
if (s > ls){
uniloopcount = 0;
ls = s;
}
//turn framing LED OFF
digitalWrite(4, HIGH);
Serial.print("UNI ");
Serial.println(count );
Serial.println(s);
if ( b >= DMX_UNIVERSE && b <= UNIVERSE_LAST) {
Serial.println(b );
if ( pbuff[125] == 0 ) { //start code must be 0
int ledNumber = (b - DMX_UNIVERSE) * LEDS_PER_UNIVERSE;
// sACN packets come in seperate RGB but we have to set each led's RGB value together
// this 'reads ahead' for all 3 colours before moving to the next led.
Serial.println("*");
for (int i = 126;i < 126+count;i = i + 3){
byte charValueR = pbuff;
byte charValueG = pbuff[i+1];
byte charValueB = pbuff[i+2];
leds[ledNumber] = CRGB(charValueR,charValueG,charValueB); //RBG GRB
Serial.println(ledNumber);
ledNumber++;
}







}








}



}

uniloopcount ++;
Serial.print("UNILOOP");
Serial.println(uniloopcount);

//if (b == UNIVERSE_LAST){
if (uniloopcount >= UNIVERSE_COUNT){
//Turn Framing LED ON
digitalWrite(4, LOW);
LEDS.show();
pixelrefresh(1);
uniloopcount = 0;
//Frames Per Second Function fps(every_seconds)
fps2(5);
}

}


int checkACNHeaders(unsigned char* messagein, int messagelength) {
//Do some VERY basic checks to see if it's an E1.31 packet.
//Bytes 4 to 12 of an E1.31 Packet contain "ACN-E1.17"
//Only checking for the A and the 7 in the right places as well as 0x10 as the header.
//Technically this is outside of spec and could cause problems but its enough checks for us
//to determine if the packet should be tossed or used.
//This improves the speed of packet processing as well as reducing the memory overhead.
//On an Isolated network this should never be a problem....
if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) {
int addresscount = (byte) messagein[123] * 256 + (byte) messagein[124]; // number of values plus start code
return addresscount -1; //Return how many values are in the packet.
}
return 0;
}



void initTest() //runs at board boot to make sure pixels are working
{
LEDS.showColor(CRGB(255, 0, 0)); //turn all pixels on red
delay(1000);
LEDS.showColor(CRGB(0, 255, 0)); //turn all pixels on green
delay(1000);
LEDS.showColor(CRGB(0, 0, 255)); //turn all pixels on blue
delay(1000);
LEDS.showColor(CRGB(0, 0, 0)); //turn all pixels off
Serial.println ("TEST");
}

void loop() {
Serial.println("loop");//Process packets
int packetSize = Udp.parsePacket(); //Read UDP packet count

if(packetSize){
Serial.println(packetSize);
Udp.read(packetBuffer,ETHERNET_BUFFER); //read UDP packet


int count = checkACNHeaders(packetBuffer, packetSize);
if (count) {

Serial.print("packet size first ");
Serial.println(packetSize);





sacnDMXReceived(packetBuffer, count); //process data function




}



}

pixelrefresh(0);


}
 
Try


Code:
//DEFINES for at Compile time.
//Leave this alone. At current a full e1.31 frame is 636 bytes..
#define ETHERNET_BUFFER 636 //540 is artnet leave at 636 for e1.31
#define NUM_LEDS_PER_STRIP 240 //170
#define NUM_STRIPS 8


///GLOBALS
int unsigned DMX_UNIVERSE = 1; //**Start** universe 1, 9, 17, 25, 33, 41
int unsigned UNIVERSE_COUNT = 12; //How Many Universes 8, 8, 8, 4, 8, 8
int unsigned UNIVERSE_LAST = 12; // List the last universe typically its sequencially from start but does not have to. 8, 16, 24, 28, 32, 40
int unsigned CHANNEL_COUNT = 510; //max channels per dmx packet
byte unsigned LEDS_PER_UNIVERSE = 170; // Max RGB pixels

Do you get any serial output
 
When you have testpatterns, it means the connection between Teensy and your LEDs are ok. You can ping, then the teensy is running ok. So, I would expect a problem with your software on the PC?

Try with the Scan test software: maybe this makes thins more clear on what happens or not? My first tests with Jinx where also not succesfull. But after some playin around, I figured it out.

da_tester_1060.zip

Good luck
 
that´s the confusing part. I´m using Madrix Ultimate and tested it with another node. That´s worked fine. I also use my scope to look what is happening at the LED-out pins 2,14,...,...,etc but they were just low. so they are just doing the test at the beginning of the scetch. I tri to debug, but it seams that the scetch is only running in the main loop without recieveing any data or don´t try to read it. A test with a webserver from the examples works fine.
greetz TS
 
yes the demo version of madrix 5 doesn´t allow output. but version 3 allows output with some blackouts. i tested again with jinx, i can see traffic on the led pins. but with da tester, same like madrix.
 
Can you try once with lower universe count?

int unsigned UNIVERSE_COUNT = 8; //How Many Universes 8, 8, 8, 4, 8, 8
int unsigned UNIVERSE_LAST = 8; // List the last universe typically its sequencially from start but does not have to. 8, 16, 24, 28, 32, 40
 
Do you get any output from

Code:
Serial.print("UNI ");
Serial.println(count );
Serial.println(s);
if ( b >= DMX_UNIVERSE && b <= UNIVERSE_LAST) {
Serial.println(b );
 
he prints nothing. only the start text. server etc... then he´s in the main loop.very confuzed about it. i also tried to change to artnet, but receiving over 3 unverses the fps collaps and it begins to stutter.
 
Yes very odd you should be seeing serial print data even if it’s an invalid packet. I suspect an error in the code is crashing or there is no packet data. I will post some code here soon for you to test to see if it is any different.
 
hello folks,

i have a project with 8 strip 300 pixel, total for 2400 pixels, i own teensy 3.2 and 3.6 with octows2811 and wiz850io. i already follow the Cree code and library


Hi Guys,

I'm nearly there.
I have a running setup with 22 universes.
But my setup (I have 4 panels of 60 x 15 LEDs) requires 23 universes.
With 22 Universes, my last 40 LEDs are not lit by LINX. (see photograph)

When I change the code to 23 universes, nothing happens anymore: no data to the controller, no display lit at all.
(Last working code with 22 universes attached)

Any ideas?
View attachment 15611

i still have error while compiling with teensyduino.

Code:
C:\Users\Laimena\Documents\Arduino\libraries\FastLED/FastLED.h:14:21: note: #pragma message: FastLED version 3.002.010

 #    pragma message "FastLED version 3.002.010"

                     ^

sacn_coba_11_juli_2019_jam_2018: In function 'void fps2(int)':
sacn_coba_11_juli_2019_jam_2018:178: warning: comparison between signed and unsigned integer expressions 
   if (now - lastMillis >= seconds * 1000) {

                        ^

sacn_coba_11_juli_2019_jam_2018: In function 'void sacnDMXReceived(unsigned char*, int)':
sacn_coba_11_juli_2019_jam_2018:234: warning: comparison between signed and unsigned integer expressions 
   if (count > CHANNEL_COUNT) count = CHANNEL_COUNT;

             ^

perhaps somebody can enlight me with the patching with JINX and i only need 16 universe with this project.
thank you in advance.
 
this is the serial monitor from the code i'm using

Code:
18:03:01.757 -> FPS @ 4
18:03:01.825 -> Partial framing detected
18:03:01.995 -> Partial framing detected
18:03:02.199 -> Partial framing detected
18:03:02.403 -> Partial framing detected
18:03:02.641 -> Partial framing detected
18:03:02.845 -> Partial framing detected
18:03:03.015 -> Partial framing detected
18:03:03.219 -> Partial framing detected
18:03:03.457 -> Partial framing detected
18:03:03.627 -> Partial framing detected
18:03:03.865 -> Partial framing detected
18:03:04.069 -> Partial framing detected
18:03:04.273 -> Partial framing detected
18:03:04.510 -> Partial framing detected
 
Hi make sure your using the one socket library. However since your using w5500 chip you will need to adapt the one socket detect the w5500 chip. Check the github for the original one socket that I forked and see if there is a newer one for proper w5500 detection.

Once you get the proper buffers ans spi speed you should see the increase of universe capacity.
 
thanks for your fast replying. i already using your socket one library. there is no update. the lastest update is your github.
can you pinpoint me which i need to change W5100.h or W5100.ccp
thank you
 
thanks for your fast replying. i already using your socket one library. there is no update. the lastest update is your github.
can you pinpoint me which i need to change W5100.h or W5100.ccp
thank you

I forgot that I did have some test code in post 29 of this thread that might get you what you need.
 
Hello to all of you. First I want to thank you for your great work you have done so far!

To my setup:

I have 2400leds on 8 strips => 300led/strip, teensy 3.2 (120MHz, obverclock), octows2811, sd-card-board and the WIZ850io (W5500) adapter.
I tried Crees code from github (post #5, https://gist.github.com/mrrees/d4ab8...d8b4f69d8105ec) and have the the Ethermet-lib for w5500 from the dropbox (post #29, https://www.dropbox.com/sh/98vhmyne0..._wPg8hHma?dl=0).

I can ping the teensy, but the leds are not working (also not the test-routine, but this worked with other code, so the leds are ok)
I tried "Da-Tester" (unicast with the IP of the teensy): no led respons. but less than 10FPS (probably due to the serial.print stuff?)

Here is the serial-monitor-output:
13:50:21.178 -> W5500 16K_BUFFER_ACTIVE
13:50:21.178 -> server is at 169.254.190.15
13:50:53.216 -> 638
13:50:53.216 -> 638
13:50:53.216 -> 6
13:50:53.216 -> *
13:50:53.216 -> 1
13:50:53.216 -> 638
13:50:53.216 -> 638
13:50:53.216 -> 7
13:50:53.216 -> *
13:50:53.216 -> 2
13:50:53.216 -> 638
13:50:53.216 -> 638
13:50:53.216 -> 8
13:50:53.216 -> *
13:50:53.216 -> 3
13:50:53.216 -> 638
13:50:53.216 -> 638
13:50:53.216 -> 9
13:50:53.216 -> *
13:50:53.216 -> 4

Here it stops.

Here is my code: ( I also tried with 1 universe, 170led, didnt work!)
// E1.31 Receiver code base by Andrew Huxtable (andrew@hux.net.au).Adapted and modified by
// ccr (megapixel.lighting).
//
// This code may be freely distributed and used as you see fit for non-profit
// purposes and as long as the original author is credited and it remains open
// source
//
// Please configure your Lighting product to use Unicast to the IP the device is given from your DHCP server
// Multicast is not currently supported due to bandwidth/processor limitations


// You will need the Ethercard and FastLed Libraries from:
// https://github.com/FastLED/FastLED/releases
//
// The Atmega328 only has 2k of SRAM. This is a severe limitation to being able to control large
// numbers of smart pixels due to the pixel data needing to be stored in an array as well as
// a reserved buffer for receiving Ethernet packets. This code will allow you to use a maximum of 240 pixels
// as that just about maxes out the SRAM on the Atmega328.


// There is deliberately no serial based reporting from the code to conserve SRAM. There is a **little**
// bit available if you need to add some in for debugging but keep it to an absolute minimum for debugging
// only.


#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#define USE_OCTOWS2811
#include<OctoWS2811.h>
#include<FastLED.h>


//*********************************************************************************


// enter desired universe and subnet (sACN first universe is 1)
#define DMX_SUBNET 0
#define DMX_UNIVERSE 1 //**Start** universe


// Set a different MAC address for each...
byte mac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x15 };


// Uncomment if you want to use static IP
//*******************************************************
// ethernet interface ip address
IPAddress ip(169, 254, 190, 15); //IP address of ethernet shield
//*******************************************************


EthernetUDP Udp;


// By sacrificing some of the Ethernet receive buffer, we can allocate more to the LED array
// but this is **technically** slower because 2 packets must be processed for all 240 pixels.


/// DONT CHANGE unless you know the consequences...
#define ETHERNET_BUFFER 636 //540
#define CHANNEL_COUNT 7200 //because it divides by 3 nicely
#define NUM_LEDS 2400 // can not go higher than this - Runs out of SRAM
#define NUM_LEDS_PER_STRIP 170
#define NUM_STRIPS 8
#define UNIVERSE_COUNT 15
#define LEDS_PER_UNIVERSE 170
//#define BRIGHTNESS 100





//********************************************************************************


// Define the array of leds
CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];

// Pin layouts on the teensy 3:
// OctoWS2811: 2,14,7,8,6,20,21,5


unsigned char packetBuffer[ETHERNET_BUFFER];
int c = 0;
float fps = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

void setup() {

pinMode(9, OUTPUT);
digitalWrite(9, LOW); // reset the WIZ820io
delay(10);
digitalWrite(9, HIGH); // reset the WIZ820io
//pinMode(10, OUTPUT);
// digitalWrite(10, HIGH); // de-select WIZ820io
//pinMode(4, OUTPUT);
//digitalWrite(4, HIGH); // de-select the SD Card
Serial.begin(115200);
delay(10);
// Using different LEDs or colour order? Change here...
// ********************************************************
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
LEDS.setBrightness(32);
// ********************************************************



// ********************************************************
Ethernet.begin(mac,ip);
Udp.begin(5568);
// ********************************************************
Serial.print("server is at ");
Serial.println(Ethernet.localIP());

//Once the Ethernet is initialised, run a test on the LEDs
//initTest();
}







void sacnDMXReceived(unsigned char* pbuff, int count, int unicount) {
if (count > CHANNEL_COUNT) count = CHANNEL_COUNT;
byte b = pbuff[113]; //DMX Subnet
if ( b == DMX_SUBNET) {
b = pbuff[114]; //DMX Universe



Serial.println(b );
if ( b >= DMX_UNIVERSE && b <= DMX_UNIVERSE + UNIVERSE_COUNT ) {






if ( pbuff[125] == 0 ) { //start code must be 0
int ledNumber = (b - DMX_UNIVERSE) * LEDS_PER_UNIVERSE;
// sACN packets come in seperate RGB but we have to set each led's RGB value together
// this 'reads ahead' for all 3 colours before moving to the next led.
Serial.println("*");
for (int i = 126;i < 126+count;i = i + 3){
byte charValueR = pbuff;
byte charValueG = pbuff[i+1];
byte charValueB = pbuff[i+2];
leds[ledNumber] = CRGB(charValueR,charValueG,charValueB);
//Serial.println(ledNumber);
ledNumber++;
}





Serial.println(unicount);
if (unicount == 15){

LEDS.show();
}


}



}
}

}


int checkACNHeaders(unsigned char* messagein, int messagelength) {
//Do some VERY basic checks to see if it's an E1.31 packet.
//Bytes 4 to 12 of an E1.31 Packet contain "ACN-E1.17"
//Only checking for the A and the 7 in the right places as well as 0x10 as the header.
//Technically this is outside of spec and could cause problems but its enough checks for us
//to determine if the packet should be tossed or used.
//This improves the speed of packet processing as well as reducing the memory overhead.
//On an Isolated network this should never be a problem....
if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) {
int addresscount = (byte) messagein[123] * 256 + (byte) messagein[124]; // number of values plus start code
return addresscount -1; //Return how many values are in the packet.
}
return 0;
}


void initTest() //runs at board boot to make sure pixels are working
{
LEDS.showColor(CRGB(255, 0, 0)); //turn all pixels on red
delay(1000);
LEDS.showColor(CRGB(0, 255, 0)); //turn all pixels on green
delay(1000);
LEDS.showColor(CRGB(0, 0, 255)); //turn all pixels on blue
delay(1000);
LEDS.showColor(CRGB(0, 0, 0)); //turn all pixels off
}

void loop() {
//Process packets
int packetSize = Udp.parsePacket(); //Read UDP packet count
if (c >= 10){

c = 0;
}
if(packetSize){
Serial.println(packetSize);
Udp.read(packetBuffer,ETHERNET_BUFFER); //read UDP packet


int count = checkACNHeaders(packetBuffer, packetSize);
if (count) {

//Serial.print("packet size first ");
Serial.println(packetSize);

c = c + 1;

// calculate framerate
currentMillis = millis();
if(currentMillis > previousMillis){
fps = 1 / ((currentMillis - previousMillis) * 0.001);
} else {
fps = 0;
}
previousMillis = currentMillis;

if (fps > 10 && fps < 500)// don't show numbers below or over given ammount
Serial.println(fps);

sacnDMXReceived(packetBuffer, count, c); //process data function



}


}


}



EDIT

After deactivating all the serial.print-stuff, the serial monitor output looks like this and doesnt stop. But still no led response!
14:03:41.015 -> W5500 16K_BUFFER_ACTIVE
14:03:41.015 -> server is at 169.254.190.15
14:03:41.015 -> 638
14:03:41.015 -> 638
14:03:41.015 -> 638
14:03:41.015 -> 638
...

Any ideas!?



EDIT 2

When I use the following code, I get the leds-test-patern! The serial output is only:
14:26:30.427 -> W5500 16K_BUFFER_ACTIVE
14:26:38.631 -> server is at 169.254.190.15

Here is the code I used
...
// E1.31 Receiver and pixel controller by Chris Rees (crees@bearrivernet.net) for the Teensy 3.2 This code was modified from
// Andrew Huxtable base code. (andrew@hux.net.au)
// This code may be freely distributed and used as you see fit for non-profit
// purposes and as long as the original author is credited and it remains open
// source
//
// Please configure your Lighting product to use Unicast to the IP the device is given from your DHCP server
// Multicast is not currently supported at the moment


// You will need the, Teensy utility installed with the added Ethernet One Socket and FastLed Libraries from:
// https://www.pjrc.com/teensy/teensyduino.html
// https://github.com/mrrees/MegaPixel-One-Socket-Ethernet
// https://github.com/FastLED/FastLED/releases
//
// Please note the one socket library may throw errors in compiling. The error was in realation to the chip speed detection and using the
// correct SPI speed.
//
// The Teensy with the Octows2811 and FastLED will allow up to 5440 Pixels (32 Universes) to run. One thing to note is if you desire
// high frame rates your pixel count must not exceed over 680 Pixels per Octo Pin. The reason why is the ammount of time to write out to
// these LED's takes time to shift from one LED to the next. The more LED's per SPI or Octo Pin the more time it takes and the less frame
// rate you will acheive. In the Pixel Controller Wolrd 680 per SPI port is the desired balance. For the Teensy this is a perfect balance
// any more pixels and memory starts to become an issue. Those who whish to push more pixels per port can do so but must sacrifice the
// fastLED and or Octows2811 libraries to free up buffer space.. but your on your own and we welcome you to share your improved methods
// with the community!


// in the code structure there is some serial feedback. Please note enableing serial feedback will interrupt with the pixel performance
// and will slow it down. use only for debugging and omit during production run.

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#define USE_OCTOWS2811
#include<OctoWS2811.h>
#include<FastLED.h>
#include <EEPROM.h>


//*********************************************************************************


// enter desired universe and subnet (sACN first universe is 1)
#define DMX_SUBNET 0
//#define DMX_UNIVERSE 1 //**Start** universe


// Set a different MAC address for each controller IMPORTANT!!!! you can change the last value but make sure its HEX!...
byte mac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x21 };

//DEFINES for at Compile time.
//Leave this alone. At current a full e1.31 frame is 636 bytes..
#define ETHERNET_BUFFER 636 //540 is artnet leave at 636 for e1.31
#define NUM_LEDS_PER_STRIP 300 //170
#define NUM_STRIPS 8


///GLOBALS
int unsigned DMX_UNIVERSE = 1; //**Start** universe 1, 9, 17, 25, 33, 41
int unsigned UNIVERSE_COUNT = 15; //How Many Universes 8, 8, 8, 4, 8, 8
int unsigned UNIVERSE_LAST = 15; // List the last universe typically its sequencially from start but does not have to. 8, 16, 24, 28, 32, 40
int unsigned CHANNEL_COUNT = 510; //max channels per dmx packet
byte unsigned LEDS_PER_UNIVERSE = 170; // Max RGB pixels

//
int unsigned NUM_LEDS = UNIVERSE_COUNT * LEDS_PER_UNIVERSE; // with current fastLED and OctoWs2811 libraries buffers... do not go higher than this - Runs out of SRAM

///



//***********************************************************
// BEGIN Dont Modify unless you know what your doing below
//***********************************************************

// Define the array of leds

CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];

// Pin layouts on the teensy 3:
// OctoWS2811: 2,14,7,8,6,20,21,5


unsigned char packetBuffer[ETHERNET_BUFFER];
int c = 0;
float fps = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

EthernetUDP Udp;

void setup() {

//byte ipadd[4] ; //Variable to store data read from EEPROM.
//unsigned int eeAddress = 39; //EEPROM address to start reading from
//EEPROM.get( eeAddress, ipadd );

//*******************************************************
// ethernet interface ip address
//IPAddress ip(ipadd[0], ipadd[1], ipadd[2], ipadd[3]); //IP address of ethernet shield
IPAddress ip(169, 254, 190, 15); //IP address of ethernet shield

//IPAddress mip(239,255,0,1); //multicast IP
//*******************************************************

// E1.31 is UDP. One socket library will only allow one protocol to be defined.




//WIZNET RESET AND INITIALIZE
pinMode(9, OUTPUT);
digitalWrite(9, LOW); // reset the WIZ820io
delay(10);
digitalWrite(9, HIGH); // reset the WIZ820io

//SD CARD INITIALIZE
//pinMode(10, OUTPUT); // For SD Card Stuff
//digitalWrite(10, HIGH); // de-select WIZ820io
//pinMode(4, OUTPUT); //SD Card Stuff
//digitalWrite(4, HIGH); // de-select the SD Card

//Serial Port Stuff
Serial.begin(115200);
delay(10);


// Using different LEDs or colour order? Change here...
// ********************************************************
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
LEDS.setBrightness(50); //value should be 0-255 Very Bright after 100 default is 50 to save on current and eyes!
// ********************************************************

//pins 3,4,22 are to the RGB Status LED

// ********************************************************
//Ethernet.init(1); //-> 1 Socket with 16k RX/TX buffer for ethernet3

Ethernet.begin(mac,ip);

//int success = Udp.beginMulticast(mip, 5568);
//Serial.print( "begin, success: " );
//Serial.println( success );

Udp.begin(5568);

//DEFINE AND Turn Framing LED OFF
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
//DEFINE AND TURN STATUS LED ON
pinMode(3, OUTPUT);

digitalWrite(3, LOW);
delay(9000);
//Turn Status LED OFF
digitalWrite(3, HIGH);
// ********************************************************
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
//Serial.println(F_BUS);

//Once the Ethernet is initialised, run a test on the LEDs
initTest();
}



static inline void fps2(const int seconds){
// Create static variables so that the code and variables can
// all be declared inside a function
static unsigned long lastMillis;
static unsigned long frameCount;
static unsigned int framesPerSecond;

// It is best if we declare millis() only once
unsigned long now = millis();
frameCount ++;
if (now - lastMillis >= seconds * 1000) {
framesPerSecond = frameCount / seconds;

Serial.print("FPS @ ");
Serial.println(framesPerSecond);
frameCount = 0;
lastMillis = now;
}

}

static inline void pixelrefresh(const int syncrefresh){
// Create static variables so that the code and variables can
// all be declared inside a function
static unsigned long frametimestart;
static unsigned long frametimeend;
static unsigned long frametimechk;
static unsigned long frameonce;
unsigned long now = micros();


//start frame time
frametimestart = now;

//Serial.println(frametimechk)
//If we have framed no need to frame again update time to most recent
if (syncrefresh == 1){
frametimeend = frametimestart;
frameonce = 1;
}

//If we havent framed this will increment via time and at some point will be true,
//if so we need to frame to clear out any buffer and the hold off untill
//we receive our next valid dmx packet. We use the pixel protocol to get a general rule of timing to compare to.

frametimechk = frametimestart - frametimeend;
// num leds time 30us + 300us reset to simulate the time it would take to write out pixels.
//this should help us not loop to fast and risk premature framing and jeopordize ethernet buffer
if (frametimechk >= (NUM_LEDS * 30) + 300){
frametimeend = frametimestart;


if (frameonce == 1){
LEDS.show();
Serial.println ("Partial framing detected");
frameonce = 0;
}

}

}



void sacnDMXReceived(unsigned char* pbuff, int count) {
static unsigned long uniloopcount;
if (count > CHANNEL_COUNT) count = CHANNEL_COUNT;
byte b = pbuff[113]; //DMX Subnet
if ( b == DMX_SUBNET) {
b = pbuff[114]; //DMX Universe
byte s = pbuff[111]; //sequence
static unsigned long ls; // Last Sequence
if (s > ls){
uniloopcount = 0;
ls = s;
}
//turn framing LED OFF
digitalWrite(4, HIGH);
//Serial.print("UNI ");
//Serial.println(count );
//Serial.println(s);
if ( b >= DMX_UNIVERSE && b <= UNIVERSE_LAST) {
//Serial.println(b );
if ( pbuff[125] == 0 ) { //start code must be 0
int ledNumber = (b - DMX_UNIVERSE) * LEDS_PER_UNIVERSE;
// sACN packets come in seperate RGB but we have to set each led's RGB value together
// this 'reads ahead' for all 3 colours before moving to the next led.
//Serial.println("*");
for (int i = 126;i < 126+count;i = i + 3){
byte charValueR = pbuff;
byte charValueG = pbuff[i+1];
byte charValueB = pbuff[i+2];
leds[ledNumber] = CRGB(charValueR,charValueG,charValueB); //RBG GRB
//Serial.println(ledNumber);
ledNumber++;
}







}








}



}

uniloopcount ++;
//Serial.print("UNILOOP");
//Serial.println(uniloopcount);

//if (b == UNIVERSE_LAST){
if (uniloopcount >= UNIVERSE_COUNT){
//Turn Framing LED ON
digitalWrite(4, LOW);
LEDS.show();
pixelrefresh(1);
uniloopcount = 0;
//Frames Per Second Function fps(every_seconds)
fps2(5);
}

}


int checkACNHeaders(unsigned char* messagein, int messagelength) {
//Do some VERY basic checks to see if it's an E1.31 packet.
//Bytes 4 to 12 of an E1.31 Packet contain "ACN-E1.17"
//Only checking for the A and the 7 in the right places as well as 0x10 as the header.
//Technically this is outside of spec and could cause problems but its enough checks for us
//to determine if the packet should be tossed or used.
//This improves the speed of packet processing as well as reducing the memory overhead.
//On an Isolated network this should never be a problem....
if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) {
int addresscount = (byte) messagein[123] * 256 + (byte) messagein[124]; // number of values plus start code
return addresscount -1; //Return how many values are in the packet.
}
return 0;
}



void initTest() //runs at board boot to make sure pixels are working
{
LEDS.showColor(CRGB(255, 0, 0)); //turn all pixels on red
delay(1000);
LEDS.showColor(CRGB(0, 255, 0)); //turn all pixels on green
delay(1000);
LEDS.showColor(CRGB(0, 0, 255)); //turn all pixels on blue
delay(1000);
LEDS.showColor(CRGB(0, 0, 0)); //turn all pixels off
}

void loop() {
//Process packets
int packetSize = Udp.parsePacket(); //Read UDP packet count

if(packetSize){
//Serial.println(packetSize);
Udp.read(packetBuffer,ETHERNET_BUFFER); //read UDP packet


int count = checkACNHeaders(packetBuffer, packetSize);
if (count) {

//Serial.print("packet size first ");
//Serial.println(packetSize);





sacnDMXReceived(packetBuffer, count); //process data function




}



}

pixelrefresh(0);


}
 
Last edited:
Hi! Ok looks like your getting buffer info! thats good! Looking at your setup the way we need to think of this is budgeting the correct pixel per port settings. since you are using 300 pixels we need to use the correct universe budget. To make sure the buffers are setup correctly we need to use and define 16 universes. sACN uses start universe 1 (not 0 like artnet)

Next troubleshooting step is to place a serial output on the buffer validation where it detects if its sACN or not. By doing this you verifying that the sacn portion is being detected. Onced verfied the buffer needs to be placed in the correct location of the pixel buffer so it can be written out (LEDshow). in the sloppy code I check the values of the array to validate that the universe fits the criteria (range that I expect). What I mean by sloppy is that I used a lazy count method or a last universe detect method to fire the LED's. Interestingly Using Jinx to send the LED data is that its very good at sending all universes. This is great because it was a reliable way to rely on in code when to send the LEDshow command. However using this code for GrandMA or other high end DMX consoles they seem to only send changed universe data so that makes it more difficult to know when to send the LED show command without compromising the incoming buffer (another discussion for another day).

Once you validate that your detecting the universe data and that its making it to the LED buffer code (getting inserted into the array) then you should be able to see if the Last universe or universe count is being satisfied and allowing the LEDshow to happen.

Hope this helps. The best part of this code is teaching how to process packets and place the data into LED buffers to be sent out.
 
Hi! Ok looks like your getting buffer info! thats good! Looking at your setup the way we need to think of this is budgeting the correct pixel per port settings. since you are using 300 pixels we need to use the correct universe budget. To make sure the buffers are setup correctly we need to use and define 16 universes. sACN uses start universe 1 (not 0 like artnet)

Next troubleshooting step is to place a serial output on the buffer validation where it detects if its sACN or not. By doing this you verifying that the sacn portion is being detected. Onced verfied the buffer needs to be placed in the correct location of the pixel buffer so it can be written out (LEDshow). in the sloppy code I check the values of the array to validate that the universe fits the criteria (range that I expect). What I mean by sloppy is that I used a lazy count method or a last universe detect method to fire the LED's. Interestingly Using Jinx to send the LED data is that its very good at sending all universes. This is great because it was a reliable way to rely on in code when to send the LEDshow command. However using this code for GrandMA or other high end DMX consoles they seem to only send changed universe data so that makes it more difficult to know when to send the LED show command without compromising the incoming buffer (another discussion for another day).

Once you validate that your detecting the universe data and that its making it to the LED buffer code (getting inserted into the array) then you should be able to see if the Last universe or universe count is being satisfied and allowing the LEDshow to happen.

Hope this helps. The best part of this code is teaching how to process packets and place the data into LED buffers to be sent out.

Hello Crees,
thank you for your fast reply. Unfortunately I´m not a software engenieer or IT-person, therefor I would need a little bit more guidance.

Ok 16 universes makes sence, so i get 2 universes per stripe without switching one universe to the next strip, right?

Would be great if you could help ma bit further.
 
FYI: crees project is closed and no longer supports his megapixel octoluminair product.

yes and no. Do to reasons I had to take down my pcb board and DIY kits, however the github code and forum posts and occasional help is still there. If your good with combining wiznet schematics to teensy and the octows2811 your pretty much the same level as where I left the project.
 
Last edited:
Back
Top