Example: Write Modbus RTU multimeter values to KNX/EIB bus group addresses


Read two parameters (3-phase system voltage, 3-phase system current) from ABB DMTME Multimeter and store the data in the KNX group addresses. Make sure to connect LM2 with Modbus device correctly, RS485 A with -, RS485 B with +.

Adding KNX objects

In Objects tab two new KNX objects should be added. In this case:

Modbus program

Source code    
  1. -- init modbus on first script execution
  2. if not mb then
  3. require('luamodbus')
  4. mb = luamodbus.rtu()
  5. mb:open('/dev/ttyS2', 9600, 'E', 8, 1, 'H')
  6. mb:connect()
  7. end
  9. -- sets slave ID to read/write data from/to
  10. mb:setslave(20)
  12. -- read 3-phase system voltage from 32-bit register
  13. r1, r2 = mb:readregisters(0x1000, 2)
  14. result = bit.lshift(r1, 16) + r2
  15. grp.write('5/5/1',result)
  17. -- read 3-phase system current from 32-bit register
  18. r1, r2 = mb:readregisters(0x100E, 2)
  19. result = bit.lshift(r1, 16) + r2
  20. grp.write('5/5/2',result)


Note! Modbus data is most often read and written as 16-bit registers. If a 32-bit is required, these values have to be read as a pair of registers, like in this example.

Note! All data addresses in Modbus messages are referenced to zero. The first occurrence of a data item is addressed as item number zero. For example: The coil known as ‘coil 1’ in a programmable controller is addressed as coil 0000 in the data address field of a Modbus message.

Read encoded Modbus values

To read and decode 32bit float value from Modbus meter use this example

Source code    
  1. r1, r2 = mb:readregisters(3000, 2)
  3. if r1 then
  4. value = bit.lshift(r1, 16) + r2
  5. value = lmcore.inttohex(value, 4)
  6. value = knxdatatype.decode(value, dt.float32)
  8. grp.write('5/5/1', value)
  9. end

Visualizing Modbus objects

By using grp.write command assign Modbus object to KNX object and then use this new KNX object in the visualization.

More Modbus communication commands

  • Open Modbus TCP connection:
Source code    
  1. if not mb then
  2. require('luamodbus')
  3. mb = luamodbus.tcp()
  4. mb:open('', 1502)
  5. mb:connect()
  6. end
  • Reads count registers/coils from the start address and return all values on success and nil, error description on error:
Source code    
  1. mb:readcoils(start, count)
  2. mb:readdiscreteinputs(start, count)
  3. mb:readregisters(start, count)
  4. mb:readinputregisters(start, count)
  • Write values to registers/coils from the start address. Single write will be used when only one value is supplied, multiple write otherwise. Returns all of values written on success and nil, error description on error:
Source code    
  1. mb:writebits(start, v1, [v2, [v3, ...]])
  2. mb:writeregisters(start, v1, [v2, [v3, ...]])
  • Read slave internal data. Returns values on success and nil, error description on error:
Source code    
  1. mb:reportslaveid()