sgb27
Posts: 4
Joined: Wed Aug 05, 2020 6:09 pm

Serial comms to Arduino only work after using screen command

Wed Aug 05, 2020 6:17 pm

I've got a strange problem that took a while to figure out, but I don't understand what is going on.

I have an arduino gathering some data, and it also waits for very simple commands (a single character) on the serial port, and replies back on the serial port with some numbers sandwiched between the command character. As an example, I'd send "A" down the serial port, and it would reply with "A50.45,200.35A".

I've connected it up to the pi, was testing it manually using "screen /dev/ttyUSB0", then wrote a python script to communicate with it. All working fine.

However when I restart the pi (or rather it got restarted because my power cut out), the python script then doesn't work. It seems to send the command ok, but then is just hangs on the serial.read() command. If I quit out of that, run the above screen command all works well, then go back and run my python script and it works!

What is it that the "screen" command is doing, that somehow then enables my python code to work? This is my SendCommand function, it hangs at the first serPort.read(1) line.

Code: Select all

# com is a command
def sendCommand(serPort, com):
  serPort.write(bytes([com]))

  # wait until "A" is recieved
  rec = 0
  while rec != com:
    bytesReceived = serPort.read(1)
    if( len(bytesReceived) == 1 ):
      rec = bytesReceived[0]
  
  # now receive all data
  rData = bytearray(0)
  rec = 0  
  
  while rec != com:
    bytesReceived = serPort.read(1)
    if( len(bytesReceived) == 1 ):
      rec = bytesReceived[0]
      if( rec != com ):
        rData.append(rec)
        
  v = rData.decode()
  return v

hippy
Posts: 7911
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Serial comms to Arduino only work after using screen command

Wed Aug 05, 2020 7:16 pm

sgb27 wrote:
Wed Aug 05, 2020 6:17 pm
If I quit out of that, run the above screen command all works well, then go back and run my python script and it works!
Sounds like the 'screen' command is setting some /dev/ttyUSB0 characteristic which the Python code isn't itself setting.

Something to do with the way you are opening the port perhaps ? Maybe post your full code.

sgb27
Posts: 4
Joined: Wed Aug 05, 2020 6:09 pm

Re: Serial comms to Arduino only work after using screen command

Wed Aug 05, 2020 9:50 pm

Sorry, here's the rest of the code in my main(), up until it blocks in the sendCommand function.

Code: Select all

ser = serial.Serial('/dev/ttyUSB0', 9600, 8, 'N', 1, timeout=0)
v = sendCommand(ser, 65)
v = v.split(",")

User avatar
scruss
Posts: 3256
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: Serial comms to Arduino only work after using screen command

Wed Aug 05, 2020 11:46 pm

it's more likely blocking on the 'timeout=0'
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.
Pronouns: he/him

sgb27
Posts: 4
Joined: Wed Aug 05, 2020 6:09 pm

Re: Serial comms to Arduino only work after using screen command

Thu Aug 06, 2020 8:45 am

I understood from the docs that timeout=0 means non-blocking mode?

https://pyserial.readthedocs.io/en/late ... l_api.html

Anyway, the code does work, albeit after I've had to run the screen command. My question is, what could the screen command be doing regarding the serial port that then makes my code work? It's annoying as I want my code to run when the pi boots.

Edit: Actually the read call is not blocking, it just always returns zero, so gets stuck in my while loop waiting for the reply from the Arduino.

User avatar
scruss
Posts: 3256
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: Serial comms to Arduino only work after using screen command

Thu Aug 06, 2020 4:47 pm

my mistake: it's timeout = None (or omitting it altogether) that's block forever. Sorry about that.

screen does set some defaults in your serial port. After a fresh reboot, try:

Code: Select all

stty -F /dev/ttyUSB0
and note the results. Run screen, then run the stty command again. Note the differences.

stty is horrible, but it's all we've got. To get to a fair approximation of 9600 baud 8N1, you need this stty command:

Code: Select all

stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.
Pronouns: he/him

hippy
Posts: 7911
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Serial comms to Arduino only work after using screen command

Fri Aug 07, 2020 10:47 am

sgb27 wrote:
Thu Aug 06, 2020 8:45 am
Edit: Actually the read call is not blocking, it just always returns zero, so gets stuck in my while loop waiting for the reply from the Arduino.
Sounds like your Arduino may be stuck in a 'transmitting break' state which running the 'screen' command kicks it out of. Perhaps the Arduino doesn't initialise its UART until it sees an RTS signal or something like that.

I would trim the project right back, Pi and Arduino side, send just one byte and echo it back. Get that working and then build on that foundation.

sgb27
Posts: 4
Joined: Wed Aug 05, 2020 6:09 pm

Re: Serial comms to Arduino only work after using screen command

Fri Aug 07, 2020 12:17 pm

Thanks, that's exactly what I have been doing over the last day or two. I think I've found the issue.

The key for me was that going through my code by typing it in "live" to the python interpreter worked, even without using screen first, so I figured this must be some kind of timing issue.

This is what I think is happening:

My code opens the serial port and immediately sends the first command byte. Without running screen first, the Arduino resets every time I open the serial port, so sending the first byte is too quick and gets lost on the way to the Arduino.

Running screen and then quitting out seems to still keep the serial port open somehow (or some other state change), as from then on running my program does NOT reset the Arduino each time, so it's ready to receive the command byte immediately.

I simply put a 5 second delay between opening the serial port and sending the first command, and it works now even without screen.

Thanks for all the suggestions.

User avatar
scruss
Posts: 3256
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: Serial comms to Arduino only work after using screen command

Fri Aug 07, 2020 2:54 pm

That's a fortunate discovery. But:
the Arduino resets every time I open the serial port
Yes, it's part of the design. It can be annoying, or it can be useful. I certainly wouldn't rely on some residual process from screen keeping the connection open for later use, especially if you're collecting data or controlling a process that might be disturbed by a reset.

Worse still, Arduino serial port behaviour varies from model to model. A clue is if the device appears as ttyACM* instead of ttyUSB*: these often behave quite differently. The if (Serial) clause is a fairly harmless check to see if the port is ready.
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.
Pronouns: he/him

Return to “Interfacing (DSI, CSI, I2C, etc.)”