#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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
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?