serial to OSX via python

Discussion in 'Mac Programming' started by Martster, Nov 22, 2008.

  1. Martster macrumors newbie

    Joined:
    Feb 9, 2008
    Location:
    Van Diemen's Land
    #1
    Hi, I'm an artist who uses programming in multimedia work. I have limited experience with python and with java. At the moment i'm trying to get data from a weather meter to use as input for an animation. The device has two optical ports on the back, and when in 'download mode' sits in a cradle (with electronics inside) that has a serial output. I have a Keyspan USA-19HS attached to the serial port, and plugged into my Santa Rosa MBP via usb port.

    I have been given authorised access to a copy of the protocol that the unit uses. It uses an ASCII protocol and comma separated output values. It operates at 9600 baud, 8 bit data, 1 stop bit and no parity. Full duplex. No hardware or software handshaking.

    I'm wondering if pySerial is the right approach in order to set up a connection via the terminal and send the unit the right signal to download the logged data?

    any comments and advice would be greatly appreciated,

    cheers

    Mart
     
  2. Bakerman macrumors member

    Joined:
    Jan 31, 2005
    Location:
    Sweden
    #2
    While you will need the serial protocol, you'll also need a driver for the chip in the Keyspan USA-19HS. Many USB to serial converters are based on the FTDI series of chips (http://www.ftdichip.com/) and a generic driver from them can often be used.

    Drivers for USB<->serial converters generally fall into two camps: either they provide a quasi-serialport interface to user-level apps, or they have a custom (but usually more efficient) interface. If the driver you find for the Keyspan USA-19HS falls into the first category, then using pySerial should be fine. Otherwise, you'll need to do some more hacking to access the API of the driver from within Python.
     
  3. Martster thread starter macrumors newbie

    Joined:
    Feb 9, 2008
    Location:
    Van Diemen's Land
    #3
    Thanks Bakerman. The Keyspan USA-19HS came with an OSX driver, and the installed 'Keyspan Serial Assistant' application shows the correct info for the device. I ran some quick tests with pySerial from the terminal and was able to open a port and seem to be able to write to the device, however when I use ser.readline() the device returns a blank line to the terminal. These are the commands i was using in the python interpreter;

    >>> import serial
    >>> ser = serial.Serial('/dev/cu.USA19H1d1P1.1', 9600, timeout=1)
    #Open named port at "9600,8,N,1", 1s timeout::

    >>> line = ser.readline() #read a '\n' terminated line

    The instructions for the protocol say that the device should download the data log upon receiving the command 'B'. I am obviously missing something here, but am not sure what to do next.

    thanks again for your help so far : )
     
  4. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    I'm just making this up, but perhaps:
    Code:
    ser.writeline('B')
    would get you going? Then you can read the response? Is there some sequence that you can be looking for to let you know the device is done transmitting?

    -Lee
     
  5. Martster thread starter macrumors newbie

    Joined:
    Feb 9, 2008
    Location:
    Van Diemen's Land
    #5
    Thanks Lee,

    I have an open port and a connection to the device
    (I have tested this by removing the device when the port is open
    and it hangs until the device is replaced)

    I seem to be able to write to the device using
    Code:
    ser.write('B')
    the problem is all I get back is
    Code:
    >>> ' '
    (an empty tuple perhaps?)
    if i use either
    Code:
    ser.read()
    ser.read(20)
    or
    Code:
    >>> []
    (i guess thats an empty array)
    when I use
    Code:
    ser.readlines()
    am not sure where to go from here,
    python uses utf-8, so the 'B' should be valid ASCII
    do you think I should add a CR and NL to my 'B' ?

    any other suggestions greatly appreciated

    thanks

    Mart
     
  6. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #6
    Did you try a flushOutput on ser after your write? Maybe the B was buffered?

    -Lee
     
  7. Bakerman macrumors member

    Joined:
    Jan 31, 2005
    Location:
    Sweden
    #7
    I would definetly try different variations of line termination. Send 0x0 or 0x13 or 0x10 or 0x13 0x10, there is unfortunately no single universal standard here. No termination at all is also possible, but you already tried that..
     
  8. Martster thread starter macrumors newbie

    Joined:
    Feb 9, 2008
    Location:
    Van Diemen's Land
    #8
    Thanks again for your input Bakerman.
    Here is a sample of my terminal session.

    Code:
    >>> import serial
    >>> ser = serial.Serial('/dev/cu.USA19H1d1P1.1', 9600, timeout=1)
    >>> ser.inWaiting()
    0
    >>> ser.flushInput()
    >>> ser.flushOutput()
    >>> 
    >>> 
    >>> 
    >>> 
    >>> 
    >>> 
    >>> 
    >>> ser.write('B0x0')
    >>> ser.read(100)
    ''
    >>> ser.write('B0x13')
    >>> ser.read(100)
    ''
    >>> ser.read()
    ''
    >>> ser.readlines()
    []
    >>> ser.write('B0x10')
    >>> ser.read(100)
    ''
    >>> ser.write('B0x130x10')
    >>> ser.read(100)
    ''
    >>> ser.readlines()
    []
    >>> ser.write("B0x130x10")
    >>> ser.read(100)
    ''
    >>> 


    Do you think I'm on the right track? I'm not at all familiar with the way serial ports handle input and output, let alone that of the Kestrel 4500 weather meter I'm trying to talk to.

    Am interested to know what format your line terminations are in. Should my 'B' be in that format too?

    tnx

    Mart
     
  9. Bakerman macrumors member

    Joined:
    Jan 31, 2005
    Location:
    Sweden
    #9
    'B0x13' should be 'B\x13'? It is supposed to be a two-character string, not five characters. Same goes for all the others.
     
  10. Sayer macrumors 6502a

    Sayer

    Joined:
    Jan 4, 2002
    Location:
    Austin, TX
    #10
    A one second timeout for a 9600 baud serial device is kinda low, try setting the timeout to 5 seconds and sending only a "B" and see if that works.
     
  11. Martster thread starter macrumors newbie

    Joined:
    Feb 9, 2008
    Location:
    Van Diemen's Land
    #11
    Tnx Sayer,

    but still no success, results below:

    Code:
    >>> import serial
    >>> ser = serial.Serial('/dev/cu.USA19H1d1P1.1', 9600, timeout=5)
    >>> ser.write("B")
    >>> ser.read(10)
    ''
    >>> print ser
    Serial<id=0x753590, open=True>(port='/dev/cu.USA19H1d1P1.1', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=5, xonxoff=0, rtscts=0, dsrdtr=0)
    >>> x = ser.readlines()
    >>> print x
    []
    >>> ser.timeout = 10
    >>> ser.write("B")
    >>> ser.read(100)
    ''
    >>> ser.write('I?')
    >>> x =  ser.readlines()
    >>> print x
    []
    >>> ser.timeout = 15
    >>> ser
    Serial<id=0x753590, open=True>(port='/dev/cu.USA19H1d1P1.1', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=15, xonxoff=0, rtscts=0, dsrdtr=0)
    >>> ser.write("I?")
    >>> ser.read() 
    ''
    >>> ser.flushInput()
    >>> ser.flushOutput()
    >>> ser.write("I?")
    >>> ser.readline()
    ''
    >>> x = ser.readline()
    >>> print x
    
    >>> 
    Ive been doing some research to try to figure what kind of microprocessor is in it, as I hope that might give me some more info. I think its a PIC16F87XAC made by Microchip, but will try to confirm that with the national tech support for the device.

    thanks for your input :apple:

    Marty
     
  12. Bakerman macrumors member

    Joined:
    Jan 31, 2005
    Location:
    Sweden
    #12
    Have you tried
    Code:
    >>> ser.write("B\x13")
    >>> ser.write("B\x10")
    >>> ser.write("B\x13\x10")
    >>> ser.write("B\x00")
    
    ?
     
  13. Cromulent macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #13
    Sometimes with protocols you need to send the correct line / carriage returns as well. So it would be B\n or B\r\n that you need to send rather than just B.

    Just an idea.
     
  14. Martster thread starter macrumors newbie

    Joined:
    Feb 9, 2008
    Location:
    Van Diemen's Land
    #14
    Success and many thanks

    Hi Cromulent, Bakerman and Sayer;

    thanks all of you for helping me out with my puzzle.
    The last bit fell into place with Crom's suggestion re \r\n.
    Tried a few combos and \r was the key. Awesome, now I can access the data in raw form without having to deal with a non-mac operating system or the gigabytes of guff that it would entail.

    Also this approach will give me access to polled data in real time, which the standard "communicator" app does not allow. So thanks again for all the help :)

    Mart







    Here is the Python session for the protocol that works:

    Code:
    >>> ser = serial.Serial('/dev/cu.USA19H1d1P1.1', 9600, timeout=5)
    >>> ser
    Serial<id=0x753dd0, open=True>(port='/dev/cu.USA19H1d1P1.1', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=5, xonxoff=0, rtscts=0, dsrdtr=0)
    >>> ser.write('I?\r')
    >>> ser.readlines()
    ['I?\r\n', 'Iss 4.29   All\r\n', 'Status=0\r\n', 'RH cal 1: 01/00/2008 05:02:33\r\n', 'RH cal 2: 01/00/2008 20:35:44\r\n', 'T2_correct: 83789846\r\n', 'K4500\r\n', '> ']
    >>> ser.write('B\r')
    >>> ser.readlines()
    ['B\r\n', '> DT,MG,TR,WS,CW,HW,TP,WC,RH,HI,DP,WB,BP,AL,DA\r\n', 's,Mag,True,km/h,km/h,km/h,\xb0C,\xb0C,%,\xb0C,\xb0C,\xb0C,hPa,m,m\r\n', '280683000,---,---,0.0,0.0,0.0,21.1,21.1,58.6,20.9,12.7,15.8,983.0,251,588\r\n', '280683600,125,125,0.0,0.0,0.0,19.9,19.9,54.9,19.0,10.5,14.2,983.3,249,534\r\n',  etc, etc 
     
  15. Cromulent macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #15
    Excellent. Glad to hear you got it sorted.
     

Share This Page