views:

87

answers:

3

I am hoping this is a simple stupid noob mistake that can be fixed with the addition of a single line of code somewhere.

I'm using pySerial to read in serial data from a USB port and print it out to standard output. I'm running Mac OSX 10.6. I open terminal and type "python", then the following:

>>> import serial;
>>> ser = serial.Serial('/dev/tty.usbserial-XXX', 9600, timeout=1);
>>> while True:
>>>      if ser.inWaiting() > 0:
>>>            ser.readline();
>>> [done, I hit enter...]

This works beautifully. It starts outputting my serial data nicely, exactly as I'd expect it to. Great, I think, let me put this into its own script with command line arguments and then I can call it any time I want to:

import sys;
import serial;

serialPort = sys.argv[1]
baudRate = sys.argv[2]

ser = serial.Serial(serialPort, baudRate, timeout=1)

while True:
    if ser.inWaiting() > 0:
        ser.readline()

On the command line, I type "python myScript.py [my serial port] 9600" and sit back and wait for a beautiful flow of serial data - but nothing comes out. It just kinda hangs until I kill the process.

I thought, well maybe for some reason it's not working - so I put some debugging prints into the code. I update my while loop to look like this:

 while True:
    print("looping...")
    print(ser.inWaiting());
    if ser.inWaiting() > 0:
        ser.readline()

I run it again, and I get a repeating output stream of "Looping..." and "0". I think, well maybe there's something wrong with my command line arguments - so I hard-coded the port and the baud rate into the script, same thing.

So, why would this be the case? Is my use of while True: somehow blocking the script from accepting serial data? Is there a better way to do this?

I'm a complete Python noob. I am writing this script in order to create a faster way to communicate between Adobe AIR and an Arduino board. I'm hoping there's a magic bullet I can drop in here to make it work - is there?

+1  A: 

In your 1st example, baud rate is an integer but in the 2nd, you don't not convert sys.argv[2] from a string. Try this ser = serial.Serial(serialPort, int(baudRate), timeout=1).

Dana the Sane
I'm pretty sure the conversion happens automatically - in my initial attempt I was off by one index in args, and it was throwing errors because it was trying to convert my serial port into an int. I will go ahead and add that conversion operator, but even when I hard-code the baud rate it doesn't work.
Myk
What happens if you hardcode the args in the script so it exactly matches your first example? I wonder if something that is included in the sys package causes problems.
Dana the Sane
hmm, could be. Let me give it a try... [time elapsing] ...no dice. Still just hangs there.
Myk
Sorry that wasn't of more help. I'd give the code a try, but I don't have that usb device in 10.5.
Dana the Sane
+1  A: 

Is it printing anything? I'd assume it would print:

looping...
<ser.inWaiting() val>

And then nothing. Add a print statement so it looks like

print ser.readline()

and see if that works. I'm guessing that the interpreter is printing the returned strings when you do it as a command, but in a script the returned strings from readline() are getting discarded.

Benn
Ah! That did it! How silly of me! Thanks so much! :)
Myk
No problem, we all have those moments :)
Benn
In the CLI, if you give a simple value like `x`, it shows you the value. To get the exact equivalent in a script, use `print repr(x)`.
bukzor
A: 

Is my use of while True: somehow blocking the script from accepting serial data?

Nope. This is very standard practice and doesn't affect I/O in any way. while True is very much equivalent to while 1 in C.

Is there a better way to do this?

I'm concerned about your arguments, like others. This should be more reliable overall:

from sys import argv
from serial import Serial

try:
    baudRate = int(argv[-1])
    serialPort = argv[1:-1]
except ValueError:
    #some nice default
    baudRate = 9600
    serialPort = argv[1:]

#support paths with spaces. Windows maybe?
serialPort = ' '.join(serialPort)
if not serialPort:
    exit("Please specify a serial port")

print( "reading from %r@%i ..." % (serialPort, baudRate) )
ser = Serial(serialPort, baudRate, timeout=1)    
while True:
    if ser.inWaiting() > 0:
        print( ser.readline() )

If that doesn't help you, please check that you are using the same interpreter by running these lines in a script and in the CLI.

import sys
print("Executable: " + sys.executable)
print("Version: " + sys.version)
bukzor