Last active
December 21, 2017 11:21
-
-
Save mrrees/d4ab83251ec6f9cd83d8b4f69d8105ec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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: | |
// [url]https://github.com/FastLED/FastLED/releases[/url] | |
// | |
// 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(192, 168, 2, 21); //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 4800 //because it divides by 3 nicely | |
#define NUM_LEDS 1600 // can not go higher than this - Runs out of SRAM | |
#define NUM_LEDS_PER_STRIP 200 | |
#define NUM_STRIPS 8 | |
#define UNIVERSE_COUNT 10 | |
#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[i]; | |
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 == 10){ | |
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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment