views:

562

answers:

3

I want to send some data to an Arduino through pyserial in Python. All I want to the Arduino to do is read the variable length string data from the serial port, and write it back so that Python can read it. Since I've been unable to do that, the code below only has Python sending on character. Here's the Python code:

import serial
import sys
import pywapi
import time

def main():
    ser = serial.Serial(3, 9600, timeout=1)
    print "Conn established"
    print "Sending: %s" % "z".__repr__()
    print ser.write('z'.encode("ascii"))
    time.sleep(2)
    print "Received: %s" % ser.read(10).__repr__()         
    ser.close()

Here's the Arduino code:

void setup(){
  analogReference(DEFAULT);
  Serial.begin(9600);
}

void loop(){
  if(Serial.available() > 0)
    Serial.println("x");
  while(Serial.available() > 0){
    Serial.print(Serial.read(), BYTE);
  }
}

The output:

Conn established
Sending: 'z'
1
Received: ''

I know the code for the Arduino works because it works when data is being sent from the Arduino terminal. However, the moment I try to send anything from Python it fails. I've been struggling with this all day. Any help would be greatly appreciated.

+2  A: 

Try increasing or removing the timeout, and set read's size to 1. You may also want to increase the sleep delay, or even implement a simple read loop.

Something like:

try:
    while True:
        data = ser.read(1).__repr__()
        if data:
            print "Received: %s." % data
        else:
            print "Looping."
except KeyboardInterrupt:
    print "Done."
except:
    raise
finally:
    ser.close()
    print "Closed port."

Then just use ctrl-c to stop it.

Robert Kluin
For some reason, the first read was always returning ''. After implementing a second read for testing purposes it started working (though I still have to do a dummy read whenever the python program starts).
JohnS
Perhaps it has something to do with "Serial.println("x");" in the Arduino code. Does the Python app print the 'x' you send upon connection? If not, maybe the Python app is picking up the newline char that gets sent after the 'x'. Or, if you are still setting a timeout on the Python serial connection the read may be timing out.
Robert Kluin
+2  A: 

I would recommend verifying the two parts independently, using a separate serial port and serial comms software on the PC.

E.g. if your PC has two serial ports, then use a null-modem (loopback) cable to connect them. Or use com0com to make a pair of linked virtual serial ports. Run your Python software on one serial port, and a terminal program (Hyperterminal or RealTerm) on the other serial port. Manually verify the Python program's operation that way.

Then, connect your PC directly to the Arduino as usual, and use the terminal software to manually verify the Arduino software operation.

That process will allow you to narrow down the problem. Once you've verified them both, they should work well together.

Serial Port Monitor

Another method you can use is software that hooks into the PC's serial port driver, and allows you to monitor traffic on the serial port. I've used the Free Serial Port Monitor software from HHD Software in the past, and it worked well for our purposes. It allows you to monitor any of the PC's serial ports, and shows you a log (hex and text) of the serial data going over the port in both directions.

Craig McQueen
A: 

Do you need to flush the sent character out of any held serial buffer?

It may be that your character is not actually leaving the COM port and arriving at the Arduino. When you test this with the Arduino Terminal (I assume you mean the UI terminal in the development environment) you are actually sending your string + a carriage return I think, not just the character. (i.e. do you hit return after you type 'z' in your test?)

Try ser.flush() or perhaps also send a \r character. From your testing the Arduino works just fine, it's the python program that doesn't seem to be sending anything.

Alan Moore