PyModbus / twisted relationship + working example code

5,612 views
Skip to first unread message

estomax

unread,
Oct 20, 2011, 10:27:40 AM10/20/11
to pymodbus
Hey Everyone,

I have been trying to figure out how to use pymodbus for a while now
but using the examples have only been able to figure out how to write
to a register on a modbus/tcp device, but not read a register. Then i
stumbled into the google groups page here and found a simple example
problem posted here http://groups.google.com/group/pymodbus/browse_thread/thread/beacc3a72dac9ae7

I used this as a base and built my own modbus read/write program while
ignoring all the example code that came with PyModbus. This simple
code works great and if you want to simply use PyModbus as a tool this
is all you need. I will post my code at the end of my message. I am
using a tri-plc nano as the modbus server that i write to / read from.
Hopefully this will save someone days of frustration trying to
understand PyModbus!

My question now is, could someone explain to me why there is all the
twisted reactor code in the examples if it is not really required
(seemingly)? I am fairly new to python so please excuse my ignorance
if it's something obvious :)

Regards,
Marko
______________________________
#!/usr/bin/env python

from pymodbus.client.sync import ModbusTcpClient as ModbusClient

#assign modbus server connection
TRIPLC = ModbusClient(host='192.168.1.5', port=502)

#send write command to modbus server
#this writes a list of values to consecutive registers
#starting with a register you specify
#syntax: write_registers(register, values*len(values))
#register 1000 = DM[1], 1001 = DM[2] etc
setVals = [ 111 , 222 , 333 , 444 , 555]
register = 1000
TRIPLC.write_registers(register, setVals*len(setVals))

#send a single register write command to modbus server
setVal = 555
register = 1010
TRIPLC.write_register(register, setVal)

#send read command to modbus server
#syntax: read_holding_registers(register, #of registers)
#rr1 reads the multi register write result, rr2 reads single reg
rr1 = TRIPLC.read_holding_registers(1000, len(setVals))
rr2 = TRIPLC.read_holding_registers(1010, 1)

#getRegister is an attribute of pyModbus read_holding_registers method
currentVals = range( len(setVals) )
for i in range( len( setVals ) ) :
currentVals[i] = rr1.getRegister(i)

currentVal = rr2.getRegister(0)

#the below 5 lines are just some result code that you can see in your
command prompt
print currentVals
if (setVals == currentVals) & (setVal == currentVal):
print "successful write"
else:
print "write failed"

Bashwork

unread,
Oct 20, 2011, 10:47:08 AM10/20/11
to pymodbus
Marko,

Pymodbus actually has two implementations: a high performance
asynchronous one and threaded synchronous one. This gives users the
ability to use the protocol to serve their specific needs. When
writing basic applications such as yours, a great deal of power is not
necessarily needed. So for this case we provided the synchronous
version with no added dependencies (except for pyserial). However,
the original use case for this library was to simulate thousands of
modbus devices on a network to load test commercial data center
monitoring software. For this case the off the shelve implementation
simply would not scale. This is why Twisted is used.

As for the examples, I have tried to provide a number of examples
showing how to create synchronous and asynchronous versions of various
use cases. From my point of view, the synchronous examples are about
as simple as they can get, however, if there is anything I can do to
make the learning curve easier, please let me know.

Galen

On Oct 20, 9:27 am, estomax <esto...@gmail.com> wrote:
> Hey Everyone,
>
> I have been trying to figure out how to use pymodbus for a while now
> but using the examples have only been able to figure out how to write
> to a register on a modbus/tcp device, but not read a register. Then i
> stumbled into the google groups page here and found a simple example
> problem posted herehttp://groups.google.com/group/pymodbus/browse_thread/thread/beacc3a7...

estomax

unread,
Oct 20, 2011, 1:15:20 PM10/20/11
to pymodbus
Thanks for the reply

I think the most confusing part of the asynchronous example (which is
what I worked with), is that i could not get the getRegister function
to spit out any data that i was reading back using the
read_holding_registers function. If you added some print getRegister
functionality into the example i think that would be of great use,
because most people will be wanted to write data (which i was able to
do) and also read it back and work with it (which i wasn't able to do
in the asynchronous example). Also, the dassert functions where you
test the expected value appeared to do nothing for me. when the
register i wrote did not equal what the dassert was comparing, there
was no error in the command prompt, nor a confirmation when it did
equal.

The other main issue is that i am not familiar with Twisted yet so i
need to understand that more thoroughly, nothing you can do there :)

Marko
> >    print "write failed"- Hide quoted text -
>
> - Show quoted text -

Bashwork

unread,
Oct 20, 2011, 1:28:49 PM10/20/11
to pymodbus
It sounds like you may not understand the twisted design, especially
the deferred callbacks. For your cases, simply keep using the
synchronous versions of the library and if you are interested in
learning more, feel free to read a bit about twisted:

http://ezyang.com/twisted/defer2.html

Galen

Albert Brandl

unread,
Oct 21, 2011, 3:37:43 AM10/21/11
to pymo...@googlegroups.com
Hi!


On Thu, Oct 20, 2011 at 07:27:40AM -0700, estomax wrote:
> My question now is, could someone explain to me why there is all the
> twisted reactor code in the examples if it is not really required
> (seemingly)? I am fairly new to python so please excuse my ignorance
> if it's something obvious :)

In one of our applications, we gather information from various sources,
archive them, and forward them to an SPS using pyModbus. The SPS sends
back some more information, which is again archived.

This is a perfect job for Twisted, since most protocols necessary for
information retrieval and storage are already available. Having the
pyModbus API available was a big advantage, since it allows us to just
"plug in" the code necessary to communicate with the SPS (using both
the serial line and TCP/IP).

For "trivial" applications, it's good to have synchronous versions of
pyModbus clients and servers. But as soon as things get more complex
(e.g., you want to have a GUI for your application, or you have to
interact with a database engine), it will definitely pay off to learn
Twisted.

Best regards,
--
Albert Brandl | Weiermayer Solutions GmbH




A-4813 Altmünster - Abteistraße 12 - web: www.weiermayer.com - phone: +43761287677 - fax: +43761220356 - mobile: +436642442777

Dariusz Maćkowiak

unread,
Nov 30, 2012, 7:00:08 PM11/30/12
to pymo...@googlegroups.com


On Thursday, October 20, 2011 4:27:40 PM UTC+2, estomax wrote:

currentVal = rr2.getRegister(0)



Hi guys,

I have tried those examples on win7 64 and Linux and I have failed, my python skills are low but this post is the simplest example I have found,  (the pymodbus docs are too complicated for beginners like me)
 
The problem I have is that 
rr2.getRegisters(0) 
gives me an error 

  File "modbus.py", line 21, in test
    print rr.getRegister(0)
AttributeError: 'NoneType' object has no attribute 'getRegister'

The device I connect to and retrieve register values have been proven to work with modpoll and nmodbus C#, also the client.connect() returns true
My test code looks like this

 
from pymodbus.client.sync import ModbusSerialClient as ModbusClient

def test():
client = ModbusClient(method='ascii',
port='/dev/ttyUSB1', 
stopbits=1,
bytesize=8,
parity='E',
baudrate=9600)
testConn = client.connect()
print testConn # this returns true
rr = client.read_holding_registers(1710,1)
regValue = rr.getRegister(0) # here i  get the error 

I am stuck, any help is highly appreciated

Darek

Darek

unread,
Dec 1, 2012, 6:10:52 AM12/1/12
to pymo...@googlegroups.com


On Saturday, December 1, 2012 1:00:08 AM UTC+1, Darek wrote:


On Thursday, October 20, 2011 4:27:40 PM UTC+2, estomax wrote:

currentVal = rr2.getRegister(0)




def test():
client = ModbusClient(method='ascii',
port='/dev/ttyUSB1', 
stopbits=1,
bytesize=8,
parity='E',
baudrate=9600)
testConn = client.connect()
print testConn # this returns true
rr = client.read_holding_registers(1710,1)
regValue = rr.getRegister(0) # here i  get the error 


Ok, I have found the problem, the read_holding_registers syntax for ModbusSerialClient is now
read_holding_registers(register_No, count=Number_of_registers_to_read, unit=Slave-Id)

so it works after changing the code to

rr = client.read_holding_registers(1710,count=1,unit=1)

Sorry for those posts but people like me need explicit examples 

Darek

   
 

Pablo Andrés

unread,
Nov 30, 2013, 5:39:57 PM11/30/13
to pymo...@googlegroups.com
Hi
I have the same problem that Darek, my code is the following:
{{{
##!/usr/bin/env python
from pymodbus.client.sync import ModbusSerialClient as MB
import serial
#---------------------------------------------------------------------------#
# configure the client logging
#---------------------------------------------------------------------------#
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
client = MB(method='rtu',port='/dev/ttyAMA0',stopbits=1,bytesize=8,parity=serial.PARITY_ODD,baudrate=9600,timeout=0.1)
client.connect()
while True:
  rr=client.read_holding_registers(address=0,count=2,unit=45)
  print rr.getRegisters(0)}}}
The class ReadRegistersResponseBase  always call the __str__ method, how to I "getRegisters()" or call this method?

Regards, Pablo.

Dinos Gonatas

unread,
Jan 10, 2017, 2:16:36 PM1/10/17
to pymodbus
Hello, this turned up when searching for 'Pymodbus for Dummies.' I echo the commenter below - I can't figure out how to set this up from the 'examples.' Is there some basic out there to read because I don't understand
- does the 'client code have to be running on the slave and the 'server' on the master?? What's the overall architecture?
- what's better, the 'synchronous' or 'asynchronous' and what's the difference?

especially, in addition to examples, documentation that tells you WHAT modbus commands you have to run to set up your device. What the different commands are for and what their arguments (and returned values) mean/ have to be. Thanks!!
Reply all
Reply to author
Forward
0 new messages