[Tutor] any serial gurus available?

Michael P. Reilly arcege@speakeasy.net
Thu, 3 May 2001 11:26:28 -0400 (EDT)


Bill Tolbert wrote
> I need to read data from a small medical device over a serial port (it's a
> spirometer; measures lung function). I'm using Roger Burnham's Serial
> package, Python 2.0 on Win98.
> 
> According to the documentation (yes, I have some!) the "transmission shall
> be initiated when the PB100 sends a start of header character (0xa5)." I
> can open the port and ask for the first byte (line 5 below). I indeed
> receive the header character, so I know something is happening (line 6
> prints '0xa5' to stdout). The docs say the device will wait on the PC for
> an acknowledgement. I believe this is working. Line 9 causes the device
> to beep. 
> 
> First question: From the docs, "Valid acknowledge signals shall be one
> byte values in the range of 0x01 to 0xFE." So, is line nine the way to
> send a valid 0x01? I assume yes (why else would it beep? <grin>)

Below you are sending the hex() of a number, which results in a multi-
byte(character) ASCII string, not a single byte binary string to be sent.
You might be getting the beep because the first byte written is 48, not 1.

The difference is that hex(1) gives a string of three bytes '0'(48),
'x'(120), '1'(49).  But the single byte string is '\001'(1).  The number
in parenthises is the ASCII (ISO-8859-1) value returned by ord().

Python provides a chr() function that creates the ASCII character for
a given value.

>>> chr(1)   # the binary 1, ASCII SOA
'\001'
>>> chr(32)  # space
' '
>>> chr(48)  # the ASCII zero numeral, but not the integer 0
'0'

> The device waits 200 milliseconds to adjust the baud rate, then sends
> either a 1 or a 2. Here's where I get really confused. How do I get the
> next value? Line 10 begins a for loop. I read 1 byte from the port,
> looping 10 times. I would expect to see either a 1 or a 2, but instead I
> usually get a series of 0's.

You can sleep for a number of milliseconds by using a float with the
"sleep" function in the "time" module.

>>> import time
>>> sleep_howlong = 0.200 # seconds, or 200 milliseconds
>>> time.sleep(sleep_howlong)

> My read of the docs is that it will just dump bytes at this point, then
> wait on a checksum. I don't think I'm getting anything to calculate a
> checksum on!
> 
> My COM1 buffers are set to the minimum, so I don't think I'm losing data
> in there. Is there something about my read method that isn't correct?
> 
> Thanks a 0xf4240,
> 
> Bill
> ==============================
> 
> (port setup stuff above...)
> ...
>  1    #read some data
>  2    try:
>  3        # read the first byte; should be 0xa5 in hex
>  4        # delivered as an octal
>  5        header = port.read(1, timed=1)
>  6        print hex(ord(header[0]))
>  7        if '0xa5' == hex(ord(header[0])):
#Just test with (use the hex character ('\xa5' with Python 2.1):
            if '\245' == header[0]:  # the octal value of 0xa5

>  8            # send an achnowlegement. now what?
>  9            port.write(hex(1))
#Use the binary character instead:
                port.write(chr(1))

> 10            for i in range(1,11):
> 11                byte = port.read(1, timed=1)
> 12                blocks.append(byte)
#Sleep here, then read ten bytes:
                time.sleep(0.2) # sleep for 200 milliseconds
                bytes = port.read(10, timed=1)
                blocks = list(bytes)

> 13        print blocks
> 14        port.close()
> 15    except:
> 16        port.close()
> 17        traceback.print_exc()
> 18        return None

Good luck - I can't test any of this of course, I don't have a device
to test it on or the "serial" module you speak of (or the OS).  But if
it doesn't work, I'm sure someone will correct me. :)

  -Arcege


-- 
+----------------------------------+-----------------------------------+
| Michael P. Reilly                | arcege@speakeasy.net              |