On Sun, May 22, 2011 at 11:59:04PM -0700, Darryl wrote:
> Basically, I want to poll a modbus device for several Holding
> Registers in one case, and several coils in another case, and send
> this data out a TCP connection via Twisted.
Will this polling be done in a cyclic fashion?
> The second part with TCP is easy. I cannot work out how to do the pymodbus
> bit of this. Later I will need to also write coils based on TCP input and
> coil value changes.
You'll have to connect the Modbus clien and the TCP part in some way.
> Any assistance with this would be really appreciated. The issue is
> that most of the examples assume a standalone program, and also assume
> TCP, which makes things harder to work out
Have a look at the attached example script. I am not sure if it works
out of the box, since I have no serial RTU server available right now.
If it does not work, the errors are most likely in the definition of
the SerialModbusClient or the main() function.
The logic of MyProtocol might be simplified. The protocol fetches the
holding registers first, and waits for the response before fetching
the coils. You might be able to collect the methods into one, but
some devices don't like too quick polling and start reacting in a
strange way.
The LineReader class is a dummy that just prints the values received
from the device. You can replace it with your instance of the TCP
protocol where you want to send the data (and use the appropriate
method instead of write()).
If you have any questions, feel free to ask them.
Best regards,
--
Albert Brandl
Weiermayer Solutions GmbH | Abteistra�e 12, A-4813 Altm�nster
phone: +43 (0) 720 70 30 14 | fax: +43 (0) 7612 20 3 56
web: http://www.weiermayer.com
That is right. Some units only work if addressed with the correct ID;
others are less picky.
> Printing response.bits will show me the state of all the 16 coils that
> I retrieved.
You should probably try not depend on the existence of this attribute
and use the getBit() method instead.
> At the moment, if I try to do a self.read from a unit that is not
> there (temporarily or permanently), the code hangs. Some idea on how
> to deal with that would definitely help.
Right now, the callback is never called, since the method for fetching
holding registers or coils does not finish.
How about updating a timestamp each time you receive data from the unit?
You could then add a "watchdog" that is called periodically and restarts
the connection if the timestamp is too old.
> But this has helped so much - so much that I think I will be able to
> soon ditch modbus-tk :-)
The Twisted integration of pymodbus is definitely better...
Regards,
On Wed, May 25, 2011 at 06:46:26PM -0700, Darryl wrote:
> Anyway, my code fragment appears below
Thanks for sharing :-).
> def timeout(self):
> print "Timeout!!!"
> reactor.callLater(10, self.fetch)
I'm not sure that this will work. We had a similar case, where our SPS
went offline and later reappeared. But Twisted didn't manage to use the
previously broken serial connection again. You can easily check this by
unplugging the serial line, waiting for some seconds and plugging it in
again.
The only way I found to reestablish communication was to terminate the
client and restart it again. This should be triggered from outside the
client.
Maybe you can add a timestamp that is updated each time you read data.
If you have a method that checks the up-to-dateness of the timestamps
(one for every client), you can create a function that calls this
method, and restarts the client if necessary - similar to your timeout
method above.
Best regards,