Last active
April 11, 2023 22:13
-
-
Save hsiboy/db54c9bf478c3d667170 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
/* | |
d8888 .d8888b. 888b 888 | |
d88888 d88P Y88b 8888b 888 | |
d88P888 888 888 88888b 888 | |
.d8888b d88P 888 888 888Y88b 888 | |
88K d88P 888 888 888 Y88b888 | |
"Y8888b. d88P 888 888 888 888 Y88888 | |
X88 d8888888888 Y88b d88P 888 Y8888 | |
88888P' d88P 888 "Y8888P" 888 Y888 | |
.d8888b. | |
d88P Y88b | |
888 | |
.d88P | |
.od888P" | |
d88P" | |
888" | |
888888888 | |
888 888 .d8888b. .d8888b. .d8888b. d888 d888 | |
888 o 888 d88P Y88b d88P Y88b d88P Y88b d8888 d8888 | |
888 d8b 888 Y88b. 888 Y88b. d88P 888 888 | |
888 d888b 888 "Y888b. .d88P "Y88888" 888 888 | |
888d88888b888 "Y88b. .od888P" .d8P""Y8b. 888 888 | |
88888P Y88888 "888 d88P" 888 888 888 888 | |
8888P Y8888 Y88b d88P 888" Y88b d88P 888 888 | |
888P Y888 "Y8888P" 888888888 "Y8888P" 8888888 8888888 | |
created January 4th, 2014 by Claude Heintz | |
modified by: Jared Alexander | |
modified by: Stuart Taylor | |
This code is in the public domain. | |
sACN E 1.31 is a public standard published by the PLASA technical standards program | |
http://tsp.plasa.org/tsp/documents/published_docs.php | |
Streaming ACN (sACN) is a standard protocol developed by ESTA to efficiently transport DMX universes over the network. | |
It is comparable to ArtNET in many aspects. One nice thing is the multicast option allowing very easy configuration. | |
sACN is a popular protocol to control large number of RGB LEDs. | |
Requires Arduino Ethernet Shield (Wiznet W5100 W5200 ENC28J60) | |
Modifed to use the lastest version of EthernetUdp library included in Arduino 1.0.5-r2. No need to install other libraries. | |
Receives E1.31 date (sACN) and outputs to WS2811 pixels using FastLED library. | |
Includes timer to run standby program when not receiving data and init program to test pixels each time board boots. | |
*/ | |
// #define DEBUG | |
#ifdef DEBUG | |
#define DEBUG_PRINT(x) Serial.println (x) | |
#else | |
#define DEBUG_PRINT(x) | |
#endif | |
#include <SPI.h> // needed for Arduino versions later than 0018 | |
#include <Ethernet.h> | |
#include <EthernetUdp.h> | |
#include <FastLED.h> | |
#define LED_PIN 6 // physical pin 12 on the chip - PD6 | |
#define LED_TYPE WS2811 | |
#define COLOR_ORDER RGB | |
#define MAX_BRIGHTNESS 128 //Default LED Brightness | |
#define NUM_LEDS 50 //number of pixels | |
CRGB leds[NUM_LEDS]; //pixel array | |
byte current_hue; //hue value for rainbow effect | |
byte ledNumber; //current led Pixel being used for rainbow effect | |
// enter desired universe and subnet (sACN first universe is 1) | |
#define DMX_SUBNET 0 | |
#define DMX_UNIVERSE 1 | |
#define SACN_BUFFER_MAX 640 | |
#define SACN_PORT 5568 | |
const byte channelwidth = 3; //3 channels per pixel | |
byte channel; //channel number for each pixel RGB | |
volatile byte currentcounter = 0; //counter for data reception | |
byte previouscounter = 0; //counter for data reception | |
unsigned long now = 0; //current time value | |
//the initial ip and MAC address will get changed by beginMulti | |
//the multicast ip address should correspond to the desired universe/subnet | |
byte mac[] = {0x90, 0xA2, 0xDA, 0x0F, 0x2A, 0xBC}; //MAC address of ethernet shield | |
IPAddress ip(192, 168, 1, 120); //IP address of ethernet shield | |
IPAddress mip(239, 255, 0, 1); //default multicast IP for E1.31 | |
// buffers for receiving and sending data | |
unsigned char packetBuffer[SACN_BUFFER_MAX]; //buffer to hold incoming packet, | |
// An EthernetUDP instance to let us send and receive packets over UDP | |
EthernetUDP Udp; | |
//setup initializes Ethernet, opens the UDP port and initializes pixels | |
void setup() | |
{ | |
delay(3000); // lets us re-program, by allowing arduino software time to interrupt. | |
FastLED.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); | |
FastLED.setBrightness(MAX_BRIGHTNESS); | |
Ethernet.begin(mac,ip); | |
Udp.begin(SACN_PORT); | |
#ifdef DEBUG | |
Serial.begin(9600); | |
#endif | |
lampTest(); //test to make sure pixels are working | |
} | |
void sacnDMXReceived(unsigned char* pbuff, int count) | |
{ | |
DEBUG_PRINT ("DMX Packet Received"); | |
if ( pbuff[113] == DMX_SUBNET ) | |
{ | |
if ( pbuff[114] == DMX_UNIVERSE ) | |
{ | |
int addressOffset = 125; | |
if ( pbuff[addressOffset] == 0 ) | |
{ //start code must be 0 | |
channel = 1; //reset DMX channel assignment to 1 each time through loop. | |
for (int i = 0; i < NUM_LEDS; i++) //loop to assign 3 channels to each pixel | |
{ | |
leds[i] = CRGB(pbuff[addressOffset + channel], pbuff[addressOffset + (channel +1)], pbuff[addressOffset + (channel +2)]); | |
channel +=channelwidth; //increase last channel number by channel width | |
} | |
} | |
} | |
} | |
FastLED.show(); //send data to pixels | |
} | |
//checks to see if packet is E1.31 data | |
/* | |
int checkACNHeaders(unsigned char* messagein, int messagelength) | |
{ | |
if ( messagein[1] == 0x10 ) | |
{ //header | |
String test = String((char*)&messagein[4]); | |
if ( test.equals("ASC-E1.17") ) | |
{ | |
int rootsizeflags = messagein[16] * 256 + messagein[17]; | |
if ( (0x7000 + messagelength-16) == rootsizeflags ) | |
{ | |
int framingsizeflags = messagein[38] * 256 + messagein[39]; | |
if ( (0x7000 + messagelength-38) == framingsizeflags ) | |
{ | |
int dmpsizeflags = messagein[115] * 256 + messagein[116]; | |
if ( (0x7000 + messagelength-115) == dmpsizeflags ) | |
{ | |
int addresscount = messagein[123] * 256 + messagein[124]; // number of addresses plus start code | |
if ( (messagelength-125) == addresscount ) | |
{ | |
return addresscount; | |
} | |
} | |
} | |
} | |
} | |
} | |
return 0; | |
} | |
*/ | |
int checkACNHeaders(const char* messagein, int messagelength) { | |
if ( messagein[1] == 0x10 && messagein[4] == 0x41 && messagein[12] == 0x37) { | |
// 0x41 = 'A' | |
// 0x37 = '7' | |
int addresscount = messagein[123] * 256 + messagein[124]; // number of values plus start code | |
return addresscount -1; //Return how many values are in the packet. | |
} | |
return 0; | |
} | |
void loop() | |
{ | |
int packetSize = Udp.parsePacket(); //store UPD packet | |
//timer to check if receiving data | |
if(currentcounter != previouscounter) //has the counter changed? | |
{ | |
now = millis(); //store the time since the counter has increased | |
previouscounter = currentcounter; //set the previous value equal to the current value | |
} | |
if((millis() - now) > 5000) //is the time since the counter changed greater than 5 seconds? | |
{ | |
noReceive(); //not receiving data. Run no receive function | |
} | |
if(packetSize) | |
{ | |
Udp.read(packetBuffer,SACN_BUFFER_MAX); //read UDP packet | |
int count = checkACNHeaders(packetBuffer, packetSize); | |
if (count) | |
{ | |
sacnDMXReceived(packetBuffer, count); //process data function | |
currentcounter++; //increase counter by 1 each time through | |
} | |
} | |
} | |
void initTest() //runs at board boot to make sure pixels are working | |
{ | |
FastLED.setBrightness(255); // set to full power | |
FastLED.clear(); // on power up, one or more leds can be in a funky state. | |
DEBUG_PRINT ("Lamp Test:"); | |
ledsSolid(CRGB::Red); | |
FastLED.show(); | |
FastLED.delay(2000); | |
ledsSolid(CRGB::Green); | |
DEBUG_PRINT ("Green"); | |
FastLED.show(); | |
FastLED.delay(2000); | |
ledsSolid(CRGB::Blue); | |
DEBUG_PRINT ("Blue"); | |
FastLED.show(); | |
FastLED.delay(2000); | |
ledsSolid(CRGB::Yellow); | |
DEBUG_PRINT ("Yellow"); | |
FastLED.show(); | |
FastLED.delay(2000); | |
ledsSolid(CRGB::Violet); | |
DEBUG_PRINT ("Violet"); | |
FastLED.show(); | |
FastLED.delay(2000); | |
ledsSolid(CRGB::White); | |
DEBUG_PRINT ("White - Check Power!"); | |
FastLED.show(); | |
FastLED.delay(2000); | |
FastLED.clear(); | |
DEBUG_PRINT ("Rainbows!"); | |
fill_rainbow(leds, NUM_LEDS, CRGB::White); | |
FastLED.show(); | |
FastLED.delay(2000); | |
Serial.println("Show Time..."); | |
FastLED.clear(); | |
FastLED.setBrightness(MAX_BRIGHTNESS); | |
} | |
void noReceive() | |
{ | |
//simple rainbow fill | |
fill_rainbow(leds, NUM_LEDS, CRGB::White); | |
FastLED.show(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment