claudeheintz / LXDMXWiFi_Library

Library for ESP8266 implements Art-Net and sACN with example DMX input/output to/from network
BSD 3-Clause "New" or "Revised" License
74 stars 17 forks source link

Fastled #22

Closed Andreadj closed 3 years ago

Andreadj commented 3 years ago

Hi, I'm using this library with ESP32 and Fastled library. Everything work fine with at maximum 170 led and 1 universe: for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CRGB(ESP32DMX.getSlot(i 3 + 1), ESP32DMX.getSlot(i 3 + 2), ESP32DMX.getSlot(i * 3 + 3)); } FastLED.show();
There's a way to use Fastled with multiple universes, with more than 170 Led?

Thanks

claudeheintz commented 3 years ago

Your limitation is going to be the refresh rate you can achieve with longer strings of LEDs. The best results are probably if you use one board for each universe or perhaps two universes, depending on the data speed of your LEDs. There is an example included with the library (WiFi2Universes) showing receiving two universes that you could modify fairly easily. Basically, the library is designed to allow an external packet buffer that is filled with the UDP.read method. The external data storage allows you to call ->readDMXPacketContents on more than one interface object using the same packet contents. Each sACN interface receives one specific universe. The (WiFi2Universes) example uses two separate interface objects, interface and interfaceUniverse2.

The library does not support sACN synchronization packets. So, you need to decide when to push the data to Fastled (every time the second universe is received?) If you do it anytime either universe changes, you might run into refresh rate issues where the Fastled takes so long to send out the data to the string that the whole thing starts to fall behind...

The issue of how long it takes to completely send the data to a long string with Fastled is a limitation you'll need to solve so receiving/sending does not lag as time goes on. It may be that two universes take too long to send to your LEDs. The maximum rate of sACN should be limited to ~44 packets a second or about 22-25ms per packet. You can calculate the time it takes to send the LED data by multiplying the time it takes to send one byte by 3 times the number of LEDs. The byte/frame time is dependent on the exact serial LEDs you are using and would be found in their datasheet. Quick math tells me that WS2812s at 1.25 microseconds/bit are around 30 microseconds per RGB LED. So by that figure it takes a little over 5 milliseconds to send 170 LEDs worth of data. (5100 microseconds) So you might get several universes out of a single board with relatively fast Neopixels. Slower serial LEDs, maybe not so much. There's processing overhead so I wouldn't count on getting 4 universes of Neopixels at maximum sACN/DMX speed. But that's how you figure it out.

Andreadj commented 3 years ago

Hi Claude, first of all thanks for you fast answer. I'm asking this because i have a strip of 300 led and would like to drive it with only 1 board. I found the Artnet library of rstephan ( https://github.com/rstephan/ArtnetWifi ) and he says his library is able to run 16 universes on 1 node. Well... assuming that the esp32 with Artnet or sACN protocol could be able to manage 4-6 universes with the Fastled library the focal point is how to make it read the instructions of the universes and address them correctly to the LEDs (1-170 for universe 1, 171 -340 for universe 2, etc.). To do this in the library he uses "onDmxFrame" which I report below.

void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data) { sendFrame = 1; // set brightness of the whole strip if (universe == 15) { FastLED.setBrightness(data[0]); FastLED.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 / 3; i++) { int led = i + (universe - startUniverse) (previousDataLength / 3); if (led < numLeds) leds[led] = CRGB(data[i 3], data[i 3 + 1], data[i 3 + 2]); } previousDataLength = length;

if (sendFrame) { FastLED.show(); // Reset universeReceived to 0 memset(universesReceived, 0, maxUniverses); } }

onDmxFrame will execute every time a packet is received by the ESP32 with: "artnet.setArtDmxCallback" The question is: since I would like to use your library it should be possible to insert the data related to your library into "onDmxFrame"? Does this make sense? Would it work for both Artnet and sACN with your "xSemaphoreGive" implementation?

Thanks

Edit: I think there's something useful and similar in "copyDMXToOutput" of "ESP-DMXNeoPixels.ino", am I right?

claudeheintz commented 3 years ago

ESP32DMX is a different library. That library is for DMX and it is limited to one universe in and out.

LXDMXWiFi_Library (this library) is not processor dependent like the serial DMX libraries are. It is for Art-Net or sACN over a network connection. You would use it for two universes like this:

LXDMXWiFi interface; LXDMXWiFi interfaceUniverse2; uint8_t packetBuffer[SACN_BUFFER_MAX];

interface = new LXWiFiSACN(&packetBuffer[0]);
interface->setUniverse(1);
interfaceUniverse2 = new LXWiFiSACN(&packetBuffer[0]);
interfaceUniverse2->setUniverse(2);

`void loop() { uint16_t packetSize = wUDP.parsePacket(); if ( packetSize ) { packetSize = wUDP.read(packetBuffer, SACN_BUFFER_MAX); uint8_t read_result = interface->readDMXPacketContents(&wUDP, packetSize); uint8_t read_result2 = 0;

    if ( read_result == RESULT_DMX_RECEIVED ) {
        for (int i = 0; i < 170; i++) {
            leds[i] = CRGB(interface->getSlot(i * 3 + 1), interface->.getSlot(i * 3 + 2), interface->.getSlot(i * 3 + 3));
        }
    } else if ( read_result == RESULT_NONE ) {// if not good_dmx first universe, try 2nd
        read_result2 = interfaceUniverse2->readDMXPacketContents(&wUDP, packetSize);
        if ( read_result2 == RESULT_DMX_RECEIVED ) {
            for (int i = 0; i < 130; i++) {
                leds[i+170] = CRGB(interfaceUniverse2->getSlot(i * 3 + 1), interfaceUniverse2->.getSlot(i * 3 + 2), interfaceUniverse2->.getSlot(i * 3 + 3));
            }   
        }
    }
    if ( read_result || read_result2 ) {
        FastLED.show();
    }
}

}`

You can look at the WiFi2Universes example for the rest of the setup of the WiFi connection an wUDP object.

(sorry for the life of me I can't get git to format the code sample in this comment)

Andreadj commented 3 years ago

Hi Claude, got it. Thanks