|
@@ -0,0 +1,199 @@
|
|
|
|
+/*
|
|
|
|
+This example will receive multiple universes via Artnet and control a strip of ws2811 leds via
|
|
|
|
+Paul Stoffregen's excellent OctoWS2811 library: https://www.pjrc.com/teensy/td_libs_OctoWS2811.html
|
|
|
|
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
|
|
|
|
+*/
|
|
|
|
+#include <SPI.h>
|
|
|
|
+#include <Artnet.h>
|
|
|
|
+#include <Ethernet.h>
|
|
|
|
+#include <EthernetUdp.h>
|
|
|
|
+
|
|
|
|
+#include <OctoWS2811.h>
|
|
|
|
+
|
|
|
|
+boolean debug = 0; //activate serial printing, !! waits for a serial input to start loop
|
|
|
|
+
|
|
|
|
+// OctoWS2811 settings
|
|
|
|
+const int ledsPerStrip = 300; // change for your setup
|
|
|
|
+const byte numStrips= 5; // change for your setup
|
|
|
|
+const byte wiredStrips[]={0 ,1 ,2 ,4 ,5};
|
|
|
|
+DMAMEM int displayMemory[ledsPerStrip*6];
|
|
|
|
+int drawingMemory[ledsPerStrip*6];
|
|
|
|
+const int config = WS2811_GRB | WS2811_800kHz;
|
|
|
|
+OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);
|
|
|
|
+
|
|
|
|
+// Artnet settings
|
|
|
|
+Artnet artnet;
|
|
|
|
+const int startUniverse = 0; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as zero.
|
|
|
|
+const int numberOfChannels = ledsPerStrip * numStrips * 3; // Total number of channels you want to receive (1 led = 3 channels)
|
|
|
|
+byte channelBuffer[numberOfChannels]; // Combined universes into a single array
|
|
|
|
+const int DMXmax = 510; // limit number of channels read from each universe (in case the artnet software always sends 512 value)
|
|
|
|
+
|
|
|
|
+// Check if we got all universes
|
|
|
|
+const int maxUniverses = (int) numberOfChannels / DMXmax + ((numberOfChannels % DMXmax) ? 1 : 0);
|
|
|
|
+bool universesReceived[maxUniverses];
|
|
|
|
+bool sendFrame = 1;
|
|
|
|
+
|
|
|
|
+// Change ip and mac address for your setup
|
|
|
|
+boolean autoIP = 0;
|
|
|
|
+byte ip[] = {192, 168, 0, 101};
|
|
|
|
+char mac_string[20];
|
|
|
|
+
|
|
|
|
+//everything on the network needs a unique MAC
|
|
|
|
+#if defined(__MK20DX128__) || defined(__MK20DX256__)
|
|
|
|
+// Teensy 3.x has MAC burned in
|
|
|
|
+static byte mac[6];
|
|
|
|
+void read(uint8_t word, uint8_t *mac, uint8_t offset) {
|
|
|
|
+FTFL_FCCOB0 = 0x41; // Selects the READONCE command
|
|
|
|
+FTFL_FCCOB1 = word; // read the given word of read once area
|
|
|
|
+
|
|
|
|
+// launch command and wait until complete
|
|
|
|
+FTFL_FSTAT = FTFL_FSTAT_CCIF;
|
|
|
|
+while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF));
|
|
|
|
+
|
|
|
|
+*(mac+offset) = FTFL_FCCOB5; // collect only the top three bytes,
|
|
|
|
+*(mac+offset+1) = FTFL_FCCOB6; // in the right orientation (big endian).
|
|
|
|
+*(mac+offset+2) = FTFL_FCCOB7; // Skip FTFL_FCCOB4 as it's always 0.
|
|
|
|
+}
|
|
|
|
+void read_mac() {
|
|
|
|
+read(0xe,mac,0);
|
|
|
|
+read(0xf,mac,3);
|
|
|
|
+}
|
|
|
|
+#else
|
|
|
|
+void read_mac() {}
|
|
|
|
+byte mac[] = {
|
|
|
|
+0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // you can find this written on the board of some Arduino Ethernets or shields
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+void print_mac() {
|
|
|
|
+size_t count = 0;
|
|
|
|
+for(uint8_t i = 0; i < 6; ++i) {
|
|
|
|
+if (i!=0) count += Serial.print(":");
|
|
|
|
+count += Serial.print((*(mac+i) & 0xF0) >> 4, 16);
|
|
|
|
+count += Serial.print(*(mac+i) & 0x0F, 16);
|
|
|
|
+}
|
|
|
|
+sprintf(mac_string, "%02X:%02X:%02X:%02X:%02X:%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
|
|
|
|
+Serial.println();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void setup()
|
|
|
|
+{
|
|
|
|
+ pinMode(9, OUTPUT);
|
|
|
|
+ digitalWrite(9, LOW); // begin reset the WIZ820io
|
|
|
|
+ pinMode(10, OUTPUT);
|
|
|
|
+ digitalWrite(10, HIGH); // de-select WIZ820io
|
|
|
|
+ pinMode(4, OUTPUT);
|
|
|
|
+ digitalWrite(4, HIGH); // de-select the SD Card
|
|
|
|
+ digitalWrite(9, HIGH); // end reset pulse
|
|
|
|
+ Serial.begin(115200);
|
|
|
|
+ artnet.begin(mac, ip);
|
|
|
|
+//if (autoIP){ ip [4]= ( startUniverse == 0 ) ? 1 : startUniverse ;} //
|
|
|
|
+if (autoIP){ ip [3]= (startUniverse + 1);} //avoid ip 0
|
|
|
|
+read_mac();
|
|
|
|
+if (debug){
|
|
|
|
+Serial.begin(115200);
|
|
|
|
+while(!Serial.available()){;} //if debug, wait until you send something to start the sketch
|
|
|
|
+Serial.print("mac : ");
|
|
|
|
+print_mac();
|
|
|
|
+// for (int i ; i<3 ; i++){
|
|
|
|
+// Serial.print(mac[i],HEX);
|
|
|
|
+// Serial.print("-");
|
|
|
|
+// }
|
|
|
|
+// Serial.println(mac[3],HEX);
|
|
|
|
+Serial.print("IP : ");
|
|
|
|
+for (int i ; i<3 ; i++){
|
|
|
|
+Serial.print(ip[i]);
|
|
|
|
+Serial.print(".");
|
|
|
|
+}
|
|
|
|
+Serial.println(ip[3]);
|
|
|
|
+Serial.print(numStrips);
|
|
|
|
+Serial.print(" strips of ");
|
|
|
|
+Serial.print(ledsPerStrip);
|
|
|
|
+Serial.println(" leds");
|
|
|
|
+}
|
|
|
|
+artnet.begin(mac, ip);
|
|
|
|
+leds.begin();
|
|
|
|
+initTest();
|
|
|
|
+
|
|
|
|
+// this will be called for each packet received
|
|
|
|
+artnet.setArtDmxCallback(onDmxFrame);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void loop()
|
|
|
|
+{
|
|
|
|
+// we call the read function inside the loop
|
|
|
|
+artnet.read();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
|
|
|
|
+{
|
|
|
|
+sendFrame = 1;
|
|
|
|
+
|
|
|
|
+// Store which universe has got in
|
|
|
|
+if (universe < maxUniverses)
|
|
|
|
+if (debug){ Serial.print(universe);}
|
|
|
|
+universesReceived[universe] = 1;
|
|
|
|
+
|
|
|
|
+// for (int i = 0 ; i < maxUniverses ; i++)
|
|
|
|
+// {
|
|
|
|
+// if (universesReceived[i] == 0)
|
|
|
|
+// {
|
|
|
|
+// if (debug){Serial.println("Broke");}
|
|
|
|
+// sendFrame = 0;
|
|
|
|
+// break;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+/* ICI length serait à 512 mais devrait etre 510, d'ou décalage de deux valeurs. Il lit les valeurs 511 et 512 (qui sont à 0), la premiere
|
|
|
|
+valeur de l'univers suivant est donc appliquée au channel trois. Verifier, les 2-3 dernieres leds devraient etre éteintes
|
|
|
|
+Tester en forçant length à 510 ?
|
|
|
|
+cf. http://forum.pjrc.com/threads/24688-...toWS2811/page5 post #119
|
|
|
|
+Tester également de ne pas démarrer à l'univers 0 sur la teensy*/
|
|
|
|
+
|
|
|
|
+// read universe and put into the right part of the display buffer
|
|
|
|
+for (int i = 0 ; i < min(length, DMXmax) ; i++)
|
|
|
|
+{
|
|
|
|
+int bufferIndex = i + ((universe - startUniverse) * min(length, DMXmax));
|
|
|
|
+if (bufferIndex < numberOfChannels) // to verify
|
|
|
|
+channelBuffer[bufferIndex] = byte(data[i]);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// send to leds
|
|
|
|
+for (int i = 0; i < ledsPerStrip * numStrips; i++)
|
|
|
|
+{
|
|
|
|
+leds.setPixel(i, channelBuffer[(i) * 3], channelBuffer[(i * 3) + 1], channelBuffer[(i * 3) + 2]);
|
|
|
|
+}
|
|
|
|
+//for (int i = 0; i < numStrips; i++)
|
|
|
|
+//{
|
|
|
|
+// for (int j = 0 ; j < ledsPerStrip ; j++)
|
|
|
|
+// {
|
|
|
|
+// leds.setPixel(wiredStrips[i] * j , channelBuffer[(i) * 3], channelBuffer[(i * 3) + 1], channelBuffer[(i * 3) + 2]);
|
|
|
|
+// }
|
|
|
|
+//}
|
|
|
|
+
|
|
|
|
+if (sendFrame)
|
|
|
|
+{
|
|
|
|
+leds.show();
|
|
|
|
+// Reset universeReceived to 0
|
|
|
|
+memset(universesReceived, 0, maxUniverses);
|
|
|
|
+}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void initTest()
|
|
|
|
+{
|
|
|
|
+for (int i = 0 ; i < ledsPerStrip * numStrips ; i++)
|
|
|
|
+leds.setPixel(i, 127, 0, 0);
|
|
|
|
+leds.show();
|
|
|
|
+delay(500);
|
|
|
|
+for (int i = 0 ; i < ledsPerStrip * numStrips ; i++)
|
|
|
|
+leds.setPixel(i, 0, 127, 0);
|
|
|
|
+leds.show();
|
|
|
|
+delay(500);
|
|
|
|
+for (int i = 0 ; i < ledsPerStrip * numStrips ; i++)
|
|
|
|
+leds.setPixel(i, 0, 0, 127);
|
|
|
|
+leds.show();
|
|
|
|
+delay(500);
|
|
|
|
+for (int i = 0 ; i < ledsPerStrip * numStrips ; i++)
|
|
|
|
+leds.setPixel(i, 0, 0, 0);
|
|
|
|
+leds.show();
|
|
|
|
+}
|