Lynn's Industrial Protocols over IP

Monday, October 09, 2006

Using Python to query Modbus slaves

I use Python ( http://www.python.org/ ) at lot in my testing. It is a language designed to make a programmer's life easy and the computer sweat - in other words, it is an ideal tool for test scripts and maybe a bad tool for "constant use" tools.

Stock python has no serial support. For serial, you'll need some serial tool like pyserial - this hides details of OS and allows Linux (or Windows) style serial calls on either OS. A web search of pyserial will turn up a download site - such as http://pyserial.sourceforge.net/ . The "Vaults of parnassus" is another nice source for Python tools including pyserial. http://py.vaults.ca/~x/parnassus/apyllo.py/

Creating binary messages is not hard in Python, but a bit ugly. You use lots of "chr(x)" function to build up a binary string and to parse a binary response lots of "ord()". Other than that, look at the spec at http://www.blogger.com/www.modus-ida.org for details of the actual protocol.

CRC-16 for Modbus (or DF1):
Here is my CRC16 routine including a few test cases (written with no regard for CPU speed, since that is not why one uses Python).

crc16.py as a ZIP file

8 Comments:

  • Standard python struct module with pack()/unpack functions will help you to create binary messages in more elegant manner.

    http://docs.python.org/lib/module-struct.html

    By Blogger techtonik, at 4:50 AM  

  • Thanks, that's an option.

    I guess 'elegance' is in the eye of the beholder - I only use that module for reading/writing floats from a binary string since it requires "try/except" to keep it from throwing exceptions.

    It's other problem is the output of the pack isn't a real Python string, so you can't do much with it ... in fact, after I pack the float I have to convert the result to a "4-byte binary string" so it works with the rest of my code.

    By Blogger Lynn August Linse, at 7:22 AM  

  • The link to your example code no longer seems to work:
    http://www.iatips.com/crc16.py

    Is there another way to get at that code?

    By Anonymous Donald, at 1:16 PM  

  • I duplicated it to: http://www.iatips.com/crc16.zip

    I guess the server was now trying to "run" the .PY as-if a server extension. The .zip format stops this.

    By Blogger Lynn August Linse, at 1:23 PM  

  • Lynn,
    Would it be possible to post a code example of a full master to slave query? I think I understand how your crc16.py function works, but I just can't seem to get my slave device to respond to my queries. One example would save me an incredible amount of time.

    Thanks!

    By Anonymous Donald, at 11:46 AM  

  • Here is a complete 'construction' which is used in one of my real-world tests - notice how the CRC16 is appended in what I'd call little-endian form.

    st = "\x03\x03\x00\x00\x00\x0A"
    crc = crc16.calcString( st, crc16.INITIAL_MODBUS)
    st += chr(crc & 0xFF) + chr(( crc >>8) & 0xFF)

    Since I moderate comments; you can just send a 'new comment' with an email address; I'll reject it (not publish) but I can send you a few complete modbus libraries 'as-is'.

    By Blogger Lynn August Linse, at 11:55 AM  

  • I need to read/write a few int/float registers in 1+ modbus slaves from an embedded device running Linux (over the serial line).

    I wrote a Python C extension module to wrap the calls I need in libmodbus (https://launchpad.net/libmodbus), but I'm wondering if it's possible to do what I need purely in Python.

    Is this possible with your code?

    Thanks!
    Tobias

    By Blogger tobias, at 8:07 PM  

  • Hi,
    You may be interested by Modbus Test Kit which is an implementation of the Modbus protcol in Python designed with testing purpose in mind.
    I am interested by your feedback if you have a little time to play with it.

    By Blogger luc, at 1:28 PM  

Post a Comment

<< Home