Forráskód Böngészése

added Artnet library

eLandon 4 éve
szülő
commit
fe328e74ea

+ 27 - 0
lib/Artnet-master/.gitignore

@@ -0,0 +1,27 @@
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# Osx
+.DS_Store
+
+# Sublime
+*.sublime-workspace

+ 202 - 0
lib/Artnet-master/Artnet.cpp

@@ -0,0 +1,202 @@
+/*The MIT License (MIT)
+
+Copyright (c) 2014 Nathanaël Lécaudé
+https://github.com/natcl/Artnet, http://forum.pjrc.com/threads/24688-Artnet-to-OctoWS2811
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <Artnet.h>
+
+Artnet::Artnet() {}
+
+void Artnet::begin(byte mac[], byte ip[])
+{
+  #if !defined(ARDUINO_SAMD_ZERO) && !defined(ESP8266) && !defined(ESP32)
+    Ethernet.begin(mac,ip);
+  #endif
+
+  Udp.begin(ART_NET_PORT);
+}
+
+void Artnet::begin()
+{
+  Udp.begin(ART_NET_PORT);
+}
+
+void Artnet::setBroadcastAuto(IPAddress ip, IPAddress sn)
+{
+  //Cast in uint 32 to use bitwise operation of DWORD
+  uint32_t ip32 = ip;
+  uint32_t sn32 = sn;
+
+  //Find the broacast Address
+  uint32_t bc = (ip32 & sn32) | (~sn32);
+
+  //sets the broadcast address
+  setBroadcast(IPAddress(bc));
+}
+
+void Artnet::setBroadcast(byte bc[])
+{
+  //sets the broadcast address
+  broadcast = bc;
+}
+void Artnet::setBroadcast(IPAddress bc)
+{
+  //sets the broadcast address
+  broadcast = bc;
+}
+
+uint16_t Artnet::read()
+{
+  packetSize = Udp.parsePacket();
+
+  remoteIP = Udp.remoteIP();
+  if (packetSize <= MAX_BUFFER_ARTNET && packetSize > 0)
+  {
+      Udp.read(artnetPacket, MAX_BUFFER_ARTNET);
+
+      // Check that packetID is "Art-Net" else ignore
+      for (byte i = 0 ; i < 8 ; i++)
+      {
+        if (artnetPacket[i] != ART_NET_ID[i])
+          return 0;
+      }
+
+      opcode = artnetPacket[8] | artnetPacket[9] << 8;
+
+      if (opcode == ART_DMX)
+      {
+        sequence = artnetPacket[12];
+        incomingUniverse = artnetPacket[14] | artnetPacket[15] << 8;
+        dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8;
+
+        if (artDmxCallback) (*artDmxCallback)(incomingUniverse, dmxDataLength, sequence, artnetPacket + ART_DMX_START, remoteIP);
+        return ART_DMX;
+      }
+      if (opcode == ART_POLL)
+      {
+        //fill the reply struct, and then send it to the network's broadcast address
+        Serial.print("POLL from ");
+        Serial.print(remoteIP);
+        Serial.print(" broadcast addr: ");
+        Serial.println(broadcast);
+
+        #if !defined(ARDUINO_SAMD_ZERO) && !defined(ESP8266) && !defined(ESP32)
+          IPAddress local_ip = Ethernet.localIP();
+        #else
+          IPAddress local_ip = WiFi.localIP();
+        #endif
+        node_ip_address[0] = local_ip[0];
+      	node_ip_address[1] = local_ip[1];
+      	node_ip_address[2] = local_ip[2];
+      	node_ip_address[3] = local_ip[3];
+
+        sprintf((char *)id, "Art-Net");
+        memcpy(ArtPollReply.id, id, sizeof(ArtPollReply.id));
+        memcpy(ArtPollReply.ip, node_ip_address, sizeof(ArtPollReply.ip));
+
+        ArtPollReply.opCode = ART_POLL_REPLY;
+        ArtPollReply.port =  ART_NET_PORT;
+
+        memset(ArtPollReply.goodinput,  0x08, 4);
+        memset(ArtPollReply.goodoutput,  0x80, 4);
+        memset(ArtPollReply.porttypes,  0xc0, 4);
+
+        uint8_t shortname [18];
+        uint8_t longname [64];
+        sprintf((char *)shortname, "artnet arduino");
+        sprintf((char *)longname, "Art-Net -> Arduino Bridge");
+        memcpy(ArtPollReply.shortname, shortname, sizeof(shortname));
+        memcpy(ArtPollReply.longname, longname, sizeof(longname));
+
+        ArtPollReply.etsaman[0] = 0;
+        ArtPollReply.etsaman[1] = 0;
+        ArtPollReply.verH       = 1;
+        ArtPollReply.ver        = 0;
+        ArtPollReply.subH       = 0;
+        ArtPollReply.sub        = 0;
+        ArtPollReply.oemH       = 0;
+        ArtPollReply.oem        = 0xFF;
+        ArtPollReply.ubea       = 0;
+        ArtPollReply.status     = 0xd2;
+        ArtPollReply.swvideo    = 0;
+        ArtPollReply.swmacro    = 0;
+        ArtPollReply.swremote   = 0;
+        ArtPollReply.style      = 0;
+
+        ArtPollReply.numbportsH = 0;
+        ArtPollReply.numbports  = 4;
+        ArtPollReply.status2    = 0x08;
+
+        ArtPollReply.bindip[0] = node_ip_address[0];
+        ArtPollReply.bindip[1] = node_ip_address[1];
+        ArtPollReply.bindip[2] = node_ip_address[2];
+        ArtPollReply.bindip[3] = node_ip_address[3];
+
+        uint8_t swin[4]  = {0x01,0x02,0x03,0x04};
+        uint8_t swout[4] = {0x01,0x02,0x03,0x04};
+        for(uint8_t i = 0; i < 4; i++)
+        {
+            ArtPollReply.swout[i] = swout[i];
+            ArtPollReply.swin[i] = swin[i];
+        }
+        sprintf((char *)ArtPollReply.nodereport, "%i DMX output universes active.", ArtPollReply.numbports);
+        Udp.beginPacket(broadcast, ART_NET_PORT);//send the packet to the broadcast address
+        Udp.write((uint8_t *)&ArtPollReply, sizeof(ArtPollReply));
+        Udp.endPacket();
+
+        return ART_POLL;
+      }
+      if (opcode == ART_SYNC)
+      {
+        if (artSyncCallback) (*artSyncCallback)(remoteIP);
+        return ART_SYNC;
+      }
+  }
+  else
+  {
+    return 0;
+  }
+  return 0;
+}
+
+void Artnet::printPacketHeader()
+{
+  Serial.print("packet size = ");
+  Serial.print(packetSize);
+  Serial.print("\topcode = ");
+  Serial.print(opcode, HEX);
+  Serial.print("\tuniverse number = ");
+  Serial.print(incomingUniverse);
+  Serial.print("\tdata length = ");
+  Serial.print(dmxDataLength);
+  Serial.print("\tsequence n0. = ");
+  Serial.println(sequence);
+}
+
+void Artnet::printPacketContent()
+{
+  for (uint16_t i = ART_DMX_START ; i < dmxDataLength ; i++){
+    Serial.print(artnetPacket[i], DEC);
+    Serial.print("  ");
+  }
+  Serial.println('\n');
+}

+ 173 - 0
lib/Artnet-master/Artnet.h

@@ -0,0 +1,173 @@
+/*The MIT License (MIT)
+
+Copyright (c) 2014 Nathanaël Lécaudé
+https://github.com/natcl/Artnet, http://forum.pjrc.com/threads/24688-Artnet-to-OctoWS2811
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef ARTNET_H
+#define ARTNET_H
+
+#include <Arduino.h>
+
+#if defined(ARDUINO_SAMD_ZERO)
+    #include <WiFi101.h>
+    #include <WiFiUdp.h>
+#elif defined(ESP8266)
+    #include <ESP8266WiFi.h>
+    #include <WiFiUdp.h>
+#elif defined(ESP32)
+    #include <WiFi.h>
+    #include <WiFiUdp.h>
+#else
+    #include <Ethernet.h>
+    #include <EthernetUdp.h>
+#endif
+
+// UDP specific
+#define ART_NET_PORT 6454
+// Opcodes
+#define ART_POLL 0x2000
+#define ART_POLL_REPLY 0x2100
+#define ART_DMX 0x5000
+#define ART_SYNC 0x5200
+// Buffers
+#define MAX_BUFFER_ARTNET 530
+// Packet
+#define ART_NET_ID "Art-Net\0"
+#define ART_DMX_START 18
+
+struct artnet_reply_s {
+  uint8_t  id[8];
+  uint16_t opCode;
+  uint8_t  ip[4];
+  uint16_t port;
+  uint8_t  verH;
+  uint8_t  ver;
+  uint8_t  subH;
+  uint8_t  sub;
+  uint8_t  oemH;
+  uint8_t  oem;
+  uint8_t  ubea;
+  uint8_t  status;
+  uint8_t  etsaman[2];
+  uint8_t  shortname[18];
+  uint8_t  longname[64];
+  uint8_t  nodereport[64];
+  uint8_t  numbportsH;
+  uint8_t  numbports;
+  uint8_t  porttypes[4];//max of 4 ports per node
+  uint8_t  goodinput[4];
+  uint8_t  goodoutput[4];
+  uint8_t  swin[4];
+  uint8_t  swout[4];
+  uint8_t  swvideo;
+  uint8_t  swmacro;
+  uint8_t  swremote;
+  uint8_t  sp1;
+  uint8_t  sp2;
+  uint8_t  sp3;
+  uint8_t  style;
+  uint8_t  mac[6];
+  uint8_t  bindip[4];
+  uint8_t  bindindex;
+  uint8_t  status2;
+  uint8_t  filler[26];
+} __attribute__((packed));
+
+class Artnet
+{
+public:
+  Artnet();
+
+  void begin(byte mac[], byte ip[]);
+  void begin();
+  void setBroadcastAuto(IPAddress ip, IPAddress sn);
+  void setBroadcast(byte bc[]);
+  void setBroadcast(IPAddress bc);
+  uint16_t read();
+  void printPacketHeader();
+  void printPacketContent();
+
+  // Return a pointer to the start of the DMX data
+  inline uint8_t* getDmxFrame(void)
+  {
+    return artnetPacket + ART_DMX_START;
+  }
+
+  inline uint16_t getOpcode(void)
+  {
+    return opcode;
+  }
+
+  inline uint8_t getSequence(void)
+  {
+    return sequence;
+  }
+
+  inline uint16_t getUniverse(void)
+  {
+    return incomingUniverse;
+  }
+
+  inline uint16_t getLength(void)
+  {
+    return dmxDataLength;
+  }
+
+  inline IPAddress getRemoteIP(void)
+  {
+    return remoteIP;
+  }
+
+  inline void setArtDmxCallback(void (*fptr)(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data, IPAddress remoteIP))
+  {
+    artDmxCallback = fptr;
+  }
+
+  inline void setArtSyncCallback(void (*fptr)(IPAddress remoteIP))
+  {
+    artSyncCallback = fptr;
+  }
+
+private:
+  uint8_t  node_ip_address[4];
+  uint8_t  id[8];
+  #if defined(ARDUINO_SAMD_ZERO) || defined(ESP8266) || defined(ESP32)
+    WiFiUDP Udp;
+  #else
+    EthernetUDP Udp;
+  #endif
+  struct artnet_reply_s ArtPollReply;
+
+
+  uint8_t artnetPacket[MAX_BUFFER_ARTNET];
+  uint16_t packetSize;
+  IPAddress broadcast;
+  uint16_t opcode;
+  uint8_t sequence;
+  uint16_t incomingUniverse;
+  uint16_t dmxDataLength;
+  IPAddress remoteIP;
+  void (*artDmxCallback)(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data, IPAddress remoteIP);
+  void (*artSyncCallback)(IPAddress remoteIP);
+};
+
+#endif

+ 9 - 0
lib/Artnet-master/Artnet.sublime-project

@@ -0,0 +1,9 @@
+{
+	"folders":
+	[
+		{
+			"follow_symlinks": true,
+			"path": "."
+		}
+	]
+}

+ 22 - 0
lib/Artnet-master/LICENSE

@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Nathanaël Lécaudé
+https://github.com/natcl/Artnet, http://forum.pjrc.com/threads/24688-Artnet-to-OctoWS2811
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 41 - 0
lib/Artnet-master/README.md

@@ -0,0 +1,41 @@
+# Artnet
+
+An Art-Net library for Teensy and Arduino
+
+Also supports Arduino Zero, ESP8266 and ESP32 based boards
+
+Note: this library assumes you are using the standard Ethernet library
+
+## Installation
+
+You can download the [master](https://github.com/natcl/Artnet/archive/master.zip) and place the folder in your `~/Documents/Arduino/libraries` folder.
+
+## Examples
+
+Different examples are provided, here is a summary of what each example does.
+
+### ArtnetNeoPixel
+
+This example will receive multiple universes via Artnet and control a strip of ws2811 leds via Adafruit's [NeoPixel library](https://github.com/adafruit/Adafruit_NeoPixel).
+
+### ArtnetNeoPixelSD
+
+Same as above but with controls to record and playback sequences from an SD card. To record, send 255 to the first channel of universe 14. To stop, send 0 and to playback send 127.  The limit of leds seems to be around 450 to get 44 fps. The playback routine is not optimzed yet.
+
+### ArtnetOctoWS2811
+
+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).
+
+### ArtnetReceive
+
+This is a basic example that will print out the header and the content of an ArtDmx packet.  This example uses the read() function and the different getter functions to read the data.
+
+### ArtnetReceiveCallback
+
+This is similar to ArtnetReceive but uses a callback to read the data.
+
+## Acknowledgements
+
+Many thanks to virtualdave and [mortonkopf](http://orchardelica.com/wp/artnet-multiple-universe-with-teensy-3-and-octows2811) on the pjrc [forums](http://forum.pjrc.com/threads/24688-Artnet-to-OctoWS2811?highlight=artnet) for the original sketches !
+
+Avec la très aimable participation de Nicolas "Magic" Plourde

+ 201 - 0
lib/Artnet-master/examples/ArduinoZero/ArtnetArduinoZeroNeopixel/ArtnetArduinoZeroNeopixel.ino

@@ -0,0 +1,201 @@
+#include <Artnet.h>
+#include <SPI.h>
+#include <Wire.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+#include <Adafruit_FeatherOLED.h>
+#include <Adafruit_FeatherOLED_WiFi.h>
+#include <Adafruit_NeoPixel.h>
+
+//Neopixels
+
+const int numLeds = 64;
+const int numberOfChannels = numLeds * 3;
+const byte dataPin = 12;
+Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ800);
+
+
+#include <WiFi101.h>
+#include <WiFiUdp.h>
+
+#define VBAT_ENABLED              1
+#define VBAT_PIN                  A7
+#define FEED_VBAT                 "vbat"
+
+int status = WL_IDLE_STATUS;
+char ssid[] = "R&D_wifi"; //  your network SSID (name)
+char pass[] = "erede2K16";    // your network password (use for WPA, or use as key for WEP)
+
+Artnet artnet;
+Adafruit_FeatherOLED_WiFi oled = Adafruit_FeatherOLED_WiFi();
+
+#if (SSD1306_LCDHEIGHT != 32)
+ #error ("Height incorrect, please fix Adafruit_SSD1306.h!");
+#endif
+
+void setup() {
+        Serial.begin(9600);
+        WiFi.setPins(8,7,4,2);
+        leds.begin();
+        initTest();
+
+        Serial.println("OLED FeatherWing test");
+
+        oled.init();
+        oled.clearDisplay();
+
+        pinMode(VBAT_PIN, INPUT);
+        oled.setBatteryIcon(true);
+        updateVbat();
+
+        oled.refreshIcons();
+        oled.clearMsgArea();
+        oled.println("Connecting to ...");
+        oled.println(ssid);
+        // oled.display();
+
+        // while (!Serial) {
+        //         ; // wait for serial port to connect. Needed for native USB port only
+        // }
+
+        // check for the presence of the shield:
+        if (WiFi.status() == WL_NO_SHIELD) {
+                Serial.println("WiFi shield not present");
+                // don't continue:
+                while (true) ;
+        }
+
+        // attempt to connect to Wifi network:
+        while ( status != WL_CONNECTED) {
+                Serial.print("Attempting to connect to SSID: ");
+                Serial.println(ssid);
+                // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
+                status = WiFi.begin(ssid, pass);
+
+                // wait 10 seconds for connection:
+                delay(10000);
+        }
+        Serial.println("Connected to wifi");
+
+        printWifiStatus();
+        artnet.begin();
+        artnet.setArtDmxCallback(onDmxFrame);
+
+        Serial.println("\nStarting connection to server...");
+
+        //Udp.begin(localPort);
+
+        delay(1000);
+}
+
+
+void loop() {
+        artnet.read();
+
+        // if ( VBAT_ENABLED )
+        //   updateVbat();
+
+        //long rssi = WiFi.RSSI();
+        // oled.setRSSI(rssi);
+        // oled.refreshIcons();
+        // oled.display();
+
+}
+
+void printWifiStatus() {
+        // print the SSID of the network you're attached to:
+        Serial.print("SSID: ");
+        Serial.println(WiFi.SSID());
+
+        // print your WiFi shield's IP address:
+        IPAddress ip = WiFi.localIP();
+        Serial.print("IP Address: ");
+        Serial.println(ip);
+
+        // print the received signal strength:
+        long rssi = WiFi.RSSI();
+        Serial.print("signal strength (RSSI):");
+        Serial.print(rssi);
+        Serial.println(" dBm");
+
+        oled.setConnected(true);
+        oled.setRSSI(rssi);
+        oled.setIPAddress(ip);
+        oled.refreshIcons();
+        oled.clearMsgArea();
+        // oled.display();
+}
+
+void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data, IPAddress remoteIP)
+{
+        // print out our data
+        Serial.print("universe number = ");
+        Serial.print(universe);
+        Serial.print("\tdata length = ");
+        Serial.print(length);
+        Serial.print("\tsequence n0. = ");
+        Serial.println(sequence);
+        Serial.print("DMX data: ");
+        for (int i = 0; i < length; i++)
+        {
+                Serial.print(data[i]);
+                Serial.print("  ");
+        }
+        Serial.println();
+        Serial.println();
+
+        for (int i = 0; i < (length / 3); i++)  {
+                leds.setPixelColor(i, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
+        }
+        leds.show();
+
+
+        // oled.clearMsgArea();
+        // oled.print("Universe: ");
+        // oled.println(universe);
+        // for (int i = 0; i < length ; i++) {
+        //   if (i < 5) {
+        //     oled.print(data[i]);
+        //     oled.print(" ");
+        //   }
+        // }
+        // oled.display();
+}
+
+void updateVbat()
+{
+        int vbatADC   = 0;     // The raw ADC value off the voltage div
+        float vbatFloat = 0.0F; // The ADC equivalent in millivolts
+        float vbatLSB   = 0.80566F;// mV per LSB
+
+        // Read the analog in value:
+        vbatADC = analogRead(VBAT_PIN);
+        vbatADC = analogRead(VBAT_PIN);
+
+        // Multiply the ADC by mV per LSB, and then
+        // double the output to compensate for the
+        // 10K+10K voltage divider
+        vbatFloat = ((float)vbatADC * vbatLSB) * 2.0F;
+
+        oled.setBattery(vbatFloat/1000);
+
+}
+
+void initTest()
+{
+        for (int i = 0; i < numLeds; i++)
+                leds.setPixelColor(i, 127, 0, 0);
+        leds.show();
+        delay(500);
+        for (int i = 0; i < numLeds; i++)
+                leds.setPixelColor(i, 0, 127, 0);
+        leds.show();
+        delay(500);
+        for (int i = 0; i < numLeds; i++)
+                leds.setPixelColor(i, 0, 0, 127);
+        leds.show();
+        delay(500);
+        for (int i = 0; i < numLeds; i++)
+                leds.setPixelColor(i, 0, 0, 0);
+        leds.show();
+}

+ 52 - 0
lib/Artnet-master/examples/Basic/ArtnetReceive/ArtnetReceive.ino

@@ -0,0 +1,52 @@
+/*
+This is a basic example that will print out the header and the content of an ArtDmx packet.
+This example uses the read() function and the different getter functions to read the data.
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+*/
+
+#include <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+
+Artnet artnet;
+
+// Change ip and mac address for your setup
+byte ip[] = {10, 0, 1, 199};
+byte broadcast[] = {10, 0, 1, 255};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+
+void setup()
+{
+  Serial.begin(115200);
+  artnet.begin(mac, ip);
+  artnet.setBroadcast(broadcast);
+}
+
+void loop()
+{
+  uint16_t r = artnet.read();
+  if(r == ART_POLL)
+  {
+    Serial.println("POLL");
+  }
+  if (r == ART_DMX)
+  {
+    // print out our data
+    Serial.print("universe number = ");
+    Serial.print(artnet.getUniverse());
+    Serial.print("\tdata length = ");
+    Serial.print(artnet.getLength());
+    Serial.print("\tsequence n0. = ");
+    Serial.println(artnet.getSequence());
+    Serial.print("DMX data: ");
+    for (int i = 0 ; i < artnet.getLength() ; i++)
+    {
+      Serial.print(artnet.getDmxFrame()[i]);
+      Serial.print("  ");
+    }
+    Serial.println();
+    Serial.println();
+  }
+}
+

+ 50 - 0
lib/Artnet-master/examples/Basic/ArtnetReceiveCallback/ArtnetReceiveCallback.ino

@@ -0,0 +1,50 @@
+/*
+This is similar to ArtnetReceive but uses a callback to read the data.
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+*/
+
+#include <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+
+Artnet artnet;
+
+// Change ip and mac address for your setup
+byte ip[] = {192, 168, 2, 2};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+
+void setup()
+{
+  Serial.begin(115200);
+  artnet.begin(mac, ip);
+
+  // 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, IPAddress remoteIP)
+{
+  // print out our data
+  Serial.print("universe number = ");
+  Serial.print(universe);
+  Serial.print("\tdata length = ");
+  Serial.print(length);
+  Serial.print("\tsequence n0. = ");
+  Serial.println(sequence);
+  Serial.print("DMX data: ");
+  for (int i = 0 ; i < length ; i++)
+  {
+    Serial.print(data[i]);
+    Serial.print("  ");
+  }
+  Serial.println();
+  Serial.println();
+
+}

+ 94 - 0
lib/Artnet-master/examples/ESP/ArtnetNeoPixelESPSync/ArtnetNeoPixelESPSync.ino

@@ -0,0 +1,94 @@
+/*
+This example will receive multiple universes via Artnet and control a strip of ws2811 leds via
+Adafruit's NeoPixel library: https://github.com/adafruit/Adafruit_NeoPixel
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+*/
+
+#include <Artnet.h>
+#include <Adafruit_NeoPixel.h>
+
+const char* ssid     = "yourssid";
+const char* password = "yourpassword";
+
+// Neopixel settings
+const int numLeds = 240; // change for your setup
+const int channelsPerLed = 3;
+const int numberOfChannels = numLeds * channelsPerLed; // Total number of channels you want to receive (1 led = 3 channels)
+const byte dataPin = 2;
+Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ800);
+
+// 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 0.
+int previousDataLength = 0;
+
+byte broadcast[] = {10, 0, 1, 255};
+void setup()
+{
+  Serial.begin(115200);
+  WiFi.begin(ssid, password);
+  while (WiFi.status() != WL_CONNECTED) {
+    delay(250);
+    Serial.print(".");
+  }
+  Serial.println("");
+  Serial.print("Connected to ");
+  Serial.println(ssid);
+  Serial.print("IP address: ");
+  Serial.println(WiFi.localIP());
+
+  //Serial.begin(115200);
+  artnet.begin();
+  leds.begin();
+  artnet.setBroadcast(broadcast);
+  initTest();
+
+  // this will be called for each packet received
+  artnet.setArtDmxCallback(onDmxFrame);
+  artnet.setArtSyncCallback(onSync);
+}
+
+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, IPAddress remoteIP)
+{
+  // read universe and put into the right part of the display buffer
+  for (int i = 0; i < length / channelsPerLed; i++)
+  {
+    int led = i + (universe - startUniverse) * (previousDataLength / channelsPerLed);
+    if (led < numLeds) {
+      if (channelsPerLed == 4)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2], data[i * channelsPerLed + 3]);
+      if (channelsPerLed == 3)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2]);
+    }
+  }
+  previousDataLength = length;
+}
+
+void onSync(IPAddress remoteIP) {
+  leds.show();
+}
+
+void initTest()
+{
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 127, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 127, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 127);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 0);
+  leds.show();
+}

