hideakitai / ArtNet

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

Use with ENC28J60 ethernet shield? #22

Closed niallfleming closed 3 years ago

niallfleming commented 3 years ago

Is it possible to swap out the Ethernet library used?

UIPEthernet works with the ENC28J60 chip, but the standard Ethernet lib does not.

Not sure if I'm being stupid or there's a way to override it?

hideakitai commented 3 years ago

@niallfleming Hi, though it's not supported, maybe you can use it if UIPEthernet is compatible with the standard Ethernet library. Please try to replace Artnet artnet; with the following.

#include <Artnet.h>

// define your artnet manager with Eth
using ArtnetUIP = arx::artnet::Manager<UIPUDP>;
ArtnetUIP artnet;

// ...
niallfleming commented 3 years ago

@hideakitai Thanks for that. Seems like it is still trying to load the normal library as well as I get duplicated class errors. Not sure if there's a way to avoid that.

I can get round it by commenting the Includes for Ethernet.h and EthernetUdp.h in ArtnetEther.h, and defining ESP8266 in order to avoid it attempting to call Ethernet.MACAddress(mac); in ArtnetCommon.

Which gets me to the point where it compiles, but then complains that it's using 135% of global variables (i'm using a nano clone), which I don't think is coming from my sketch, it has to be mainly from the includes I guess, probably the UIPEthernet lib.

hideakitai commented 3 years ago

@niallfleming You can reduce the size of the library if you only need either receiving or sending the artnet.

#include <Artnet.h>

using ArtnetSenderUIP = arx::artnet::Sender<UIPUDP>;
using ArtnetReceiverUIP = arx::artnet::Receiver<UIPUDP>;

ArtnetReceiverUIP artnet;
// OR
ArtnetSenderUIP artnet;
niallfleming commented 3 years ago

I've managed to get a lot further with this. It turns out that someone had done the work to make the UIPEthernet library more compatible with Ethernet - EthernetENC - and it seems a little smaller. So now it's compiling and uploading and pingable - it seems like the example MAC address listed in examples/Ethernet/receive_fastled. But I'm not seeing it as a node in MagicQ.

MagicQ is using broadcast by default for discovery, is that what this library expects and listens on? Is there somewhere I can add a judicious serial.println to check the broadcast it has computed.

I see the subscribe_net and subscribe_subnet can be passed to begin(), but I am not sure what these relate to by the name given and the expected values Net must be < 128, Subnet < 16.

I'm only testing (eventually) with 5 LEDS, so I've used an IP in the local subnet which is a /24 (255.255.255.0), so I expect packets on the broadcast address 192.168.0.255, which I do see coming from MagicQ:

21:03:58.645985 IP (tos 0x0, ttl 64, id 7015, offset 0, flags [none], proto UDP (17), length 558) 192.168.0.101.6454 > 192.168.0.255.6454: [udp sum ok] UDP, length 530 21:03:59.066090 IP (tos 0x0, ttl 64, id 52887, offset 0, flags [none], proto UDP (17), length 42) 192.168.0.101.6454 > 192.168.0.255.6454: [udp sum ok] UDP, length 14

niallfleming commented 3 years ago

OK so I read the documentation on art-net.org.uk and I understand that net/subnet refer to artnet universe addressing. So the default of universe 0, net 0, subnet 0 should relate to Art-0 as configured in MagicQ.

Here's my current sketch:

#include <EthernetENC.h>
#include <FastLED.h>  // include FastLED *before* Artnet
#include <ArtnetEther.h>

// Ethernet stuff
const IPAddress ip(192, 168, 0, 115);
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x78, 0xEE };

ArtnetReceiver artnet;
uint8_t universe = 0;  // 0 - 15

// FastLED
#define NUM_LEDS 5
CRGB leds[NUM_LEDS];
const uint8_t PIN_LED_DATA = 3;

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

    FastLED.addLeds<NEOPIXEL, PIN_LED_DATA>(leds, NUM_LEDS);

    Ethernet.begin(mac, ip);
    Serial.println(Ethernet.localIP());
    Serial.println(Ethernet.subnetMask());
    Serial.println(universe);
    artnet.begin();
    //artnet.subscribe_net(0);     // optionally you can change
    //artnet.subscribe_subnet(0);  // optionally you can change

    // if Artnet packet comes to this universe, forward them to fastled directly
    //artnet.forward(universe, leds, NUM_LEDS);

    artnet.subscribe(universe, [&](const uint8_t* data, const uint16_t size) {
        Serial.print("artnet data (universe : ");
        Serial.print(universe);
        Serial.print(", size = ");
        Serial.print(size);
        Serial.print(") :");
        for (size_t i = 0; i < size; ++i) {
            Serial.print(data[i]);
            Serial.print(",");
        }
        Serial.println();
    });

    // if Artnet packet comes, this function is called to every universe
    artnet.subscribe([&](const uint32_t univ, const uint8_t* data, const uint16_t size) {
        Serial.print("ArtNet data has come to universe: ");
        Serial.println(univ);
    });
}

void loop() {
    artnet.parse();  // check if artnet packet has come and execute callback
    //FastLED.show();
}

I've commented out FastLED temporarily so I could serial log any received packets.

hideakitai commented 3 years ago

@niallfleming You can set net and subnet by using artnet.begin(net, subnet). After that, please subscribe 4-bit universe with artnet.subscribe(universe, callback).

Please check here if the packet has come. And if the ArtPoll packet has come, this block will be executed.

niallfleming commented 3 years ago

Hi

I've got so much further! I've got it receiving on local broadcast at last, with some help from the current maintainer of EthernetENC, it turns out that it was filtering out everything but ARP... for some reason.

So now the board is receiving the ArtPoll 0x2000, and it definitely enters the poll_reply method but somewhere between the top and bottom of that method it's getting stuck, I've got a Serial.println just prior to static const IPAddress local_broadcast_addr

There's 214 bytes left for global vars, could that be an issue?

hideakitai commented 3 years ago

@niallfleming The struct ArtPollReply requires 239 bytes so maybe it is because of the memory shortage. Are you using the Artnet class? If you still using Artnet (integrated sender and receiver) and no need to send Artnet packets, please try to use ArtnetReceiver.

@niallfleming You can reduce the size of the library if you only need either receiving or sending the artnet.

#include <Artnet.h>

using ArtnetSenderUIP = arx::artnet::Sender<UIPUDP>;
using ArtnetReceiverUIP = arx::artnet::Receiver<UIPUDP>;

ArtnetReceiverUIP artnet;
// OR
ArtnetSenderUIP artnet;
niallfleming commented 3 years ago

No I'm only using the Receiver as shown above, the code in my sketch is largely unchanged except that I removed a bunch of serial.print(ln)s, and reenabled all the FastLED stuff.

I'm starting to think this may be impossible on nano.

hideakitai commented 3 years ago

Yes, I recommend you to use the more powerful board if you can (Teensy, ESP32, etc.).

hideakitai commented 3 years ago

@niallfleming I'm going to close this issue but please reopen if you have any other suggestions.