Go Down

Topic: ArtNet to WS2812 Pixel LED driver : Using Wemos D1 (arduino-esp8266) (Read 7737 times) previous topic - next topic

mcnobby

This works fine with the current install of the ESP8266 for Arduino libraries
Just set your own router SSID and Password, and run using Jinx software available from http://www.live-leds.de/

This forms the basis of a few projects I am running using multiple universes and browser-based configuration

Code: [Select]

/*
  SmartShow AirPixel ONE - Single Universe ArtNet to WS2812 Driver - For Wemos D1
  You can set the Device IP, and universe number below
  Works perfectly with Jinx LED software
*/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#define WSout 5  // Pin D1
#define WSbit (1<<WSout)

// ARTNET CODES
#define ARTNET_DATA 0x50
#define ARTNET_POLL 0x20
#define ARTNET_POLL_REPLY 0x21
#define ARTNET_PORT 6454
#define ARTNET_HEADER 17

WiFiUDP udp;

uint8_t uniData[514];
uint16_t uniSize;
uint8_t hData[ARTNET_HEADER + 1];
uint8_t net = 0;
uint8_t universe = 0;
uint8_t subnet = 0;

const char* ssid     = "RouterSSID";
const char* password = "RouterPASS";

IPAddress local_ip(192, 168, 1, 200);
IPAddress gateway_ip(192, 168, 1, 1);
IPAddress subnet_ip(255, 255, 255, 0);

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  WiFi.config(local_ip, gateway_ip, subnet_ip);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  udp.begin(ARTNET_PORT); // Open ArtNet port

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  pinMode(WSout, OUTPUT);
}



void ICACHE_FLASH_ATTR sendWS() {
  uint32_t writeBits;
  uint8_t  bitMask, time;
  os_intr_lock();
  for (uint16_t t = 0; t < uniSize; t++) { // outer loop counting bytes
    bitMask = 0x80;
    while (bitMask) {
      // time=0ns : start by setting bit on
      time = 4;
      while (time--) {
        WRITE_PERI_REG( 0x60000304, WSbit );  // do ON bits // T=0
      }
      if ( uniData[t] & bitMask ) {
        writeBits = 0;  // if this is a '1' keep the on time on for longer, so dont write an off bit
      }
      else {
        writeBits = WSbit;  // else it must be a zero, so write the off bit !
      }
      time = 4;
      while (time--) {
        WRITE_PERI_REG( 0x60000308, writeBits );  // do OFF bits // T='0' time 350ns
      }
      time = 6;
      while (time--) {
        WRITE_PERI_REG( 0x60000308, WSbit );  // switch all bits off  T='1' time 700ns
      }
      // end of bite write time=1250ns
      bitMask >>= 1;
    }
  }
  os_intr_unlock();
}

void loop() {
  if (udp.parsePacket()) {
    udp.read(hData, ARTNET_HEADER + 1);
    if ( hData[0] == 'A' && hData[1] == 'r' && hData[2] == 't' && hData[3] == '-' && hData[4] == 'N' && hData[5] == 'e' && hData[6] == 't') {
      if ( hData[8] == 0x00 && hData[9] == ARTNET_DATA && hData[15] == net ) {
        if ( hData[14] == (subnet << 4) + universe ) { // UNIVERSE
          uniSize = (hData[16] << 8) + (hData[17]);
          udp.read(uniData, uniSize);
          //Serial.print("ArtNet packet RX Uni 0 - size:");
          //Serial.println(uniSize);
          sendWS();
        }
      } // if Artnet Data
    }
  }
}
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

mcnobby

I have expanded this to output 16 universes across 4 output pins, enough to drive 2720 WS2812 RGB Pixel LEDs
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

CrossRoads

2720 * 0.6A when all are full on (bright white) = 163A! Hope you have some hefty 5V switching power supplies around.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

mcnobby

2720 * 0.6A when all are full on (bright white) = 163A! Hope you have some hefty 5V switching power supplies around.
I have just bought some !
Although I still dont have that many WS2812s to drive/test, but I cant do this in blocks of 4 universes (680pix)
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

diversyy

Hi,

I just bought a Wemos D1 to drive a 24x16 LED Matrix with WS2812.

The WiFi connection seems to work.

How would the cabling look like? D1 to the LED Pixel, GND to a common ground?

Can I see if the connection between Jinx! and the Wemos D1 has been successfully been established?

Kind regards
diversyy

mcnobby

Hi,
Firstly, 24*16 pixels is 384 Pixels, which is more than one universe, its even more than two !