+ 52 - 0
lib/Artnet-master/examples/ESP/ArtnetReceiveESP/ArtnetReceiveESP.ino

@@ -0,0 +1,52 @@
+/*
+This is a basic example that will print out the header and the content of an ArtDmx packet.
+This example uses the read() function and the different getter functions to read the data.
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+This works with ESP8266 and ESP32 based boards
+*/
+
+#include <Artnet.h>
+
+const char* ssid     = "yourssid";
+const char* password = "yourpassword";
+
+Artnet artnet;
+
+void setup()
+{
+  Serial.begin(115200);
+  WiFi.begin(ssid, password);
+  while (WiFi.status() != WL_CONNECTED) {
+    delay(250);
+    Serial.print(".");
+  }
+  Serial.println("");
+  Serial.print("Connected to ");
+  Serial.println(ssid);
+  Serial.print("IP address: ");
+  Serial.println(WiFi.localIP());
+
+  artnet.begin();
+}
+
+void loop()
+{
+  if (artnet.read() == ART_DMX)
+  {
+    // print out our data
+    Serial.print("universe number = ");
+    Serial.print(artnet.getUniverse());
+    Serial.print("\tdata length = ");
+    Serial.print(artnet.getLength());
+    Serial.print("\tsequence n0. = ");
+    Serial.println(artnet.getSequence());
+    Serial.print("DMX data: ");
+    for (int i = 0 ; i < artnet.getLength() ; i++)
+    {
+      Serial.print(artnet.getDmxFrame()[i]);
+      Serial.print("  ");
+    }
+    Serial.println();
+    Serial.println();
+  }
+}

