I have a python script that sends a stream of data, and then I have a Linux embedded computer receiving the data (code written in C++). Most of the times it works, however, I am noticing I get data corrupted when sending specific patterns of bytes. I have been struggling with this for a while and I don't know how to solve it.
Python script (sender):
serial = serial.Serial("COM2", 115200, timeout=5) all_bytes = [0x63,0x20,0x72,0x69,0x67,0x68,0x74,0x73,0x20,0x61,0x6e,0x64,0x20,0x72,0x65,0x73,0x74,0x72,0x69,0x63,0x74,0x69,0x6f,0x6e,0x73,0x20,0x69,0x6e,0x0a,0x68,0x6f,0x77,0xff,0x20,0xf0,0x8b] fmt = "B"*len(all_bytes) byte_array = struct.pack(fmt,*all_bytes) serial.write(byte_array)
C++ code (receiver)
typedef std::vector<uint8_t> ustring; // ustring = vector containing a bunch of uint8_t elements // configure the port int UART::configure_port() { struct termios port_settings; // structure to store the port settings in cfsetispeed(&port_settings, B115200); // set baud rates cfsetospeed(&port_settings, B115200); port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits port_settings.c_cflag &= ~CSTOPB; port_settings.c_cflag &= ~CSIZE; port_settings.c_cflag |= CS8; port_settings.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines port_settings.c_cc[VTIME] = 10; // n seconds read timeout //port_settings.c_cc[VMIN] = 0; // blocking read until 1 character arrives port_settings.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl port_settings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw port_settings.c_oflag &= ~OPOST; // make raw tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port return(fd); } int UART::uart_read(ustring *data,int buffer_size) { // Buffer uint8_t * buf = new uint8_t[buffer_size]; // Flush contents of the serial port //tcflush(fd, TCIOFLUSH); //usleep(1000); ustring data_received; // Read int n_bytes = 0; while (n_bytes < buffer_size) { int n = read( fd, buf , buffer_size ); // Some bytes were read! if (n > 0) { n_bytes+=n; // Add to buffer new data! for( int i=0; i<n; i++ ) { data_received.push_back(buf[i]); } } } // String received *data = data_received; cout << "Data received..." << endl; print_ustring(data_received); delete[] buf; return read_valid; } int main() { UART uart_connection; vector<uint8_t> data; vector<uint8_t> *data_ptr = &data; int status = uart_connection.uart_read(data_ptr,36); return 0; }
This is what's happening:
If I send the following bytes (from python):
0x632072696768747320616e64207265737472696374696f6e7320696e0a686f77ff20f08b
This is what I am receiving (in C++ program):
0x632072696768747320616e64207265737472696374696f6e7320696e0a686f77ffff20f0
As you can see there are a few bytes at the end (the CRC) that are changed, the rest seems fine. But it doesn't always happen, it only happens when sending some specific pattern of bytes.
Let's say I send the following for instance (some other pattern):
0x6868686868686868686868686868686868686868686868686868686868686868b18cf5b2
I get exactly what I am sending in the above pattern!
At first I thought it was Pyserial changing my unsigned bytes to ASCII... But now I know for sure now that pyserial is not the problem. I tried replacing pyserial with nodejs serial port library. The same problem persists. I noted that the only way to "fix it" is closing the port and opening it again. Once the port is opened, the serial port data will either be (always corrupted or always right) depending if the first one was received OK or corrupted I have no clue what's going on. I have been struggling with this for days!