Yes, D1 is the output to the Pixels, as Data out
Ground is ground and pick the 5v supply up from somewhere else as the Wemos cannot supply 5V, even if you pulled it through the USB it will be far too much current for the USB, the max Pixels I would drive direct from USB is 10 (30 channels = 500ma ish)

Why dont you light another Port/LED when the right IP/ArtNet/Universe is seen from the Wemos ?

Regards
Bob
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

diversyy

Hi,

thank you very much for the response.

I tried to uncomment the following lines in your sketch, since it looked like I could see artnet packets coming in with that:

          //Serial.print("ArtNet packet RX Uni 0 - size:");
          //Serial.println(uniSize);


Today I received the LED stripes and also the 5V power-supplies. I will try to put it together tomorrow.

Regarding the universes I need for the project...could you give me a hint, how I can use multiple universes with your code?

Kind regards
Christian

mcnobby

After the initial filter of the desired universe you can do something like this to pick up universe+1

Code: [Select]
        if ( hData[14] == (subnet << 4) + universe +1 ) { // UNIVERSE
          uniSize2 = (hData[16] << 8) + (hData[17]);
          udp.read(uniData2, uniSize2);
          Serial.print("ArtNet packet RX Uni 1 - size:");
          Serial.println(uniSize2);
          sendWS2();
        }


Notice I have used uniSize2, uniData2 and sendWS2(), these are to save the second universe data and display it. You can either write/adjust a new sendWS2() routine to output the second uni on a separate pin, or work out a way to add the second universe after the first universe on the SAME pin
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

Alfiszcze

Magnificent piece of code :) ... The first one which do not flicker leds. But I'm totally newbie in arduino coding :(
I have put your code in the NodeMcu and it works like charm but my construction have 503 pixels [ 3 artnet universes ] .. can you give me a little helping hand with expanding your code to contain this 3 universes ?

mcnobby

Hi, you need to read the header part, determine what universe has just come in (but not yet read), then assign an array for it to be read into

Code: [Select]
if ( hData[14] == (subnet << 4) + universe ) { // UNIVERSE
          uniSize = (hData[16] << 8) + (hData[17]);
          udp.read(uniData[hData], uniSize);


You will also need to store the universe size so that you know how big each universe is when concatinating them together, I have managed to read and store 16 universes using this method
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

Alfiszcze

As I said before :/ I'm total newbie in arduino and when I paste your code into .ino in place of orginal one this give me error
Code: [Select]
116: error: invalid types 'uint8_t [514] {aka unsigned char [514]}[uint8_t [18] {aka unsigned char [18]}]' for array subscript

           udp.read(uniData[hData], uniSize);

This is the only change in the code
Code: [Select]
udp.read(uniData, uniSize); or am I missing something ?

mcnobby

You would also have to define the variable for uniData differently at the beginning of the code

where it says
Code: [Select]
uint8_t uniData[512];


change the array format to show the number of universes you are wanting to hold

Code: [Select]

uint8_t uniData[NUMBER_OF_UNIVERSES][512];
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

Alfiszcze

Thanx for help but it is too complicated to me :(

in header I put something like this :
Code: [Select]
#define NUMBER_OF_UNIVERSES 4
WiFiUDP udp;

uint8_t uniData[NUMBER_OF_UNIVERSES][514];


then put your code :
Code: [Select]
udp.read(uniData[hData], uniSize);

but getting error message like this:
Code: [Select]
115: error: invalid types 'uint8_t [4][514] {aka unsigned char [4][514]}[uint8_t [18] {aka unsigned char [18]}]' for array subscript

           udp.read(uniData[hData], uniSize);

In the code in start of this topic you put uniData [514] but yesterday you used 512.. tryied both with same error :(

mcnobby

Sorry, my mistake, the line should be

udp.read(uniData[uni], uniSize);
where 'uni' is the decoded universe number from the hData[14] portion of the UDP packet

1. decode the universe from the packet header
2. make sure this is the universe you want
3. use the universe to index the right uniData array for reading the rest of the udp message

http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

TomsDJbike

Hi Bob.

Have you managed to test this with your 16 universes of LEDs? does it manage to not flicker or freeze?

My project has 2016 x Ws2812 LEDs split into three panels.
Im hoping to run this from 3xESP8266 as Artnet receivers (1 per panel) and a single ESP8266 as a WIFI Access point.

Thanks for your good work,
This code seems to work very well and i'm hoping that with my limited knowledge, i can learn how to expand to 4-5 universes per unit and add a web based setup.
Cheers
Tom

Go Up