stm32duino / STM32Ethernet

Arduino library to support Ethernet for STM32 based board
151 stars 42 forks source link

Massive lost of received packages using UDP #53

Closed sstaub closed 2 years ago

sstaub commented 3 years ago

I have a big problem when using the UDP and receiving packages. I use a simple code for testing UDP receive. This works fine when you get sometimes a package. But when getting a bunch of messages more than 60% of the packages are lost. I have the same problem with Mbed, so I think it could be a LWIP problem. If I use nearly the same code for Teensy41 with NativeEthernet library based on FNET it works as expected even with high data traffic, also when using WIZNet 5500 chips. Following code for testing:

#include "Arduino.h"
#include "LwIP.h"
#include "STM32Ethernet.h"
#include "EthernetUdp.h"

IPAddress localIP(10, 101, 1, 201); // IP address of the microcontroller board
IPAddress subnet(255, 255, 0, 0); // subnet range
uint16_t localUdpPort = 8001;
IPAddress remoteIP(10, 101, 1, 100); // IP address of the gma3 console
uint16_t remotePort = 8000;

EthernetUDP udp;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(localIP, subnet);
  udp.begin(localUdpPort);
  }

void loop() {
  static String message;
    int size;
  size = udp.parsePacket();
    if (size > 0) {
        // Fill the msg with all of the available bytes
        while (size--) message += (char)(udp.read());
    Serial.println(message);
        message = String();
        }
  }
ABOSTM commented 2 years ago

Hi @sstaub Sorry for this late answer, I know it quite a long time ... Nevertheless, I made some testing and here is my findings:

Setup I used Python script to send UDP packet from my computer to my Nucleo_F746ZG Arduino_Core_STM32: main (sha1: 67a5298b92140de11a38a2c10869d505eb1c1466) STM32duino_STM32Ethernet: main (sha1 7669880d8f1347b45f4bc2749ce9ef3eaf2b40ba)

import socket
from time import sleep

UDP_IP = "192.168.0.177"
UDP_PORT = 8001
MESSAGE = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

print("UDP target IP: %s" % UDP_IP)
print("UDP target port: %s" % UDP_PORT)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # UDP

for x in range(100):
    UDP_MSG = MESSAGE + "{0:>3}".format(x).encode('ascii')
    print("message: %s" % UDP_MSG)
    sock.sendto(UDP_MSG, (UDP_IP, UDP_PORT))
    sleep(0.0000000001)

And I used your sketch on Nucleo to receive UDP packet

Results That is right that I face high percentage of packet lost, BUT, using serial at 115200 instead of 9600 drastically improves performances : 100% packet received. !!!

Of course increasing Serial speed let more CPU bandwidth to deal with UDP packet, But also, compare to your testing (almost a year ago), there as been some improvements, especially on Serial https://github.com/stm32duino/Arduino_Core_STM32/pull/1313

Note: you can see that there is a sleep() function in my python script between each packet send. If I remove this delay, there are packets lost, but I feel like it is understandable: MCU (216MHZ) cannot be as fast as my core i7 (2.9GHZ). Also, without delay, instead of printing the full message, I tried to print only a message count (leaving more CPU bandwidth for UDP), and things are better (even if not perfect).

That said, the sleep duration is the smallest I can set, (smaller value seems to do no difference). And with this minimal delay, there is no packet lost (Serial == 115200)

sstaub commented 2 years ago

Thanks for testing and suggestions, I work on a new library for OSC, when ready I will retest. The problem is that I have no control over the OSC sender, so I get a bunch of messages in a very short time.

fpistm commented 2 years ago

Based on @ABOSTM input this issue seem less relevant so I close it. It could be reopen later if needed.