2

I have a question about sending and receiving multiple data using the pySerial Python library. According to what I understand, serial port communication works with byte variables.

How do I send four different variables with method write and then with method read receive two different variables?

As an example:

import serial
import time

sendSerial = serial.Serial ("COM4", 9600)
readoutSerial = serial.Serial ("COM4", 9600)
time.sleep (2)
sendSerial.write ("data1" + "data2" + "data3" + "data4")
while True:
    readoutSerial.read ("data5" + "data6")

What should I do to send the four variables with write differentiated by some character and then separate them for the respective use of each variable? (applying the same for the two variables received with read) Also, what can I do to send the variables asfloat and not generate conflict with the reading in byte?

gre_gor
  • 6,669
  • 9
  • 47
  • 52
Henry Avery
  • 33
  • 1
  • 1
  • 6

3 Answers3

4

If you are transporting text, the easies way is to pick some character to separate individual strings, it can be \n(newline), comma or anything.

ser = serial.Serial ("COM4", 9600)
ser.write(b"some string\n")
ser.write(b"some other string\n")

Reading of text in python will be like this:

s1 = ser.readline()

On arduino, you will read the string like this(primitive example):

char buf[64];
int bufIdx = 0;
while(Serial.peek() != '\n') { // Continue till the end of line
  if(Serial.peek() != -1) { // If no char arrived in this loop, skip.
    buf[bufIdx] = Serial.read();
    bufIdx = (bufIdx + 1) % 64; // Wrap around, so it will not go crazy string too long
  }
}
buf[bufIdx] = '\0'; // End of string char

Or if you don't mind using strings on Arduino(you most likely don't), you might be better of using readStringUntil function:

string str1 = Serial.readStringUntil('\n');
string str2 = Serial.readStringUntil('\n');

In python, you can even convert numerical values into text:

textStr = str(1234)

On Arduino side, you can receive numbers as a string like this:

int x = Serial.parseInt(); // Receives (string)"1234", returns (int)1234
float y = Serial.parseFloat(); // Receives (string)"1.24E13", returns (float)1.24E13

If you need to transport structured binary data, python has a module called struct, that is the recomended way to do it in python. On arduino side, you will most likely have to shuffle bytes manualy. For example, int16 would be received like this:

while(Serial.available() < 2); // Block, until at least 2 bytes are received
int int16;
int16 = Serial.read() | (Serial.read()<<8); // Little-endian, low byte first, high byte second
Martin
  • 333
  • 1
  • 8
1

Using mutex(Lock) to avoid send and receive conflict:

import serial
import time
from threading import Lock

mutex = Lock() 

sendSerial = serial.Serial ("COM4", 9600)
readoutSerial = serial.Serial ("COM4", 9600)
time.sleep (2)

mutex.acquire()
try:
    sendSerial.write ("data1" + "data2" + "data3" + "data4")
except:
    pass
finally:
    self.mutex.release()

while True:
    with mutex:
        readoutSerial.read ("data5" + "data6")
Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
0
  1. Store the strings in a variable such as:

    • var = "data1\r" + "data2\r" + "data3\r" + "data4\r"
  2. Then send the above concatenated string in a for loop

    • for i in range len(var):
      sendSerial.write (var)

This worked for me while I was playing around with the serial port of PSoc using a python script.