Advertisement
Guest User

Simple modbus code in python.

a guest
Mar 23rd, 2016
457
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 1.99 KB | None | 0 0
  1. #!/usr/bin/python3
  2. import serial
  3. import crcmod  # pip install --user crcmod
  4. import struct
  5. import binascii
  6. import time
  7.  
  8.  
  9. _modbus_crc = crc = crcmod.Crc(poly=0x18005)
  10. def modbus_crc(frame) :
  11.     '''Generate the modbus CRC for given frame (without the CRC) as bytes().'''
  12.     crc = _modbus_crc.new()
  13.     crc.update(frame)
  14.     # CRC returned in *LITTLE* endian, unless usual modbus
  15.     return struct.pack('<H',crc.crcValue)
  16.  
  17. def request_frame(unit, function, register, length) :
  18.     '''Generate a modbus request frame.'''
  19.     payload = struct.pack('>BBHH', unit, function, register, length)
  20.     return payload + modbus_crc(payload)
  21.  
  22. def error(what, msg, ret) :
  23.     def ascii(raw) :
  24.         return str(binascii.hexlify(raw), 'ascii')
  25.     print(what)
  26.     print('Frame sent:      (%2d byte) %s'%(len(msg),ascii(msg)))
  27.     print('Answer received: (%2d byte) %s'%(len(ret),ascii(ret)))
  28.  
  29. def modbus_request(dev, unit, fct, reg, nregs) :
  30.     # generate request frame, send to serial port
  31.     msg = request_frame(unit, fct, reg, nregs)
  32.     dev.write(msg)
  33.  
  34.     # request max of 1024 bytes, but only wait up to timeout (0.2sec)
  35.     ret = dev.read(1024)
  36.  
  37.     # check returned packet for
  38.     if len(ret) < 5 or (ret[-2:] != modbus_crc(ret[0:-2])) :
  39.         error('Short message, or wrong CRC in answer.', ret, msg)
  40.         return None
  41.  
  42.     if ret[0] != unit or ret[1] != fct :
  43.         error('Reply has wrong unit of function.', ret, msg)
  44.         return None
  45.  
  46.     return ret[3:-2] # only return payload
  47.  
  48. # open serial port
  49. dev = serial.Serial('/dev/ttyUSB0', 9600, stopbits=2, parity='N', timeout=0.2)
  50.  
  51. # query these registers, for a 1 phase meter, returns 2 16-bit values, which,
  52. # when concatenated, correspond to a 32bit IEEE float.
  53. for reg in 0x00, 0x06, 0x0c, 0x12, 0x18, 0x1e, 0x24, 0x46 :
  54.  
  55.     payload = modbus_request(dev, unit=1, fct=4, reg=reg, nregs=2)
  56.     if payload is None :
  57.         continue
  58.  
  59.     v = struct.unpack('>f', payload)[0]
  60.     print('Float register %04x is %f.'%(reg, v))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement