How to Write (Update the values) into registers via modbus in python

P

Thread Starter

Praful Bagai

I'm able to read the register value in modbus using 03 as the function code. and moreover I'm also able to re-write the currently existing value with the same value which is inside the register via Modbus protocol. but when I try to modify the contents of the register, it raises an error saying socket.timeout: timed out. How can I modify the contents of a register via Modbus protocol?

Here is the code.<pre>
import struct
import binascii
import socket
import time
import sys
class main:
def __init__(self):
self.server_socket = ''

def send_packet(self):
self.server_socket = socket.create_connection(('192.168.1.51', 5050), 0.4)
message=struct.pack('>BBHHBBBBBBB',14,16,295,3,6,0,1,48,0,56,21) //(slaveid,function_code,register_address,quantity of registers,total bytes, values....)
message += struct.pack('>H',self.computeCRC(message))

message_hex = binascii.b2a_hex(message)
message_bcd = ''.join('{0:04b}'.format(int(char)) for char in str(int(output_hex, 16)))
print message_hex
print message_bcd

self.server_socket.send(message)

res = self.server_socket.recv(1024)
print binascii.b2a_hex(res)

def computeCRC(self,data):
result = []
for byte in range(256):
crc = 0x0000
for _ in range(8):
if (byte ^ crc) & 0x0001:
crc = (crc >> 1) ^ 0xa001
else: crc >>= 1
byte >>= 1
result.append(crc)

crc = 0xffff
for a in data:
idx = result[(crc ^ ord(a)) & 0xff];
crc = ((crc >> 8) & 0xff) ^ idx
swapped = ((crc << 8) & 0xff00) | ((crc >> 8) & 0x00ff)
return swapped


obj = main()

obj.send_packet()</pre>
 
('>BBHHBBBBBBB',14,16,295,3,6,0,1,48,0,56,21)
>//(slaveid,function_code,register_address,quantity
>of registers,total bytes, values....)

The "quantity of registers" appears to be 6 which would result in a "byte count" of 12 where as you have a byte count of 1 AND there are only 4 bytes of actual data.

Four bytes of data implies you may be trying to send QTY 1 IEEE Single Precision Float Value. BUT, the only float value I can see is 0.000355569 (0x38 15 30 00). Even so, it may be 1 float value BUT it still needs to be sized as 4 bytes in ModBus.
 
L

Lynn August Linse

I would add as a general comment on writing work-station code like Python - make sure the serial doesn't open default with flow-control enabled. For example I had an experience where a customer had XON/OFF enabled, meaning receiving 1 of 256 binary values caused the serial port to stop sending data.

the symptom was the customer could read and write a dozen different values, but 1 specific register would cause the program to stop working ... it just turned out that this particular register value included an XOFF byte which stopped the PC from sending any more Modbus requests! If they stopped their program, it could be run again because 'closing' the serial port reset the XON/XOFF state.
 
R

Rufus V. Smith

Presumably the socket.timeout error is on the .recv() call, and not the connect or write, correct?

If there was a timeout on the receive, it means the slave did not receive what it considered a valid message, so it didn't answer. This can be due to bad slave addressing, bad packet length, bad crc.

Since you are able to read out registers, your crc generation works okay, and you are specifying the correct slave address. So the answer Harvard gave you about packet length may be the key.

(A hint for people developing protocols like this, is to run several different pieces of test data through your own encoder and decoders and ensure that what comes back is what you sent! e.g.:<pre>
if mytestdata != mydecoder(myencoder(mytestdata)):
raise Exception("Problem in encode or decode!"</pre>
It doesn't guarantee your algorithms are correct, but at least they are consistent!)
 
Top