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?

2
  • 1
    In any case, this is not a good way to write an IO loop. Have you tried reading regardless of whether there is anything waiting? The read method should block until sufficient data is available, or the timeout passes. Commented Oct 28, 2010 at 15:25
  • Oh, that's a good point - hadn't even really thought about it, I can just nix the nested conditional. I will do that - though it doesn't address the larger issue. :-\ Commented Oct 28, 2010 at 15:27

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

No problem, we all have those moments :)
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).
1

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).

4 Comments

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.
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.
hmm, could be. Let me give it a try... [time elapsing] ...no dice. Still just hangs there.
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.
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.