hideakitai / ArtNet

Art-Net Sender/Receiver for Arduino (Ethernet, WiFi)
MIT License
257 stars 52 forks source link

Inconsistent receive with more than 6 universes ESP32 ETH #123

Closed RAK-XTECH closed 2 months ago

RAK-XTECH commented 3 months ago

I'm using an ESP32 WT32-ETH01 V1.4 and compiling using Arduino IDE, this board has the ethernet interface embedded.

Since it's an ESP32 I need to use the ArtnetETH, it can connect without problem and the device gets detected on any light control programs without problem.

Eventually I'll use the data to light up a led strip, but first I wanted to stress test how many universes I could process.

The library works wonders up to 6 universes, but when doing 7 or more the callback for those wasn't being called as often.

So I tried making this code to represent what I'm facing. On this code it shows the frequency that the device receives all the expected universes, so if we expect 6 universes it uses a mask to save which universes we already got callbacks and when it reaches all 6 we calculate the frequency. The mask is set to show up to 12 universes, so when parsing universe index 2 it would show 000000000100, when expecting 6 universes the mask needs to fill to 000000111111 and only then it will calculate the frequency, expecting 12 universes would need to fill all of the mask 111111111111.

#include <ArtnetETH.h>
#include <Arduino.h>

const IPAddress ip(192, 168, 0, 30);
const IPAddress gateway(192, 168, 0, 1);
const IPAddress subnet(255, 255, 255, 0);
ArtnetReceiver artnet;

// Bitmask to track which universes have been received
uint16_t receivedUniversesMask = 0;
const uint8_t numUniverses = 7;
const uint8_t startUniverse = 0;
uint16_t allUniversesMask = ((1 << numUniverses) - 1) << startUniverse;

// Variable to track frequency
unsigned long lastPrintTime = 0;

void setup() {
  Serial.begin(115200);
  delay(500);

  ETH.begin();
  ETH.config(ip, gateway, subnet);

  artnet.begin();
  for (uint16_t i = startUniverse; i < startUniverse + numUniverses; i++) {
    artnet.subscribeArtDmxUniverse(i, callback);
  }
}

void loop() {
  artnet.parse();  // Check for Art-Net packets and process them

  // Check if all universes have been received
  if (receivedUniversesMask == allUniversesMask) {
    unsigned long currentTime = millis();
    unsigned long timeElapsed = currentTime - lastPrintTime;
    lastPrintTime = currentTime;

    // Calculate frequency in Hz and FPS
    float frequencyHz = 1000.0 / timeElapsed;

    // Print the time and frequency
    Serial.print("Time since all universes were received: ");
    Serial.print(timeElapsed);
    Serial.print(" ms, Frequency: ");
    Serial.print(frequencyHz);
    Serial.println(" Hz");

    receivedUniversesMask = 0;  // Reset the bitmask
  }
}

void callback(const uint8_t *data, const uint16_t size, const ArtDmxMetadata &metadata, const ArtNetRemoteInfo &remote) {
  // Update the bitmask to indicate this universe has been received
  receivedUniversesMask |= (1 << metadata.universe);
  printReceivedUniversesMask(metadata.universe, receivedUniversesMask);
}

void printReceivedUniversesMask(uint8_t universe, uint16_t mask) {
  Serial.print("Parsed universe/current mask: ");

  // Print the universe as a bitmask
  for (int i = 11; i >= 0; i--) {  // 12 bits (for 12 universes)
    Serial.print((universe == i) ? '1' : '0');
  }

  Serial.print("/");

  // Loop through each bit in the mask from the most significant to the least significant
  for (int i = 11; i >= 0; i--) {  // 12 bits (for 12 universes)
    Serial.print((receivedUniversesMask & (1 << i)) ? '1' : '0');
  }

  Serial.println();
}

My preferred fixture program uses 25hz as default and when doing 6 universes I get that consistent frequency. Capturar

But when I add the 7th universe I still only get the consistent 6 universes while the 7th one fails to get callbacks. 7 universes 7 universes 2

Going up to 12 universes the problem persists. 12 universes

Changing the starting universe makes no difference, the first 6 universes will update properly, but the 7th forward would get inconsistent callbacks.

I know that the ESP32 is capable of handling more universes, after all there's a lot of chinese artnet interfaces using ESP32 that can handle way more than 6 universes.

Looking at the closed issues list I could see that there might be limitations on the device memory, I don't think this is the case since checking the free heap memory states there's more than 200k available, also the chinese devices corroborate that this doesn't seem to be the problem.

One similar problem was posted by damienrivoal on Nov 13, 2021 but that solution is for the arduino Ethernet library and doesn't apply to the espressif ETH library.

Since I've read people being able to use this library to process more universes I believe that it's indeed a problem with the ETH library and I'll probably post it to espressif github eventually, but decided to report my findings here just in case because this info might be helpful to someone in the future.

hideakitai commented 2 months ago

Thank you for sharing! I've added a log output for raw received bytes before parsing. Now you can see if the cause is

To use the debug output, please call:

artnet.setLogger(&Serial);