Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

udp multicast, receiving bytes stops after a while #132

Open
lathoub opened this issue Apr 26, 2020 · 7 comments
Open

udp multicast, receiving bytes stops after a while #132

lathoub opened this issue Apr 26, 2020 · 7 comments
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Comments

@lathoub
Copy link
Contributor

lathoub commented Apr 26, 2020

Hi, I wrote a library for Arduino to send/receive ipMIDI (IDE 1.8.10). All works fine, but after a while, the Arduino stops receiving input (sending bytes continues to work).

The failure does not happen after a fixed number of reads or parsepackets, it varies between 10 and 1000 iterations in the example. Failure happens on both W5100 and W5500 shields and on both Arduino Ethernet (W5100) and MKR1000 with Ethernet shield (W5500). Failure does not happen on ESP32.

Below the (compacted) source code for an Arduino Ethernet (using 38% program storage space, 25% of dynamic memory). Packet Sender on a Mac (10.15.4) sends 3 bytes (MIDI note on) to multicast address 225.0.0.37, port 21928 (udp) every 500ms.

#include <EthernetUdp.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,

EthernetUDP Udp;
int loopCounter = 0;

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

  Ethernet.begin(mac);
  Udp.beginMulticast({ 225, 0, 0, 37 }, 21928);
}

void loop() {
  auto packetSize = Udp.parsePacket();
  if (packetSize > 0) {
    Serial.print("packetSize: ");
    Serial.println(packetSize);

    auto readLen = Udp.read(packetBuffer, sizeof(packetBuffer));
    for (auto i = 0; i < packetSize; i++) {
      Serial.print ("0x");
      Serial.print (packetBuffer[i], HEX);
      Serial.print (" ");
    }
    Serial.println(loopCounter++);
  }

  Ethernet.maintain();
}
@lathoub
Copy link
Contributor Author

lathoub commented Apr 26, 2020

sample output:

...
11:22:22.527 -> 0x90 0x4C 0x40 589
11:22:22.948 -> packetSize: 3
11:22:22.948 -> 0x90 0x4C 0x40 590
11:22:23.398 -> packetSize: 3
11:22:23.398 -> 0x90 0x4C 0x40 591
11:22:23.830 -> packetSize: 3
11:22:23.830 -> 0x90 0x4C 0x40 592
11:22:24.283 -> packetSize: 3
11:22:24.283 -> 0x90 0x4C 0x40 593
11:22:24.704 -> packetSize: 3
11:22:24.704 -> 0x90 0x4C 0x40 594

in this case, receiving stops after 594 packets - that number varies

@Rotzbua
Copy link
Contributor

Rotzbua commented Apr 26, 2020

@lathoub Did you checked for a memory leak?

@lathoub
Copy link
Contributor Author

lathoub commented Apr 26, 2020

@Rotzbua no memory is dynamically allocated in the above example. Only static memory is used in packetBuffer. (I don't know what happens in the Ethernet library)

@Rotzbua
Copy link
Contributor

Rotzbua commented Apr 26, 2020

@lathoub My suggestion is a memory leak in the library, because it stops after "some packets". I suggest to print the free ram of the arduino in every loop, if it becomes less there is a memory leak otherwise there is a other problem. https://github.com/mpflaga/Arduino-MemoryFree

Maybe check your hardware (clone?) for faulty design. Those clones cost me a lot of time in the past #117 .

@lathoub
Copy link
Contributor Author

lathoub commented Apr 26, 2020

@Rotzbua thanks - I installed the suggested MemoryFree library and printed the freeMemory(). No memory leak, stable at 2292 bytes (all using genuine Arduino hardware)

17:40:52.886 -> packetSize: 3
17:40:52.886 -> 0x90 0x4C 0x40 248 2292
17:40:53.876 -> packetSize: 3
17:40:53.876 -> 0x90 0x4C 0x40 249 2292
17:40:54.834 -> packetSize: 3
17:40:54.834 -> 0x90 0x4C 0x40 250 2292
17:40:55.811 -> packetSize: 3
17:40:55.811 -> 0x90 0x4C 0x40 251 2292
17:40:56.772 -> packetSize: 3
17:40:56.772 -> 0x90 0x4C 0x40 252 2292

@Rotzbua
Copy link
Contributor

Rotzbua commented Apr 26, 2020

The last thing is a code part which depends on ram of the target. Printing MAX_SOCK_NUM should give you 8 on the mkr1000 and 4 on Uno.

Ethernet/src/Ethernet.h

Lines 32 to 40 in 6e9dffa

// Configure the maximum number of sockets to support. W5100 chips can have
// up to 4 sockets. W5200 & W5500 can have up to 8 sockets. Several bytes
// of RAM are used for each socket. Reducing the maximum can save RAM, but
// you are limited to fewer simultaneous connections.
#if defined(RAMEND) && defined(RAMSTART) && ((RAMEND - RAMSTART) <= 2048)
#define MAX_SOCK_NUM 4
#else
#define MAX_SOCK_NUM 8
#endif

@lathoub
Copy link
Contributor Author

lathoub commented Apr 26, 2020

W5100 (Arduino Ethernet) reports 4, W5500 shield (on MKRZERO) reports 8.

@per1234 per1234 added topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project labels Feb 22, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

No branches or pull requests

3 participants