1

I have 2 programs to test serial communication, an simple arduino program that echoes whatever is on the serial port and a python program that writes to the serial port and prints the reply.

I'm having an issue where whenever I upload the arduino program and try to run the python code the arduino code wouldn't detect serial available on the first run. I would have to either

  • open and close serial monitor before I run python program
  • run the python program, quit, and run it again

and it would continue to work until I re-upload the arduino then the same thing happens. Does anyone know what is the issue? This is on Ubuntu.

arduino

String str;

void setup() {                
// Turn the Serial Protocol ON
  Serial.begin(115200);
}

void loop() {
  if (Serial.available()) {
      str = Serial.readStringUntil('\n');     // Read the serial input
      Serial.println(str);             // sends ascii code

  }
}

Python

import serial


ser = serial.Serial('/dev/ttyACM1', 115200)

for i in range(0,4):
    str = "test string\n"
    ser.write(str)
    print ser.readline()
  • Even: void setup() { Serial.begin(115200); Serial.println("Hello, World!"); } fails right after upload. This seems to have happened relatively recently in the development of the IDE; I've no idea why but I'd sure like to fix it. – JRobert Jun 15 '16 at 1:18
2

This fails due to the typical auto-reset-on-open serial port configuration interacting with a problematic assumption made by the PC code.

The first issue means that it will typically take a few seconds between when the port is opened (unless the port is configured not to manipulate modem control signals on open) and when the usual bootloader times out, yields to the custom sketch loaded in the Arduino, and the latter becomes able to accept input and potentially respond.

The second issue is with the PC side code:

for i in range(0,4):
    str = "test string\n"
    ser.write(str)
    print ser.readline()

Assuming that import serial refers to pySerial, then because you did not specify a timeout when opening the port, the ser.readline() is an eternally blocking read. To quote the documentation:

Be carefully when using readline(). Do specify a timeout when opening the serial port otherwise it could block forever if no newline character is received.

If we look at what happens with your python program and a typical serial port configuration where modem status lines change on open, then the first thing your program does is implicitly reset the Arduino. Next, it writes "test string\n" - but because of the reset, it writes this at the bootloader, not the sketch which is not running yet. Finally your program eternally waits for a newline terminated reply - which it will never receive, because your sketch will not send that until it receives something from the PC, which will not send anything else until it receives the newline terminated response to its first message.

Your programs are thus stuck in a "no, after you" deadlock.

There are many potential ways to work around this. For example, you might open the port with a timeout, wait a few seconds, and conduct this test write and attempt to read a reasonable number of times, but declare an error to the user if success is not achieved in ten or so seconds of those attempts.

Note also that the sketch may start running midway through transmission of the test string, so you will have to handle the possibility of a message with the beginning missing, either by declaring an error or discarding it and waiting for a subsequent intact one.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.