This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Modbus TCP connection datakom d-200 mk2
#1
Good day!

There is an unclear problem with the Modbus TCP connection. The controller has restrictions on the number of registers requested at a time (no more than 16), and the controller can only process group requests for reading registers, the function read single registers is not supported. in this regard, I use the program code and not the modbus profiles.

Faced a very strange problem. Initially, I checked by reading the modbus pull program, when using it, I can open and close the connection many times in a row and the controller works it out correctly, but when using a fairly standard code for the logic machine, the datakom controller stops responding after several requests and even to connect the modus pull program as well does not connect. What could be the reason, did anyone come across a similar one?

description of the modus protocol for the datakom d-200 mk2  controller: http://datakom.com.tr/upload/Files/500_MODBUS.pdf

example of code i am using:

Code:
require('luamodbus')
mb = luamodbus.tcp()
mb:open('10.36.0.25', 502)
--mb:setresponsetimeout(5)
if mb:connect() then
  log('connect')
  reg10240, reg10241, reg10242, reg10243, reg10244, reg10245, reg10246 = mb:readregisters(10240,7)
  if (reg10240 ~= nil) then log('Mains phase L1 voltage: '..reg10240) end
  if (reg10242 ~= nil) then log('Mains phase L2 voltage: '..reg10242) end
  if (reg10244 ~= nil) then log('Mains phase L3 voltage: '..reg10244) end
  if (reg10246 ~= nil) then log('Genset phase L1 voltage: '..reg10246) end
os.sleep(0.5)
  reg10338, reg10339, reg10340, reg10341 = mb:readregisters(10338,4)
  if (reg10338 ~= nil) then log('Mains frequency: '..reg10338) end
  if (reg10339 ~= nil) then log('Genset frequency: '..reg10339) end
  if (reg10341 ~= nil) then log('Battery voltage: '..reg10341) end   
  mb:close()
else
  log('read error reg10240...reg10246') 
end

mb:close()

To restore communication with the controller, only its power restart helps, reconnecting the etnernet line does not remove the problem
Reply
#2
There's no "read single register" function in modbus, this only applies to writing where there are two different commands for single/multiple registers.
Keep in mind that voltage registers are 32-bit so each value consists of 2 registers. This might be why profile was not working for you.
Another thing is that you should not close the connection after each run. Profiles also support this by enabling "persistent" connection mode.

See if this works for you:
Code:
if not mb then
  require('luamodbus')
  mb = luamodbus.tcp()
  mb:open('10.36.0.25', 502)
  mb:setresponsetimeout(5)

  res, err = mb:connect()
  if not res then
    log('modbus connect failed ' .. tostring(err))
    mb:close()
    mb = nil
  end
end

if mb then
  reg10240, reg10241, reg10242, reg10243, reg10244, reg10245, reg10246, reg10247 = mb:readregisters(10240, 8)
  
  if reg10240 then
    mains_l1_voltage = reg10240 * 0x10000 + reg10241
    mains_l2_voltage = reg10242 * 0x10000 + reg10243
    mains_l3_voltage = reg10244 * 0x10000 + reg10245
    genset_l1_voltage = reg10246 * 0x10000 + reg10247
    log('voltage values', mains_l1_voltage, mains_l2_voltage, mains_l3_voltage, genset_l1_voltage)
  else
    log('modbus read failed ' .. tostring(reg10241))
    mb:close()
    mb = nil
  end
end
Reply
#3
Unfortunately, this did not help. Log after restarting the controller:

DGU_modbus_tcp 22.02.2021 20:47:47
* arg: 1
* string: voltage values
* arg: 2
* number: 157089792
* arg: 3
* number: 154992640
* arg: 4
* number: 154075136
* arg: 5
* number: 0

DGU_modbus_tcp 22.02.2021 20:47:57
* string: modbus read failed Invalid data

DGU_modbus_tcp 22.02.2021 20:48:07
* arg: 1
* string: voltage values
* arg: 2
* number: 155320320
* arg: 3
* number: 154992640
* arg: 4
* number: 155844608
* arg: 5
* number: 0

DGU_modbus_tcp 22.02.2021 20:48:18
* string: modbus read failed Invalid data

DGU_modbus_tcp 22.02.2021 20:48:28
* arg: 1
* string: voltage values
* arg: 2
* number: 154796032
* arg: 3
* number: 154599424
* arg: 4
* number: 156958720
* arg: 5
* number: 0

DGU_modbus_tcp 22.02.2021 20:48:38
* string: modbus read failed Invalid data

DGU_modbus_tcp 22.02.2021 20:48:48
* arg: 1
* string: voltage values
* arg: 2
* number: 155451392
* arg: 3
* number: 154337280
* arg: 4
* number: 155910144
* arg: 5
* number: 0


DGU_modbus_tcp 22.02.2021 20:48:58
* string: modbus read failed Invalid data

DGU_modbus_tcp 22.02.2021 20:49:13
* string: modbus connect failed Operation in progress

DGU_modbus_tcp 22.02.2021 20:49:28
* string: modbus connect failed Operation in progress

DGU_modbus_tcp 22.02.2021 20:49:43
* string: modbus connect failed Operation in progress

(Then the controller stops responding, and restarting the script also does not help, only restarting the controller.)

I do not understand the moment why when using the modbus pull, even with several connections and subsequent disconnections, the connection is restored, and when connecting to the logic machine, the controller completely stops responding?
Reply
#4
Seems to be a networking issue of some kind. Try running the same script with debug mode enabled and post what you get in Logs tab.
Code:
if not mb then
  require('luamodbus')
  mb = luamodbus.tcp()

  mb:setresponsetimeout(5)
  mb:open('10.36.0.25', 502)

  res, err = mb:connect()
  if res then
    
    buffer = {}
    mb:setdebug(function(msg)
      buffer[ #buffer + 1 ] = msg
    end)
  else
    log('modbus connect failed ' .. tostring(err))
    mb:close()
    mb = nil
  end
end

if mb then
  reg10240, reg10241, reg10242, reg10243, reg10244, reg10245, reg10246, reg10247 = mb:readregisters(10240, 8)
  
  if reg10240 then
    mains_l1_voltage = reg10240 / 10
    mains_l2_voltage = reg10242 / 10
    mains_l3_voltage = reg10244 / 10
    genset_l1_voltage = reg10246 / 10
    log('voltage values', mains_l1_voltage, mains_l2_voltage, mains_l3_voltage, genset_l1_voltage)
    log(table.concat(buffer))
    buffer = {}
  else
    log('modbus read failed ' .. tostring(reg10241))
    mb:close()
    mb = nil
  end
end
Reply
#5
I checked with the debug code, previously I tried several times to connect and disconnect the modbus pull application (all timeouts by default), everything worked correctly, and I also ran the 'ping 10.36.0.25 -t' command on the laptop to track the network connection. I ran the script on logic machine, the script gave the following log:

DGU_modbus_tcp 24.02.2021 22:56:59
* arg: 1
* string: voltage values
* arg: 2
* number: 242.7
* arg: 3
* number: 242.8
* arg: 4
* number: 241.8
* arg: 5
* number: 0
DGU_modbus_tcp 24.02.2021 22:56:59
* string: [00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><7B><00><00><09><7C><00><00><09><72><00><00><00><00><00><00>

DGU_modbus_tcp 24.02.2021 22:57:10
* string: modbus read failed Invalid data
DGU_modbus_tcp 24.02.2021 22:57:20
* arg: 1
* string: voltage values
* arg: 2
* number: 244.1
* arg: 3
* number: 241.1
* arg: 4
* number: 242.2
* arg: 5
* number: 0
DGU_modbus_tcp 24.02.2021 22:57:20
* string: [00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><89><00><00><09><6B><00><00><09><76><00><00><00><00><00><00>

DGU_modbus_tcp 24.02.2021 22:57:30
* string: modbus read failed Invalid data
DGU_modbus_tcp 24.02.2021 22:57:41
* string: modbus read failed Operation timed out
DGU_modbus_tcp 24.02.2021 22:57:51
* arg: 1
* string: voltage values
* arg: 2
* number: 243.7
* arg: 3
* number: 243
* arg: 4
* number: 241.2
* arg: 5
* number: 0
DGU_modbus_tcp 24.02.2021 22:57:51
* string: [00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><85><00><00><09><7E><00><00><09><6C><00><00><00><00><00><00>

DGU_modbus_tcp 24.02.2021 22:58:01
* string: modbus read failed Invalid data
DGU_modbus_tcp 24.02.2021 22:58:11
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 24.02.2021 22:58:22
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 24.02.2021 22:58:32
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 24.02.2021 22:58:43
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 24.02.2021 22:58:53
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 24.02.2021 22:59:04
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 24.02.2021 22:59:14
* string: modbus connect failed Operation in progress

ping was without a single timeout. But after stopping the script, I was no longer able to connect through the modbus poll program, the following error is returned: "Modbus/TCP Connection Failed.Connect Timeout.Open Command Prompt and ping the slave/server to verify the connection"

There were no ping problems during the entire check

after running the script again, the connection was also not restored and the device stopped responding to the ping command.
Reply
#6
It's strange that you get "invalid data" first. This might indicate that the device is faulty.
I've made a mistake in the previous test script so it does not log communication in case of an error. Run this and post what you get in Logs tab:
Code:
if not mb then
  require('luamodbus')
  mb = luamodbus.tcp()

  mb:setresponsetimeout(5)
  mb:open('10.36.0.25', 502)

  res, err = mb:connect()
  if res then
    
    buffer = {}
    mb:setdebug(function(msg)
      buffer[ #buffer + 1 ] = msg
    end)
  else
    log('modbus connect failed ' .. tostring(err))
    mb:close()
    mb = nil
  end
end

if mb then
  reg10240, reg10241, reg10242, reg10243, reg10244, reg10245, reg10246, reg10247 = mb:readregisters(10240, 8)
  
  if reg10240 then
    mains_l1_voltage = reg10240 / 10
    mains_l2_voltage = reg10242 / 10
    mains_l3_voltage = reg10244 / 10
    genset_l1_voltage = reg10246 / 10
    log('voltage values', mains_l1_voltage, mains_l2_voltage, mains_l3_voltage, genset_l1_voltage)
  else
    log('modbus read failed ' .. tostring(reg10241))
    mb:close()
    mb = nil
  end

  log(table.concat(buffer))
  buffer = {}
end
Reply
#7
DGU_modbus_tcp 25.02.2021 18:11:00
* arg: 1
* string: voltage values
* arg: 2
* number: 243.5
* arg: 3
* number: 235.4
* arg: 4
* number: 235.8
* arg: 5
* number: 0
DGU_modbus_tcp 25.02.2021 18:11:00
* string: [00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><83><00><00><09><32><00><00><09><36><00><00><00><00><00><00>

DGU_modbus_tcp 25.02.2021 18:11:10
* string: modbus read failed Invalid data
DGU_modbus_tcp 25.02.2021 18:11:10
* string: [00][02][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<1A><00><02><00><00><00><13><FF><03>
Invalid transaction ID received 0x1A00 (not 0x2)

DGU_modbus_tcp 25.02.2021 18:11:20
* arg: 1
* string: voltage values
* arg: 2
* number: 243.7
* arg: 3
* number: 236.5
* arg: 4
* number: 234.6
* arg: 5
* number: 0
DGU_modbus_tcp 25.02.2021 18:11:20
* string: [00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><85><00><00><09><3D><00><00><09><2A><00><00><00><00><00><00>

DGU_modbus_tcp 25.02.2021 18:11:30
* string: modbus read failed Invalid data
DGU_modbus_tcp 25.02.2021 18:11:30
* string: [00][02][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<1A><00><02><00><00><00><13><FF><03>
Invalid transaction ID received 0x1A00 (not 0x2)

DGU_modbus_tcp 25.02.2021 18:11:40
* arg: 1
* string: voltage values
* arg: 2
* number: 244.3
* arg: 3
* number: 237.8
* arg: 4
* number: 231.3
* arg: 5
* number: 0
DGU_modbus_tcp 25.02.2021 18:11:40
* string: [00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><8B><00><00><09><4A><00><00><09><09><00><00><00><00><00><00>

DGU_modbus_tcp 25.02.2021 18:11:51
* string: modbus read failed Invalid data
DGU_modbus_tcp 25.02.2021 18:11:51
* string: [00][02][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<1A><00><02><00><00><00><13><FF><03>
Invalid transaction ID received 0x1A00 (not 0x2)

DGU_modbus_tcp 25.02.2021 18:12:01
* arg: 1
* string: voltage values
* arg: 2
* number: 243.4
* arg: 3
* number: 237
* arg: 4
* number: 233.4
* arg: 5
* number: 0
DGU_modbus_tcp 25.02.2021 18:12:01
* string: [00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><82><00><00><09><42><00><00><09><1E><00><00><00><00><00><00>

DGU_modbus_tcp 25.02.2021 18:12:11
* string: modbus read failed Invalid data
DGU_modbus_tcp 25.02.2021 18:12:11
* string: [00][02][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<1A><00><02><00><00><00><13><FF><03>
Invalid transaction ID received 0x1A00 (not 0x2)

DGU_modbus_tcp 25.02.2021 18:12:21
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 25.02.2021 18:12:32
* string: modbus connect failed Operation in progress
DGU_modbus_tcp 25.02.2021 18:12:42
* string: modbus connect failed Operation in progress
Reply
#8
The illegal data error seems to come from the device sending some extra byte when it should not. Unfortunately it's hard to tell why the connection stops working. Try this test script which discards any stale data before reading.
Code:
if not mb then
  require('luamodbus')
  mb = luamodbus.tcp()

  mb:setresponsetimeout(5)
  mb:open('10.36.0.25', 502)

  res, err = mb:connect()
  if res then
    
    buffer = {}
    mb:setdebug(function(msg)
      buffer[ #buffer + 1 ] = msg
    end)
  else
    log('modbus connect failed ' .. tostring(err))
    mb:close()
    mb = nil
  end
end

if mb then
  mb:flush()
  reg10240, reg10241, reg10242, reg10243, reg10244, reg10245, reg10246, reg10247 = mb:readregisters(10240, 8)
  
  if reg10240 then
    mains_l1_voltage = reg10240 / 10
    mains_l2_voltage = reg10242 / 10
    mains_l3_voltage = reg10244 / 10
    genset_l1_voltage = reg10246 / 10
    log('voltage values', mains_l1_voltage, mains_l2_voltage, mains_l3_voltage, genset_l1_voltage)
  else
    log('modbus read failed ' .. tostring(reg10241))
    mb:close()
    mb = nil
  end

  log(table.concat(buffer))
  buffer = {}
end
Reply
#9
it looks like the mb:flush() has solved the problem. I also tested stopping and running the script several times, everything works correctly. The controller does not hang.

DGU_modbus_tcp 01.03.2021 13:24:10
* arg: 1
* string: voltage values
* arg: 2
* number: 240.8
* arg: 3
* number: 241
* arg: 4
* number: 236.6
* arg: 5
* number: 0

DGU_modbus_tcp 01.03.2021 13:24:10
* string: Bytes flushed (0)
[00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><68><00><00><09><6A><00><00><09><3E><00><00><00><00><00><00>


DGU_modbus_tcp 01.03.2021 13:24:20
* arg: 1
* string: voltage values
* arg: 2
* number: 240.2
* arg: 3
* number: 240.9
* arg: 4
* number: 237.4
* arg: 5
* number: 0

DGU_modbus_tcp 01.03.2021 13:24:20
* string: Bytes flushed (1)
[00][02][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><02><00><00><00><13><FF><03><10><09><62><00><00><09><69><00><00><09><46><00><00><00><00><00><00>


DGU_modbus_tcp 01.03.2021 13:24:30
* string: modbus read failed Operation timed out

DGU_modbus_tcp 01.03.2021 13:24:30
* string: Bytes flushed (1)
[00][03][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
ERROR Operation timed out: select


DGU_modbus_tcp 01.03.2021 13:24:41
* arg: 1
* string: voltage values
* arg: 2
* number: 238.8
* arg: 3
* number: 241.2
* arg: 4
* number: 237.6
* arg: 5
* number: 0

DGU_modbus_tcp 01.03.2021 13:24:41
* string: Bytes flushed (0)
[00][01][00][00][00][06][FF][03][28][00][00][08]
Waiting for a confirmation...
<00><01><00><00><00><13><FF><03><10><09><54><00><00><09><6C><00><00><09><48><00><00><00><00><00><00>


DGU_modbus_tcp 01.03.2021 13:24:51
* arg: 1
* string: voltage values
* arg: 2
* number: 239.8
* arg: 3
* number: 239.4
* arg: 4
* number: 238.1
* arg: 5
* number: 0


Is there a complete description of the luamodbus library with all supported commands? On the web, I found only individual parts of the code without a detailed description of the functions...
Reply
#10
Unfortunately there's no full documentation because the recommended approach is to use profiles.
There seems to be a problem in the Datakom controller. Flush is used when a the read request times out to remove any partial data from the buffer. Otherwise next read calls can fail dues to erroneous data that is already in the buffer. This is the first time that I've seen that flush is needed for TCP communication though.
Reply
#11
It is very likely that the problem is in the controller after about 5 hours of operation a similar situation with the controller hanging...
Reply
#12
Is the setresponsetimeout parameter set in seconds or milliseconds? in the examples on the forum, there are both so and so... and what is it by default if it is not specifically set? In what place is it correct to specify it, before opening the port or after?

According to the manufacturer, it should be at least a second....
Reply
#13
The timeout value is in seconds, it should be set before connect()
Reply


Forum Jump: