0

Warning - total beginner with Modbus and industrial control in general... Sorry for any incorrect terminology/etc. in advance!

I've got a project using a Beckhoff BK9000/BK9100 ethernet coupler and I need to check the states of up to six digital outputs (KL2602 modules) and also turn those same six outputs on/off depending on some logic.

I know that the unit works and is at the IP specified, as I'm able to see it in TwinCat3 and manually manipulate the outputs.

I've been trying to use the following code:

from pyModbusTCP.client import ModbusClient

SERVER_HOST = "172.16.17.32"
SERVER_PORT = 502

# TCP auto connect on modbus request, close after it
c = ModbusClient(host=SERVER_HOST, port=SERVER_PORT, auto_open=True, auto_close=True)

for i in range(4):
    print(str(i) + str(c.read_coils(i,16)))

status = c.write_single_coil(0, False)
print(status)

for i in range(4):
    print(str(i) + str(c.read_coils(i,16)))

When I do this, I can see that the True/False for coil '0' correspond to the various output states that I set manually using TwinCat3. There are six outputs manually set high, visible here:

0[True, True, True, True, True, True, True, True, False, False, False, False, False, False, False, False]
1[True, True, True, True, True, True, True, False, False, False, False, False, False, False, False, False]
2[True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False]
3[True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False]

It appears that when I increment the 'coil' it's just reading one bit further into the stream, as "coil" 1, 2, and 3 are rotating left.

However, I still cannot seem to change the values. I do hear a mystery relay click when setting coil '0' to False (but no click on true) and the status of the coil reads does not change. TwinCat is also showing no change. I'm getting a "None" back from the write, which indicates it's failing according to the module's documentation.

0[True, True, True, True, True, True, True, True, False, False, False, False, False, False, False, False]
1[True, True, True, True, True, True, True, False, False, False, False, False, False, False, False, False]
2[True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False]
3[True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False]
None
0[True, True, True, True, True, True, True, True, False, False, False, False, False, False, False, False]
1[True, True, True, True, True, True, True, False, False, False, False, False, False, False, False, False]
2[True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False]
3[True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False]

I'm sure this is something simple with bit-wise operations or something like that which I'm overlooking. Any ideas on what I'm doing wrong that causing the writes to fail?

  • It's unclear to me if you can set the coil state with twincat or not. If not then I'd look at the controller manual/settings. – intrepidhero Nov 21 '16 at 19:31
  • Also, have you tried enabling the [debug mode](https://pythonhosted.org/pyModbusTCP/quickstart/index.html#modbusclient-debug-mode) to see if it provides any useful feedback? You also might try capturing the traffic in Wireshark - it should decode Modbus/TCP and might be easier to follow than Modbus frame data from Python. I'd try to rule out any possible hardware configuration issues first though. – thephez Nov 21 '16 at 19:49
  • I'll definitely check-out debug mode and Wireshark if nothing else pops-up. As far as I can tell, the hardware is working fine - I can fully control it via TwinCat3, either through a soft PLC or manually right-clicking and setting the outputs to 1 or 0. I also have two units (BK9000 at home and BK9100 at work) and both exhibit the same behavior. – user2726921 Nov 21 '16 at 20:07
  • FYI - the `read_coils` command is just incrementing as you suspected. The first parameter of the method is which bit to start reading at and the second parameter is the number of bits to read. So your loop is reading bits [0..15], then [1..16], then [2..17], etc. – thephez Nov 21 '16 at 21:39

1 Answers1

2

I'm total beginner with Beckhoff PLCs ;), but I'm pretty sure that the bit address is wrong. bit_addr is not the same as output number of the module. You should be able to get it from somewhere, e.g. from module discovery and configuration utility.

From pyModbusTCP.client documentation:

write_single_coil(bit_addr, bit_value)

Parameters:   
bit_addr (int) – bit address (0 to 65535)
bit_value (bool) – bit value to write
Returns:  
True if write ok or None if fail

You get the status None, i.e fail. You heard relay click because something wrong happened (plc has reset?)

BTW. you should increment coil address by 16. in your loop, like thephez wrote. Eg:

var output0addr = 0x12346789
for i in range(4):
    print(str(i) + str(c.read_coils(output0addr + (i * 16), 16)))
Community
  • 1
  • 1
Jacek Szumigaj
  • 113
  • 2
  • 8