+ 114 - 0
lib/Artnet-master/examples/NeoPixel/ArtnetNeoPixel/ArtnetNeoPixel.ino

@@ -0,0 +1,114 @@
+/*
+This example will receive multiple universes via Artnet and control a strip of ws2811 leds via
+Adafruit's NeoPixel library: https://github.com/adafruit/Adafruit_NeoPixel
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+*/
+
+#include <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+#include <Adafruit_NeoPixel.h>
+
+// Neopixel settings
+const int numLeds = 240; // change for your setup
+const int channelsPerLed = 3;
+const int numberOfChannels = numLeds * channelsPerLed; // Total number of channels you want to receive (1 led = 3 channels)
+const byte dataPin = 2;
+Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ800);
+
+// 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 0.
+
+// Check if we got all universes
+const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
+bool universesReceived[maxUniverses];
+bool sendFrame = 1;
+int previousDataLength = 0;
+
+// Change ip and mac address for your setup
+byte ip[] = {10, 0, 1, 199};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+byte broadcast[] = {10, 0, 1, 255};
+void setup()
+{
+  //Serial.begin(115200);
+  artnet.begin(mac, ip);
+  leds.begin();
+  artnet.setBroadcast(broadcast);
+  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, IPAddress remoteIP)
+{
+  sendFrame = 1;
+  // set brightness of the whole strip
+  if (universe == 15)
+  {
+    leds.setBrightness(data[0]);
+    leds.show();
+  }
+
+  // Store which universe has got in
+  if ((universe - startUniverse) < maxUniverses)
+    universesReceived[universe - startUniverse] = 1;
+
+  for (int i = 0 ; i < maxUniverses ; i++)
+  {
+    if (universesReceived[i] == 0)
+    {
+      //Serial.println("Broke");
+      sendFrame = 0;
+      break;
+    }
+  }
+
+  // read universe and put into the right part of the display buffer
+  for (int i = 0; i < length / channelsPerLed; i++)
+  {
+    int led = i + (universe - startUniverse) * (previousDataLength / channelsPerLed);
+    if (led < numLeds) {
+      if (channelsPerLed == 4)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2], data[i * channelsPerLed + 3]);
+      if (channelsPerLed == 3)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2]);
+    }
+  }
+  previousDataLength = length;
+
+  if (sendFrame)
+  {
+    leds.show();
+    // Reset universeReceived to 0
+    memset(universesReceived, 0, maxUniverses);
+  }
+}
+
+void initTest()
+{
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 127, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 127, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 127);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 0);
+  leds.show();
+}

