Skip to content

Instantly share code, notes, and snippets.

@jshaw
Forked from hsiboy/TeensyArtNetE1.31.ino
Created November 5, 2023 17:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jshaw/72cd92e729196f1f9d7a5fc89e31e936 to your computer and use it in GitHub Desktop.
Save jshaw/72cd92e729196f1f9d7a5fc89e31e936 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
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment