Skip to content

Instantly share code, notes, and snippets.

@hsiboy
Created January 3, 2018 23:45
Show Gist options
  • Save hsiboy/e25184e42c5b34dd2a61c6b12c2884a6 to your computer and use it in GitHub Desktop.
Save hsiboy/e25184e42c5b34dd2a61c6b12c2884a6 to your computer and use it in GitHub Desktop.
#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
#define DEBUG 1
// Set a unique MAC address for each node.
byte gMac[] = {0x74,0x69,0x69,0x2D,0x30,0x15};
EthernetUDP Udp;
#define ETHERNET_BUFFER 636
#define CHANNEL_COUNT 16320 //because it divides by 3 nicely
#define NUM_LEDS_PER_STRIP 150
#define NUM_STRIPS 8
#define NUM_LEDS NUM_LEDS_PER_STRIP * NUM_STRIPS
#define UNIVERSE_COUNT 32
#define LEDS_PER_UNIVERSE 170 // DMX 512 / 3 = 170-ish
#define BRIGHTNESS 100
CRGB leds[NUM_LEDS];
// Pin layouts on the teensy 3:
// OctoWS2811: 2,14,7,8,6,20,21,5
unsigned char gPacketBuffer[ETHERNET_BUFFER];
int gC = 0;
float gFps = 0;
unsigned long gCurrentMillis = 0;
unsigned long gPreviousMillis = 0;
void setup() {
pinMode(9, OUTPUT);
digitalWrite(9, LOW); // toggle the WIZ820io reset
delay(10);
digitalWrite(9, HIGH);
#ifdef DEBUG
Serial.begin(115200);
delay(10); // let UART settle
#endif
/*
*** WARNING ***
3 big blocks of Memory in use here:
The first is your LEDs array - which is going to be over NUM_LEDS_PER_STRIP * NUM_STRIPS * 3 bytes.
The second is the buffer that octows2811 is writing out of, which is the same size as above.
The third is a buffer that is used to translate/scale the first buffer while octows2811 may still be
writing data out of the second buffer.
The Teensy 3.2 has only 64K to work with.
*/
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP); // block of memory NUM_LEDS_PER_STRIP * 3
LEDS.setBrightness(32);
Ethernet.begin(gMac); // DHCP assigned IP
Udp.begin(5568);
#ifdef DEBUG
Serial.print("DHCP ADDr: ");
Serial.println(Ethernet.localIP());
#endif
lampTest();
}
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
#ifdef DEBUG
Serial.println(b);
#endif
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.
#ifdef DEBUG
Serial.println("*");
#endif
for (int i = 126; i < 126 + count; i = i + 3) {
byte red = pbuff[i];
byte green = pbuff[i + 1];
byte blue = pbuff[i + 2];
leds[ledNumber] = CRGB(red, green, blue);
#ifdef DEBUG
Serial.println(ledNumber);
#endif
ledNumber++;
}
#ifdef DEBUG
Serial.println(unicount);
#endif
if (unicount == UNIVERSE_COUNT) {
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 lampTest() {
FastLED.setBrightness(BRIGHTNESS);
FastLED.clear();
FastLED.show();
for (int i = 0; i < 4; i++) {
const struct CRGB colours[4] = {
CRGB::Red,
CRGB::Green,
CRGB::Blue,
CRGB::White
};
fill_solid(leds, NUM_LEDS, colours[i]);
FastLED.show();
FastLED.delay(400);
}
FastLED.clear();
FastLED.show();
}
void loop() {
//Process packets
int packetSize = Udp.parsePacket(); //Read UDP packet count
if (gC >= 10) {
gC = 0;
}
if (packetSize) {
#ifdef DEBUG
Serial.println(packetSize);
#endif
Udp.read(gPacketBuffer, ETHERNET_BUFFER); //read UDP packet
int count = checkACNHeaders(gPacketBuffer, packetSize);
if (count) {
#ifdef DEBUG
Serial.print("packet size first ");
Serial.println(packetSize);
#endif
gC = gC + 1;
// calculate framerate
gCurrentMillis = millis();
if (gCurrentMillis > gPreviousMillis) {
gFps = 1 / ((gCurrentMillis - gPreviousMillis) * 0.001);
} else {
gFps = 0;
}
gPreviousMillis = gCurrentMillis;
#ifdef DEBUG
if (gFps > 10 && gFps < 500) { // don't show numbers below or over given ammount
Serial.println(gFps);
}
#endif
sacnDMXReceived(gPacketBuffer, count, gC); //process data function
}
}
}
@mrrees
Copy link

mrrees commented Jan 4, 2018

I was able to get 32 universes to run on this code. I took the hard limit (10) and replaced it with UNIVERS_COUNT. So it frames when it sees the any 32 universes. how is this code working now for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment