SpaceLogic KNX Forum
Schneider Electric SpaceLogic KNX forum to get support and share knowledge including selection, installation and troubleshooting for spaceLYnk, Wiser for KNX, eConfigure KNX, SpaceLogic KNX Hybrid module and other topics.
Posted: 2016-07-06 04:42 AM . Last Modified: 2024-07-14 11:55 PM
Link copied. Please paste this link to share this article on your social media post.
I am using spacelynk as a slave, modbus tcp.
I got also an error code in error log.
Error message:
Line 107: attempt to perform a arithmetic on local 'value' (a nil value)
I am sendig temperatures, status value for heating/ cooling valves, and 1bit status heating / cooling from KNX to modbus
The 2-byte float value is rounded in the script, so when i send 23.4 °C from the knx to the Fidelix ventilation system it shows 23°C.
Line:
103, -- try to find matching register
104, for id, addr in ipairs(registers) do
105, if event.dst == addr then
106, value = knxdatatype.decode(event.datahex, regdt[ id ])
107, mb:setregisters(id - 1, math.floor(value + 0.5))
108, end
109, end
110, end
*********************This is the script i am using.*****************************
-- must run as a resident script with sleep time = 0
-- supports coils (1 bit) and holding registers (1 byte and 2 byte)
if not mb then
require('genohm-scada.eibdgm')
require('luamodbus')
----------- Change mapping to fit local project ------------------
-- list of coil mapping, starting from 0
coils = { '25/1/1' }
-- list of register mapping, starting from 0
registers = {
'29/1/1', '29/1/2',
'6/1/1', '6/1/2', '6/1/3', '6/1/4', '6/1/5', '6/1/6', '6/1/7', '6/1/8', '6/1/9', '6/1/10', '6/1/11', '6/1/13',
'6/2/1', '6/2/2', '6/2/3', '6/2/4', '6/2/5', '6/2/6', '6/2/7', '6/2/8', '6/2/9', '6/2/10', '6/2/11', '6/2/13',
'6/3/1', '6/3/2', '6/3/3', '6/3/4', '6/3/5', '6/3/6', '6/3/7', '6/3/8', '6/3/9', '6/3/10', '6/3/11', '6/3/13',
'6/4/1', '6/4/2', '6/4/3', '6/4/4', '6/4/5', '6/4/6', '6/4/7', '6/4/8', '6/4/9', '6/4/10', '6/4/11', '6/4/13',
'6/4/1', '6/4/2', '6/4/3', '6/4/4',
'21/1/21',
'7/1/1', '7/1/2', '7/1/3', '7/1/4', '7/1/5', '7/1/6', '7/1/7', '7/1/8', '7/1/9',
'7/2/1', '7/2/2', '7/2/3', '7/2/4', '7/2/5', '7/2/6', '7/2/7', '7/2/8', '7/2/10',
'7/3/1', '7/3/2', '7/3/3', '7/3/4', '7/3/5', '7/3/6', '7/3/7', '7/3/8', '7/3/10',
'7/4/1', '7/4/2', '7/4/3', '7/4/4', '7/4/5', '7/4/6', '7/4/7', '7/4/8', '7/4/10',
'7/4/1', '7/4/2', '7/4/3', '7/4/4',
'21/0/26',
'8/1/0', '8/1/1', '8/1/2',
'8/2/1', '8/2/2',
'8/3/0', '8/3/1', '8/3/3',
'8/4/1', '8/4/2',
'12/0/0', '12/0/1', '12/0/2', '12/0/3', '12/0/4', '12/0/5', '12/0/6', '12/0/7',
'12/0/8', '12/0/9', '12/0/10', '12/0/11', '12/0/13', '12/0/14', '12/0/15',
'12/0/16', '12/0/17', '12/0/18', '12/0/19', '12/0/20', '12/0/21', '12/0/22', '12/0/23', '12/0/24', '12/0/25',
'0/0/3', '29/1/8', '0/0/21', '0/0/22',
'11/0/1', '11/0/2', '11/0/3', '11/0/4', '11/0/5', '11/0/6', '0/1/7',
'11/0/10', '11/0/11', '11/0/110', '11/0/111',
'29/4/5', '29/4/6', '29/4/7', '29/4/8',
'0/7/6',
'11/3/1', '11/3/2', '11/3/3', '11/3/4', '11/3/5', '11/3/6', '11/3/7',
'11/3/8', '11/3/9', '11/3/10', '11/3/11', '11/3/12', '11/3/13', '11/3/14',
'11/4/1', '11/4/2', '11/4/3', '11/4/4', '11/4/5', '11/4/6', '11/4/7',
'11/4/8', '11/4/9', '11/4/10', '11/4/11', '11/4/12', '11/4/13',
'0/7/5',}
-- list of register data types, element count must match registers table above
-- dt.uint8 1 byte unsigned
-- dt.scale 1 byte 0-100%
-- dt.angle 1 byte 0-360
-- dt.int8 1 byte singed
-- dt.uint16 2 byte unsigned
-- dt.int16 2 byte signed
-- dt.float16 2 byte float (rounded)
regdt = {
'dt.float16', 'dt.int8',
'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8',
'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8',
'dt.float16', 'dt.float16', 'dt.float16',
'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8',
'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16',
'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16',
'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16', 'dt.float16',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8', 'dt.int8',
'dt.int8'}
---------- Don't change anything below ---------------------------
---------- CALLBACK FUNCTIONS ------------------------------------
-- knx group write callback, the funtion is called when a KNX object is written to
-- if the group address is in the above tables coils or registers the corresponding MODBUS register is updated
function knxgroupwrite(event)
local value
-- try to find matching coil
for id, addr in ipairs(coils) do
if event.dst == addr then
value = knxdatatype.decode(event.datahex, dt.bool)
mb:setcoils(id - 1, value)
end
end
-- try to find matching register
for id, addr in ipairs(registers) do
if event.dst == addr then
value = knxdatatype.decode(event.datahex, regdt[ id ])
mb:setregisters(id - 1, math.floor(value + 0.5))
end
end
end
-- coil write callback, the function is called when a MODBUS client is writing to a coil in sL
-- the MODBUS coil value is written to the corresponding KNX object
function mbwritecoils(coil, value)
local addr = coils[ coil + 1 ]
if addr then
grp.write(addr, value, dt.bool)
end
end
-- register write callback, the function is called when a MODBUS client is writing to a register in sL
-- the MODBUS register value is written to the corresponding KNX object
function mbwriteregisters(register, value)
local addr = registers[ register + 1 ]
if addr then
grp.write(addr, value, regdt[ register + 1])
end
end
--------------- INIT ------------------------------------------------------------
-- knx group monitor, handles group writes
knxclient = eibdgm:new({ timeout = 0.1 })
knxclient:sethandler('groupwrite', knxgroupwrite)
-- modbus slave, listen on all interfaces and default port 502
mb = luamodbus.tcp()
mb:open('0.0.0.0', 502) -- ip-address 0.0.0.0 represents the local sL
-- setting slave id is optional
-- mb:setslave(1)
mb:setreceivetimeout(0.1)
-- sets up the number of MODBUS coils and holding registers according to the
-- number of group addresses in the coils and registers table
mb:setmapping(#coils, 0, #registers, 0)
-- init coils
for id, addr in ipairs(coils) do
value = grp.getvalue(addr)
mb:setcoils(id - 1, value)
end
-- init registers
for id, addr in ipairs(registers) do
value = grp.getvalue(addr)
mb:setregisters(id - 1, value)
end
-- set callbacks for coil and register write
mb:setwritecoilcb(mbwritecoils)
mb:setwriteregistercb(mbwriteregisters)
end
------------ RUNTIME -----------------------------------------------------
-- handle modbus and knx
mb:handleslave()
knxclient:step()
Link copied. Please paste this link to share this article on your social media post.
Hi Martin,
This error is because the script can't get the value if the KNX object. Do all objects in the table exist and are the dtp'set correct?
Do you have backup so i can check where it goes wrong?
BR,
Erwin van der Zwart
Link copied. Please paste this link to share this article on your social media post.
Hi Martin,
As discussed over the mail the issue is that you have enclosed the dpt's in the table with 'xxx" like 'dt.float16', this cause the function to be transformed to a string and that's
why you get 'nil' back on the object value as the decoding fails.
I changed all items in the dpt table and it works now as it should.
I have mailed you the correction but basicly its just removing the ' ' from all dpt's
BR,
Erwin van der Zwart
Create your free account or log in to subscribe to the board - and gain access to more than 10,000+ support articles along with insights from experts and peers.