Potential UDP data loss or wrong Python syntax

34 views Asked by At

I am doing a project involving UDP from teensy 4.1 to PC. After some experiments and help from forums I managed to acquire data on teensy and send to the PC via regular Cat5e twisted pair cable. The problem is that the data I am receiving on the PC is far from what I am actually sending. I already verified that hardware is tested and working properly.

2 pictures down below of arduino serial monitor (two numbers separated by space converted into 12 position char array, nice and clean, thats what I am after...) and text file on PC (there are some fragments of the data I want but its really messy and unpredictable).

What is more, the text file should be written almost instantly, but after running the python code for 5-10 seconds, I only get sometimes only several hundred lines beginning and ending with random numbers (it should always be 0-4095)

I guess there is no problem with the teensy code. But I am not sure about python. I wrote and improvised an algorithm to synchronize teensy and PC (teensy is constatnly spitting stream of data, the PC only has to write data lines that contain 0-4095 first number values.)

I am aware that UDP can lose some packets etc. But I am giving a really generous 50 us delay after each send operation on teensy, I feel like this problem is not about UDP limits, any observations about python code? Thank you in advance

P.S. I am adding teensy code, but its really bulky and I believe its ok...

Teensy:

#include <QNEthernet.h>
//#include "TeensyTimerTool.h"

using namespace qindesign::network;
//using namespace TeensyTimerTool;

IPAddress staticIP{10, 10, 16, 111};
IPAddress subnetMask{255, 255, 255, 0};
IPAddress gateway{10, 10, 16, 1};

constexpr uint16_t kPort = 5190;  

EthernetUDP udp;

static void printPrompt();
static void receivePacket();
static void sendLine();

int Chanel[4096];

int Chanel_value[4096] = {0};

int Analog_value = 0;

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {

  }
  printf("Starting...\r\n");

  uint8_t mac[6];
  Ethernet.macAddress(mac);  
  printf("MAC = %02x:%02x:%02x:%02x:%02x:%02x\r\n",
         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  Ethernet.onLinkState([](bool state) {
    printf("[Ethernet] Link %s\r\n", state ? "ON" : "OFF");
  });

  printf("Starting Ethernet with static IP...\r\n");
  if (!Ethernet.begin(staticIP, subnetMask, gateway)) {
    printf("Failed to start Ethernet\r\n");

  }

  udp.begin(kPort);

  printPrompt();

  for (int i = 0; i<4096; i++){
    Chanel[i]=i;
  }

  analogReadResolution(12);

}
//*******************************************************************************************************************

void loop() {

  Analog_value = analogRead(A9);

    for (int i = 0; i<4096; i++){
      if(Analog_value==Chanel[i]){
      Chanel_value[i]++;
      }
    }
    delay(1000);
sendLine();
//Serial.end();

}

//*******************************************************************************************************************

static const String kCtrlNames[] {
  "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
  "BS",  "HT",  "LF",  "VT",  "FF",  "CR",  "SO",  "SI",
  "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
  "CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US",
};


static void receivePacket() {
  int size = udp.parsePacket();
  if (size < 0) {
    return;
  }

  const uint8_t *data = udp.data();
  IPAddress ip = udp.remoteIP();

  printf("[%u.%u.%u.%u][%d] ", ip[0], ip[1], ip[2], ip[3], size);

  for (int i = 0; i < size; i++) {
    uint8_t b = data[i];
    if (b < 0x20) {
      printf("<%s>", kCtrlNames[b].c_str());
    } else if (b < 0x7f) {
      putchar(data[i]);
    } else {
      printf("<%02xh>", data[i]);
    }
  }
  printf("\r\n");
}

static bool readLine(String &line) {
  static bool inCR = false;  

  while (Serial.available() > 0) {
    int c;
    switch (c = Serial.read()) {
      case '\r':
        inCR = true;
        return true;

      case '\n':
        if (inCR) {
          
          inCR = false;
          break;
        }
        return true;

      default:
        if (c < 0) {
          return false;
        }
        inCR = false;
        line.append(static_cast<char>(c));
    }
  }
  return false;
}


static void printPrompt() {
  printf("chat> ");
  fflush(stdout);  
}

static void sendLine() {

char line[12]={'\0'};

  for (int i = 0; i<4096; i++){
    
    line[0]=((Chanel[i]/1000)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[0],sizeof(char)); 
    Serial.print(line[0]);

    delayMicroseconds(50);           

    line[1]=((Chanel[i]/100)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[1],sizeof(char)); 
    Serial.print(line[1]);

    delayMicroseconds(50);

    line[2]=((Chanel[i]/10)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[2],sizeof(char)); 
    Serial.print(line[2]);

    delayMicroseconds(50);

    line[3]=(Chanel[i]%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[3],sizeof(char)); 
    Serial.print(line[3]); 

    delayMicroseconds(50);

    line[4]=' ';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[4],sizeof(char)); 
    Serial.print(line[4]);

    delayMicroseconds(50);

    line[5]=((Chanel_value[i]/1000000)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[5],sizeof(char)); 
    Serial.print(line[5]);

    delayMicroseconds(50);

    line[6]=((Chanel_value[i]/100000)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[6],sizeof(char)); 
    Serial.print(line[6]);

    delayMicroseconds(50);

    line[7]=((Chanel_value[i]/10000)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[7],sizeof(char)); 
    Serial.print(line[7]);

    delayMicroseconds(50);
  
    line[8]=((Chanel_value[i]/1000)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[8],sizeof(char)); 
    Serial.print(line[8]);

    delayMicroseconds(50);

    line[9]=((Chanel_value[i]/100)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[9],sizeof(char)); 
    Serial.print(line[9]);

    delayMicroseconds(50);

    line[10]=((Chanel_value[i]/10)%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[10],sizeof(char)); 
    Serial.print(line[10]);

    delayMicroseconds(50);

    line[11]=(Chanel_value[i]%10)+'0';
    udp.send({10, 10, 16, 110}, kPort,(const uint8_t*)&line[11],sizeof(char)); 
    Serial.print(line[11]);

    Serial.print('\n');

    delayMicroseconds(50);

    printPrompt();
    delayMicroseconds(50);
  }
  
}

Python:

    import socket
from datetime import datetime
import os
import time

localIP = "10.10.16.110"
localPort = 5190
bufferSize = 1024

counter = 0

flag = 0

msgFromServer = "Hello UDP Client\n"

bytesToSend = str.encode(msgFromServer)

UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

UDPServerSocket.bind((localIP, localPort))

print("UDP server up listening")

while(True):

    bytesAddressPair = UDPServerSocket.recvfrom(bufferSize)
    message = bytesAddressPair[0]

    address = bytesAddressPair[1]
    clientMsg = "Message from client:{}".format(message.decode())
    clientIP = "Client IP Address:{}".format(address)
    file = open ('Results.txt', 'w') 
    now = datetime.now() 
    if counter%12==0:
        dt_string = now.strftime("%Y/%m/%d, %H:%M:%S")
    else:
        dt_string = ''

    if flag == 1: 

        if counter < 4096:

            if counter%12==0:
                with open(os.path.join('D:\VSC_projektai\Python_ETH','Results.txt'), 'a') as f1: 
                    f1.write("\n")
                    f1.write("{} {}".format(dt_string,message.decode()))
                
            else:
                with open(os.path.join('D:\VSC_projektai\Python_ETH','Results.txt'), 'a') as f1: 
                    f1.write("{}".format(message.decode()))
            
            counter=counter+1

    else:
    
        counter=counter+1

        if counter==4095:
            flag=1
            counter=0

    print(clientMsg)
    print(clientIP)

    UDPServerSocket.sendto(bytesToSend, address)

enter image description here

enter image description here

0

There are 0 answers