• Programming
  • Reading the quarto's serial port with python faster?

Hello everybody,

The following code is uploaded on the Quarto:

int incoming;
volatile double ch1_data;

void setup() {
Serial.begin(9600);
configureADC1(4,0,BIPOLAR_1250mV,getADC1);
}

void getADC1(void){
ch1_data = readADC1_from_ISR(); //read ADC1 voltage
}

void loop() {
if (Serial.available() > 0) {
incoming = Serial.read();
if (incoming == 'A') {
toggleLEDGreen();
Serial.print(ch1_data, 8); }
} }

And I am using the following Python code to get the data from the Quarto's serial port:
for v in range(5):
ser.write(b'A')
line = ser.readline()
print(line)

The code works, but it takes about 5 seconds to run the for loop, which adds up to be a really long time in my code.
What can I do to make the data acquisition faster?

Thanks!

The slowness is because of the python line ser.readline(). readline() is blocking (meaning it takes prevents anything else from happening) until either it hits a timeout, or it gets an end-of-line (EOL) character. In the case of PySerial, the EOL character is \n. The timeout is set when python initializes the serial port. If you have
ser = serial.Serial('COM16',115200,timeout=5)
then anytime ser.readline() is run, the command will wait for up to 5 seconds to get an EOL character.

In your Quarto code, when a command is sent, the returned data does not have a \n at the end to mark the end of line, to python keeps waiting for it until it times out each time readline() is run.

There are two solutions. One is add a terminal line to your sends, so replace

if (incoming == 'A') {  
    toggleLEDGreen(); 
    Serial.print(ch1_data, 8);
}

with

if (incoming == 'A') {  
    toggleLEDGreen(); 
    Serial.print(ch1_data, 8);
    Serial.print('\n')
}

Alternatively, you can replace Serial.print(ch1_data, 8); with Serial.println(ch1_data, 8); to do it on one line. That uses the Arduino's Serial print line command, which ends each line with a \r\n. This will work fine with PySerial's readline, but you'll see \r\n and the end of each line instead of just \n.

The second solution is to not use readline, but instead read by fixed number of bytes you want to read and then you do not need to change the Quarto code to add line termination. This can be tricky because you have to make sure the Quarto always sends the same number of bytes. Serial.print(512,HEX) will send out "200" (3 bytes) but Serial.print(16384) will send out 4000 (4 bytes). But if your Quarto code does send out fixed bytes (let's say 4) then you can replace ser.readline() with ser.read(4) to read exactly 4 bytes.