Управление освещением
    Презентации
    Технические решения на LogicMachine
    Визуализация
      evika.ru    Технические решения на LogicMachine    Работа LogicMachine в качестве Modbus Slave устройства

    Работа LogicMachine в качестве Modbus Slave устройства

    Добавление необходимых функций в библиотеку Общие функции (Common Functions).

    Для возможности работы в качестве Modbus Slave устройства добавьте следующий код в библиотеку Скрипты –> Общие функции (Scripting -> Common Functions).

    -- modbus proxy
    mbproxy = {
      -- supported function list
      functions = {
        'readdo',
        'readcoils',
        'readdi',
        'readdiscreteinputs',
        'readao',
        'readregisters',
        'readai',
        'readinputregisters',
        'writebits',
        'writemultiplebits',
        'writeregisters',
        'writemultipleregisters',
        'reportslaveid',
        'getcoils',
        'getdiscreteinputs',
        'getinputregisters',
        'getregisters',
        'setcoils',
        'setdiscreteinputs',
        'setinputregisters',
        'setregisters',
      },
      -- new connecton init
      new = function()
        require('rpc')
        local mb = setmetatable({}, { __index = mbproxy })
     
        mb.slaveid = 0
        mb.rpc = rpc.client('127.0.0.1', 28002, 'mbproxy')
     
        for _, fn in ipairs(mbproxy.functions) do
          mb[ fn ] = function(self, ...)
            return mb:request(fn, ...)
          end
        end
     
        return mb
      end
    }
     
    -- set local slave id
    function mbproxy:setslave(slaveid)
      self.slaveid = slaveid
    end
     
    -- send rpc request for a spefic function
    function mbproxy:request(fn, ...)
      local res, err = self.rpc:request({
        fn = fn,
        params = { ... },
        slaveid = self.slaveid or 0,
      })
     
      -- request error
      if err then
        return nil, err
      -- request ok
      else
        -- reply with an error
        if res[ 1 ] == nil then
          return nil, res[ 2 ]
        -- normal reply
        else
          return unpack(res)
        end
      end
    end

    Modbus handler

    Данная программа будет поддерживать работу Modbus и производить ответы на запросы
    от Modbus Master устройства.

    Состав скрипта:

    1. mb:open(‘/dev/RS485-2’, 38400, ‘E’, 8, 1, ‘H’)
    Открытие порта и установка параметров соединения. Для LogicMachine 2 порт RS485 – ttyS2,
    для семейства LogicMachine 3 – RS485-#, где # — порядковый номер порта RS485 слева направо
    2. mb:setslave(10)
    Установка адреса LogicMachine в Modbus
    3. mb:setmapping(10, 10, 10, 10)
    Резервирование количества coils, discrete inputs, holding registers и input registers
    4. mb:setwritecoilcb(function(coil, value)…
    Функция обратного вызова, который выполняется для каждой записи в coil
    5. mb:setwriteregistercb(function(coil, value)…
    Функция обратного вызова, который выполняется для каждой записи в регистр

    Рассмотрим на примере

    Переходим в меню LogicMachine -> Скрипты -> Резидентные (LogicMachine -> Scripting -> Resident) и создаем новый резидентный скрипт с параметром Интервал запуска (Sleep interval) равным 0.

    Modbus02

    Нажмем на иконку редактирования скрипта для добавления следующего программного кода:

    -- инициализация modbus 
    if not mb then
      require('luamodbus')
      mb = luamodbus.rtu()
      --указать верный порт
      mb:open('/dev/RS485-2', 9600, 'E', 8, 1, 'H')
      mb:connect()
     
      -- установка slave id
      mb:setslave(10)
     
      -- инициализация резервирования для coils, discrete inputs, 
    --holding registers и input registers  
      mb:setmapping(10, 10, 10, 10)
     
      -- запись от мастера значения coil 
      mb:setwritecoilcb(function(coil, value)
        if coil == 0 then
          grp.write('3/2/75', value, dt.bool)
        else
          alert('coil: %d = %s', coil, tostring(value))
        end
      end)
     
      -- запись от мастера значения register 
      mb:setwriteregistercb(function(register, value)
        if register == 0 then
          -- запись значения отгрниченного в пределах 0..100
          grp.write('3/2/76', math.min(100, value), dt.scale)
        else
          alert('register: %d = %d', register, value)
        end
      end)
    end
     
    -- инициализация серверной части 
    if not server then
      require('rpc')
     
      -- incoming data handler
      local handler = function(request)
        local fn, res
     
        fn = tostring(request.fn)
     
        if not mb[ fn ] then
          return { nil, 'unknown function ' .. fn }
        end
     
        if type(request.params) == 'table' then
          table.insert(request.params, 1, mb)
          res = { mb[ fn ](unpack(request.params)) }
        else
          res = { mb[ fn ](mb) }
        end
     
        return res
      end
     
      server = rpc.server('127.0.0.1', 28002, 'mbproxy', handler, 0.01)
    end
     
    mb:handleslave()
    server:step()

    Запись значений Modbus в мастер-устройство

    Рассмотрим установление coil на примере скрипта по событию. Скрипт отвечает на запись в KNX адрес 1 битового значения и записывает в coil с адресом 2.
    Переходим в меню LogicMachine -> Скрипты -> Событийные (LogicMachine -> Scripting -> Event-based) и создаем новый скрипт по событию.

    Modbus01

    value = event.getvalue()
    mb = mbproxy.new()
    mb:setcoils(2, value)

    Рассмотрим аналогичную ситуацию, но с записью в регистр. Записываем байтовое значение в регистр 5. Далее аналогично предыдущему пункту.
    value = event.getvalue()
    mb = mbproxy.new()
    mb:setregisters(5, value)




    Copyright © Evika.ru 2017
    All Rights Reserved