+ 117 - 0
lib/Artnet-master/examples/NeoPixel/ArtnetNeoPixelRGBW/ArtnetNeoPixelRGBW.ino

@@ -0,0 +1,117 @@
+/*
+This example will receive multiple universes via Artnet and control a strip of sk6812RGBW leds via
+Adafruit's NeoPixel library: https://github.com/adafruit/Adafruit_NeoPixel
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+*/
+
+#include <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+#include <Adafruit_NeoPixel.h>
+
+// Neopixel settings
+const int numLeds = 120; // change for your setup
+const int channelsPerLed = 4;
+const int numberOfChannels = numLeds * channelsPerLed; // Total number of channels you want to receive (1 led = 4 channels)
+const byte dataPin = 2;
+Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRBW + NEO_KHZ800);
+
+// 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 0.
+
+// Check if we got all universes
+const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
+bool universesReceived[maxUniverses];
+bool sendFrame = 1;
+int previousDataLength = 0;
+
+// Change ip and mac address for your setup
+byte ip[] = {192, 168, 2, 2};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+
+void setup()
+{
+  //Serial.begin(115200);
+  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, IPAddress remoteIP)
+{
+  sendFrame = 1;
+  // set brightness of the whole strip
+  if (universe == 15)
+  {
+    leds.setBrightness(data[0]);
+    leds.show();
+  }
+
+  // Store which universe has got in
+  if ((universe - startUniverse) < maxUniverses)
+    universesReceived[universe - startUniverse] = 1;
+
+  for (int i = 0 ; i < maxUniverses ; i++)
+  {
+    if (universesReceived[i] == 0)
+    {
+      //Serial.println("Broke");
+      sendFrame = 0;
+      break;
+    }
+  }
+
+  // read universe and put into the right part of the display buffer
+  for (int i = 0; i < length / channelsPerLed; i++)
+  {
+    int led = i + (universe - startUniverse) * (previousDataLength / channelsPerLed);
+    if (led < numLeds) {
+      if (channelsPerLed == 4)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2], data[i * channelsPerLed + 3]);
+      if (channelsPerLed == 3)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2]);
+    }
+  }
+  previousDataLength = length;
+
+  if (sendFrame)
+  {
+    leds.show();
+    // Reset universeReceived to 0
+    memset(universesReceived, 0, maxUniverses);
+  }
+}
+
+void initTest()
+{
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 127, 0, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 127, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 127, 0);
+  leds.show();
+  delay(500);
+    for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 0, 127);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 0, 0);
+  leds.show();
+}

