Indexing data using UDP useless?

Hello everyone,
Iam working on a project where i want to send a 4 digit number between 2500 and 3524 to my pc from my esp32. I am an arduino novice and read somewhere that udp protocol is the fastest to transfer data. together with chatgpt i wrote this code to transfer the data. somewhere else i read that you can have packet lose with udp, that is not really a bad thing since i will refresh the data quickly and a few data points missed is not the worst. But the order of the data points is important so if i lose something that probarbly messes up the data order. So for every data point i assigned an index number first=1 second=2 etc. Is this uselesss? cause these indexes could also be lost? and if i dont include the index the transfer is faster and i need it as fast as possible. Also any tips on a faster transfer are apprecoated thanks!
Below my code.

#include <WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "secret";
const char* password = "SECRET";

const char* host = "?"; // PC's IP address
const int port = 12345;

WiFiUDP udp;

const int dataCount = 1024;  // Total numbers to send
const int maxPacketSize = 1400; // Max UDP payload (in bytes)

// Temporary buffer for data packets
uint8_t packetBuffer[maxPacketSize];

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to Wi-Fi");

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("\nConnected to Wi-Fi");
  udp.begin(port);
}

void loop() {
  // Populate and send data in batches
  unsigned long startTime = millis();

  for (int i = 0; i < dataCount; i += maxPacketSize / 4) {
    // Fill the packet buffer with index-value pairs
    int packetLength = 0; // Reset packet length
    for (int j = 0; j < maxPacketSize / 4 && (i + j) < dataCount; j++) {
       uint16_t index = i + j + 1;       // 1-based index
      uint16_t value = 2500 + i + j;   // Corresponding data value

      // Write index and value to the buffer
      memcpy(&packetBuffer[packetLength], &index, sizeof(index));
      packetLength += sizeof(index);
      memcpy(&packetBuffer[packetLength], &value, sizeof(value));
      packetLength += sizeof(value);
    }

    // Send the packet
    udp.beginPacket(host, port);
    udp.write(packetBuffer, packetLength);
    udp.endPacket();
  }

  unsigned long endTime = millis();
  Serial.println("Time taken: " + String(endTime - startTime) + " ms");

  // Reduce or eliminate delay for speed testing
  delay(100); // Adjust or remove for live data
}

No comment !

Yes the chance of packet loss exists, it is a protocol without confirmation, and even the arrival order of the packets may not be the same as the transmission order. Though this largely depends on the other network traffic, it should always be a consideration.

You send a packet. If you include a header as a part of the packet, that is preferred. I don't know what kind of speed you are aiming for.

The program that you have written now first chucks all of your data into 1 packet and then transmits. Either that packet is received or it isn't. In that scenario it makes no sense to add indices within that packet.

If you are going to send the data a packet at a time, adding a header with either an index or probably more simple using a timecode, makes sense, so that at least the received packets can be put into the correct order.

you should ask CrapGPT what's the disadvantages of UDP are.

Hi @matrixesp32 ,

what you are intending to do ... is to implement TCP :wink:

TCP other than UDP is a protocol to support the transfer of data packages where the TCP stack takes care of the order of packages, sorts them if they come disordered etc.

Most of the problems occur more likely in a WAN than a small LAN.

If you consider this (Source: wikipedia )

UDP is suitable for purposes where error checking and correction are either not necessary or are performed in the application; UDP avoids the overhead of such processing in the protocol stack. Time-sensitive applications often use UDP because dropping packets is preferable to waiting for packets delayed due to retransmission, which may not be an option in a real-time system

it's not likely that you earn something (except knowledge and experience) if you implement error corrections etc. on your own.

I would recommend to test TCP in parallel to see if it is significantly delaying anything in your communication chain.

What is acceptable and what not finally depends on the limits and requirements of your application.

I wrote this post on my own without any AI assistance, so any errors are based on human failure

ec2021

those for's are hard to read..
the memcpy is confusing and probably slows you down..
a sequence per packet wouldn't be a bad idea but not one for each word..
take a peek at this..

good luck.. ~q

If packet order is important then you need to go tcp but if this is just over your local network udp should work ok for you.

I implemented TCP, and it works, but iam having stability issues. sometimes it takes 1 ms to transfer the data and the next cycle to send the data it takes 150ms to send the data. I tried a more stable power source by using 5v instead of 3v from usb but it didnt improve. do you have any ideas?

Have you tried what happens when you connect your PC to the ESP directly (the esp as an AP )

the cause is most likely the router.

Is it true that you don't lose data but the timing doesn't meet your expectations?

TCP has not been designed to be a realtime transmission rather than a safe way to transport data streams.

There is a tradeoff between small amounts of data sent as immediately as possible and the required overhead for stability and keeping track of the correct order.

Would you mind to tell a little bit more about your intended application (what do you want to achieve, not how)?

How dod you measure the 150ms .. and the 1ms before?

no data lost, the timing doesnt meet my expectations. i am creating a matrix pressuremat with 1024 points. i want to measure every point +-50 per second. i want to send this data live or near live to a pc where i can save it.
i tried with udp again just generating a number between 0 and 4000 packaging that and then sending it. the max bytes/s i got was 400000B/s, the send time takes between 0-1ms. then i tried to write whatever i send into the arduino ide serial and the send time shoots up to 2-4ms. i think the esp32 is just not good enough for what iam trying to do. Also a lot of people online say that esp32 wifi is garbage, so i will start looking for something more powerfull. unless you have some better idea?

Thanks for the update.

Without your test sketches it is hard to identify reasons for your findings ...

An improvement in case one encounters problems with the ESP32 Wifi (not verified by myself) has been mentioned here:

ESP32 power supply

Regarding the indexing from post #1: It is not required to put an index to each measurement in the UDP datagram. If you lose data it will be a complete datagram, not parts of it. So you could reduce the transmission of 1024 data to two UDP calls instead of three.

Each transmission could hold a time stamp (e.g. millis) in the first eight bytes of the datagram, a flag for first or second package in a row and 512 integer data (1024 bytes).

Depending on what you are doing on the PC side you might even be able to cope with the loss of some packets, e.g. by a dead reckoning algorithm (https://en.wikipedia.org/wiki/Dead_reckoning)

Just curious: How are you going to measure the 1024 points at 50 Hz?

my plan is to use a sepperate adc to measure the signal. I was looking at other options beside an esp32 and came across the Pi zero 2 W. this is basically an allround better version of the esp32. it has enough pins and i dont need to send a 50hz signal over the wifi. i can send a 10hz signal over wifi for live viewing and store the data of 50hz on the board and later retrieve it.
On the power supply solution, i tried it but nothing changed.
Thanks for you input, still learned some stuff about protocols.

You mentioned values between 2500 and 3524.

If you subtract 2500 from the value (and limit to 3523) you get values between 0 and 1023. That fits into 10 bits.

Now do some bit stuffing by encoding 4 integer values in 40 bit = 5 byte:

  • put the lower 8 bits in the first 4 bytes
  • store the higher 2 bits of these four values in the fifth byte

These leads to (1024 /4)*5 bytes = 1280 bytes. That fits in one UDP datagram.

Further question: I understand you have 1024 points to measure. Are you planning to use Analog Multiplexers?