+ 186 - 0
lib/Artnet-master/examples/NeoPixel/ArtnetNeoPixelSD/ArtnetNeoPixelSD.ino

@@ -0,0 +1,186 @@
+/*
+Same as ArtnetNeoPixel.ino but with controls to record and playback sequences from an SD card.
+To record, send 255 to the first channel of universe 14. To stop, send 0 and to playback send 127.
+The limit of leds seems to be around 450 to get 44 fps. The playback routine is not optimzed yet.
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+*/
+
+#include <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+#include <Adafruit_NeoPixel.h>
+#include <SD.h>
+
+// Neopixel settings
+const int numLeds = 200; // change for your setup
+const byte dataPin = 2;
+Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ800);
+
+// 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 = numLeds * 3; // Total number of channels you want to receive (1 led = 3 channels)
+byte channelBuffer[numberOfChannels]; // Combined universes into a single array
+
+// SD card
+File datafile;
+char fileName[] = "data.txt";
+const int chipSelect = 4;
+bool record = 0;
+bool playback = 0;
+
+// Check if we got all universes
+const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
+bool universesReceived[maxUniverses];
+bool sendFrame = 1;
+
+// Change ip and mac address for your setup
+byte ip[] = {192, 168, 2, 2};
+byte broadcast[] = {192, 168, 2, 255};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+
+void setup()
+{
+  Serial.begin(115200);
+  artnet.begin(mac, ip);
+  artnet.setBroadcast(broadcast);
+  leds.begin();
+  initTest();
+
+  if (!SD.begin(chipSelect)) {
+    Serial.println("initialization failed!");
+  }
+  else
+    Serial.println("initialization done.");
+
+  // this will be called for each packet received
+  artnet.setArtDmxCallback(onDmxFrame);
+}
+
+void loop()
+{
+  // we call the read function inside the loop
+  artnet.read();
+  if (playback)
+  {
+    while(datafile.available() && playback)
+    {
+      artnet.read();
+      datafile.read(channelBuffer, numberOfChannels);
+      for (int i = 0; i < numLeds; i++)
+        leds.setPixelColor(i, channelBuffer[(i) * 3], channelBuffer[(i * 3) + 1], channelBuffer[(i * 3) + 2]);
+
+      leds.show();
+      delay(20);
+    }
+    playback = 0;
+    datafile.close();
+  }
+}
+
+void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data, IPAddress remoteIP)
+{
+  sendFrame = 1;
+  // set brightness of the whole strip
+  if (universe == 15)
+  {
+    leds.setBrightness(data[0]);
+    leds.show();
+  }
+
+  if (universe == 14)
+  {
+    // record
+    if (data[0] == 255)
+    {
+      if (SD.exists(fileName))
+      {
+        SD.remove(fileName);
+      }
+      datafile = SD.open(fileName, FILE_WRITE);
+      record = 1;
+      playback = 0;
+    }
+    // play
+    if (data[0] == 127)
+    {
+      record = 0;
+      playback = 1;
+      datafile = SD.open(fileName, FILE_READ);
+    }
+    // stop
+    if (data[0] == 0)
+    {
+      record = 0;
+      playback = 0;
+      datafile.close();
+    }
+  }
+
+  // Store which universe has got in
+  if (universe < maxUniverses)
+    universesReceived[universe] = 1;
+
+  for (int i = 0 ; i < maxUniverses ; i++)
+  {
+    if (universesReceived[i] == 0)
+    {
+      //Serial.println("Broke");
+      sendFrame = 0;
+      break;
+    }
+  }
+
+  if (!playback)
+  {
+    // read universe and put into the right part of the display buffer
+    for (int i = 0 ; i < length ; i++)
+    {
+      int bufferIndex = i + ((universe - startUniverse) * length);
+      if (bufferIndex < numberOfChannels) // to verify
+        channelBuffer[bufferIndex] = byte(data[i]);
+    }
+  }
+
+  if (record && sendFrame)
+  {
+    datafile.write(channelBuffer, numberOfChannels);
+    memset(universesReceived, 0, maxUniverses);
+  }
+
+  if (!playback && !record)
+  {
+    // send to leds
+    for (int i = 0; i < numLeds; i++)
+    {
+      leds.setPixelColor(i, 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 < numLeds ; i++)
+    leds.setPixelColor(i, 127, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 127, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 127);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 0);
+  leds.show();
+}

+ 85 - 0
lib/Artnet-master/examples/NeoPixel/ArtnetNeoPixelSync/ArtnetNeoPixelSync.ino

@@ -0,0 +1,85 @@
+/*
+This example will receive multiple universes via Artnet and control a strip of ws2811 leds via
+Adafruit's NeoPixel library: https://github.com/adafruit/Adafruit_NeoPixel
+This example may be copied under the terms of the MIT license, see the LICENSE file for details
+*/
+
+#include <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+#include <Adafruit_NeoPixel.h>
+
+// Neopixel settings
+const int numLeds = 240; // change for your setup
+const int channelsPerLed = 3;
+const int numberOfChannels = numLeds * channelsPerLed; // Total number of channels you want to receive (1 led = 3 channels)
+const byte dataPin = 2;
+Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ800);
+
+// 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 0.
+int previousDataLength = 0;
+
+// Change ip and mac address for your setup
+byte ip[] = {10, 0, 1, 199};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+byte broadcast[] = {10, 0, 1, 255};
+void setup()
+{
+  //Serial.begin(115200);
+  artnet.begin(mac, ip);
+  leds.begin();
+  artnet.setBroadcast(broadcast);
+  initTest();
+
+  // this will be called for each packet received
+  artnet.setArtDmxCallback(onDmxFrame);
+  artnet.setArtSyncCallback(onSync);
+}
+
+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, IPAddress remoteIP)
+{
+  // read universe and put into the right part of the display buffer
+  for (int i = 0; i < length / channelsPerLed; i++)
+  {
+    int led = i + (universe - startUniverse) * (previousDataLength / channelsPerLed);
+    if (led < numLeds) {
+      if (channelsPerLed == 4)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2], data[i * channelsPerLed + 3]);
+      if (channelsPerLed == 3)
+        leds.setPixelColor(led, data[i * channelsPerLed], data[i * channelsPerLed + 1], data[i * channelsPerLed + 2]);
+    }
+  }
+  previousDataLength = length;
+}
+
+void onSync(IPAddress remoteIP) {
+  leds.show();
+}
+
+void initTest()
+{
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 127, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 127, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 127);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixelColor(i, 0, 0, 0);
+  leds.show();
+}

+ 107 - 0
lib/Artnet-master/examples/OctoWS2811/ArtnetOctoWS2811/ArtnetOctoWS2811.ino

@@ -0,0 +1,107 @@
+/*
+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 <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+#include <OctoWS2811.h>
+
+// OctoWS2811 settings
+const int ledsPerStrip = 240; // change for your setup
+const byte numStrips= 2; // change for your setup
+const int numLeds = ledsPerStrip * numStrips;
+const int numberOfChannels = numLeds * 3; // Total number of channels you want to receive (1 led = 3 channels)
+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 0.
+
+// Check if we got all universes
+const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
+bool universesReceived[maxUniverses];
+bool sendFrame = 1;
+int previousDataLength = 0;
+
+// Change ip and mac address for your setup
+byte ip[] = {192, 168, 2, 2};
+byte broadcast[] = {192, 168, 2, 255};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+
+void setup()
+{
+  //Serial.begin(115200);
+  artnet.setBroadcast(broadcast);
+  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, IPAddress remoteIP)
+{
+  sendFrame = 1;
+
+  // Store which universe has got in
+  if ((universe - startUniverse) < maxUniverses)
+    universesReceived[universe - startUniverse] = 1;
+
+  for (int i = 0 ; i < maxUniverses ; i++)
+  {
+    if (universesReceived[i] == 0)
+    {
+      sendFrame = 0;
+      break;
+    }
+  }
+
+  // read universe and put into the right part of the display buffer
+  for (int i = 0; i < length / 3; i++)
+  {
+    int led = i + (universe - startUniverse) * (previousDataLength / 3);
+    if (led < numLeds)
+      leds.setPixel(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
+  }
+  previousDataLength = length;
+
+  if (sendFrame)
+  {
+    leds.show();
+    // Reset universeReceived to 0
+    memset(universesReceived, 0, maxUniverses);
+  }
+}
+
+void initTest()
+{
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixel(i, 127, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds  ; i++)
+    leds.setPixel(i, 0, 127, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds  ; i++)
+    leds.setPixel(i, 0, 0, 127);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds  ; i++)
+    leds.setPixel(i, 0, 0, 0);
+  leds.show();
+}

+ 85 - 0
lib/Artnet-master/examples/OctoWS2811/ArtnetOctoWS2811Sync/ArtnetOctoWS2811Sync.ino

@@ -0,0 +1,85 @@
+/*
+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 <Artnet.h>
+#include <Ethernet.h>
+#include <EthernetUdp.h>
+#include <SPI.h>
+#include <OctoWS2811.h>
+
+// OctoWS2811 settings
+const int ledsPerStrip = 240; // change for your setup
+const byte numStrips= 2; // change for your setup
+const int numLeds = ledsPerStrip * numStrips;
+const int numberOfChannels = numLeds * 3; // Total number of channels you want to receive (1 led = 3 channels)
+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 0.
+int previousDataLength = 0;
+
+// Change ip and mac address for your setup
+byte ip[] = {192, 168, 2, 2};
+byte broadcast[] = {192, 168, 2, 255};
+byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
+
+void setup()
+{
+  //Serial.begin(115200);
+  artnet.setBroadcast(broadcast);
+  artnet.begin(mac, ip);
+  leds.begin();
+  initTest();
+
+  // this will be called for each packet received
+  artnet.setArtDmxCallback(onDmxFrame);
+  artnet.setArtSyncCallback(onSync);
+}
+
+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, IPAddress remoteIP)
+{
+  // read universe and put into the right part of the display buffer
+  for (int i = 0; i < length / 3; i++)
+  {
+    int led = i + (universe - startUniverse) * (previousDataLength / 3);
+    if (led < numLeds)
+      leds.setPixel(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
+  }
+  previousDataLength = length;
+}
+
+void onSync(IPAddress remoteIP) {
+    leds.show();
+}
+
+void initTest()
+{
+  for (int i = 0 ; i < numLeds ; i++)
+    leds.setPixel(i, 127, 0, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds  ; i++)
+    leds.setPixel(i, 0, 127, 0);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds  ; i++)
+    leds.setPixel(i, 0, 0, 127);
+  leds.show();
+  delay(500);
+  for (int i = 0 ; i < numLeds  ; i++)
+    leds.setPixel(i, 0, 0, 0);
+  leds.show();
+}

+ 16 - 0
lib/Artnet-master/keywords.txt

@@ -0,0 +1,16 @@
+# Datatypes
+
+Artnet	KEYWORD1
+
+# Methods
+
+begin	KEYWORD2
+read	KEYWORD2
+printPacketHeader	KEYWORD2
+printPacketContent	KEYWORD2
+getDmxFrame	KEYWORD2
+getOpcode	KEYWORD2
+getSequence	KEYWORD2
+getUniverse	KEYWORD2
+getLength	KEYWORD2
+setArtDmxCallback	KEYWORD2

+ 26 - 0
lib/Artnet-master/library.json

@@ -0,0 +1,26 @@
+{
+  "name": "Art-Net",
+  "keywords": "artnet, art-net, Ethernet, DMX",
+  "description": "An Art-Net library for Teensy and Arduino",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/natcl/Artnet.git"
+  },
+  "authors":
+  [
+    {
+      "name": "Nathanaël Lécaudé",
+      "maintainer": true
+    }
+  ],
+  "dependencies":
+  {
+    "name": "Ethernet",
+    "authors": "Paul Stoffregen",
+    "frameworks": "arduino"
+  },
+  "version": "1.0.0",
+  "frameworks": "arduino",
+  "platforms": "*"
+}