User Tools

Site Tools


custom_protocols

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
custom_protocols [2019/01/09 12:15] – [readRegister] emozolyakcustom_protocols [2019/01/09 12:19] – [Modbus RTU in custom protocol version] emozolyak
Line 446: Line 446:
   *ModBus TCP   *ModBus TCP
   *ModBus ASCII   *ModBus ASCII
-  *Modbus RTU.+  *[[http://docs.webhmi.com.ua/modbus_rtu_custom|Modbus RTU]].
  
  
  
- 
-===== Modbus RTU in custom protocol version ===== 
- 
-An example of custom protocol for Modbus RTU. 
- 
-  *Type: Serial Port 
-  *Address validation: ^(C[0-9]+)$|^(DI[0-9]+)$|^(HR[0-9]+)$|^(IR[0-9]+)$ 
-  *Validation error message: Invalid register address. Valid ModBus addresses are Cxxx, DIxxx, IRxxx, HRxxx. 
-Code: 
-<code lua> 
--- MODBUS RTU Demo Driver 
- 
-function createDevices () 
-                                                     -- read FC write FC 
-  addDevice({name = "C",  shift = 0, base = 10, xtraFields = {1, 5}}) 
-  addDevice({name = "DI", shift = 0, base = 10, xtraFields = {2, 0}}) 
-  addDevice({name = "HR", shift = 0, base = 10, xtraFields = {3, 6}}) 
-  addDevice({name = "IR", shift = 0, base = 10, xtraFields = {4, 0}}) 
-   
-end 
- 
-local errorCount = 0 
- 
--- template  
-local request = {1, 2,      -- slaveId FC 
-                 3,  4,  -- addr high lo  
-                 5,  6, -- count hi lo  
-                 0,  0      -- crc high lo  
-                }      
- 
-EXCEPTIONS = {"Illegal Function",     "Illegal Data Address", 
-               "Illegal Data Value",  "Slave Device Failure", 
-               "Acknowledge",         "Slave Device Busy", 
-               "Negative Acknowledge", "Memory Parity Error", 
-               "Gateway Path Unavailable", "Gateway Target Device Failed to Respond" 
-              } 
- 
-function readRegister (reg, device, unitId) 
-                             --- FORMING REQUEST -----------  
-      -- slave address 
-  request[1] = unitId; 
-   
-  -- function code 
-  request[2] = device.xtraFields[1] 
-   
-  -- address of register 
-  request[3] = GetHiByte(reg.internalAddr) 
-  request[4] = GetLoByte(reg.internalAddr) 
-   
-  -- count of registers 
-  local count = 1 
-      if (reg.dataType == 3) then -- double word 
-        count = 2 
-      end 
-  request[5] = GetHiByte(count) 
-  request[6] = GetLoByte(count) 
-   
-   -- CRC 
-  local crc = GetCRC(request, 2) 
-  local crcLo,crcHi = 0,0 -- will be used below too  
-  crcLo = GetLoByte(crc) ; request[7] = crcLo 
-  crcHi = GetHiByte(crc) ; request[8] = crcHi 
- 
-                           -- SENDING REQUEST  
-  if not (sendBytes(request)) then 
-      DEBUG("Can't send bytes") 
-      return false 
-  end 
-                           -- RECEIVING REPLY ---  
-  local respHead, respData, respCRC = {}, {}, {} 
-   
-    -- read Header with length  
-  respHead = readBytes(3) 
-  if (respHead == false) then 
-      DEBUG("Can't read response") 
-      return false 
-  end 
-   
-  if (respHead[1] ~= request[1]) then 
-      ERROR("Wrong slaveID in response!") 
-      return false 
-  end 
-   
-  if (respHead[2] ~= request[2]) then 
-      if (respHead[2] >= 0x81) then  
-          ERROR("EXCEPTION: "..EXCEPTIONS[bit.band(respHead[2], 0x0F)]) 
-          readBytes(2) -- read till the end  
-      else        
-          ERROR("Wrong Func Code in response") 
-      end  
-   return false; 
-  end 
-   
-  local resp_Lentgh = respHead[3];  
-        respData = readBytes(resp_Lentgh) 
-  if (respData == false) then 
-      DEBUG("Can't read response"); 
-      return false; 
-  end 
-  -- check CRC in reply  
-  local tmpResponseTab = {} 
-    for i,v in ipairs(respHead) do  
-        table.insert(tmpResponseTab, v)  
-    end  
-    for i,v in ipairs(respData) do  
-        table.insert(tmpResponseTab, v)  
-    end  
-   
-  crc = GetCRC(tmpResponseTab, 0) 
-  crcLo = GetLoByte(crc) 
-  crcHi = GetHiByte(crc) 
-     
-  respCRC = readBytes(2) 
-  if (respCRC == false) then 
-      DEBUG("Can't read response"); 
-      return false; 
-  end 
-  if (respCRC[1] ~= crcLo) or (respCRC[2] ~= crcHi) then  
-      DEBUG("Wrong CRC in reply! "..string.format("%X", crcLo).." "..string.format("%X", crcHi)); 
-      return false; 
-  end  
-   
-  if (device.name == "DI") or (device.name == "C" then  
-      if (resp_Lentgh ~= count) then 
-          ERROR("Wrong length in response"); 
-          return false; 
-      end 
-  else  
-      if (resp_Lentgh ~= count*2) then 
-          ERROR("Wrong length in response"); 
-          return false; 
-      end 
-  end  
-                                  -- RETURN DATA --   
-    return GetHexFromTable(respData) 
- 
-end -- readRegister 
- 
- 
- 
-function writeRegister (reg, device, unitId, newValue) 
-    -- for read-only don't write  
-                                    DEBUG("Going to write this value "..newValue) 
-    if device.name == "IR" or device.name == "DI" then  
-         ERROR("Can't write these type of registers (" .. device.name .. ")") 
-        return true  
-    end  
-    local wrRequest = {}; 
-     
-    -- slave address 
-    wrRequest[1] = unitId;    
-     
-    -- function code 
-    wrRequest[2] = device.xtraFields[2] 
-     
-    -- address of register 
-    wrRequest[3] = GetHiByte(reg.internalAddr) 
-    wrRequest[4] = GetLoByte(reg.internalAddr) 
-     
-    local dataTable = GetDataAsTable(newValue, device.dataType) 
-         
-        local coilsTmp = 0  
-        if (device.name == "C") then  
-            coilsTmp = dataTable[2] * 0xFF  
-            dataTable[2] = dataTable[1] 
-            dataTable[1] = coilsTmp 
-        end  
-    DEBUG("#dataTable now "..#dataTable) 
-     
-    wrRequest[5] = dataTable[1] 
-    wrRequest[6] = dataTable[2] 
-     
-    -- CRC 
-    local crc, crcLo, crcHi = 0,0,0 
-    crc = GetCRC(wrRequest, 0) 
-    crcLo = GetLoByte(crc) 
-    crcHi = GetHiByte(crc)  
-    wrRequest[7] = crcLo 
-    wrRequest[8] = crcHi  
-     
-    DEBUG("Going to send this packet "..table.concat(wrRequest))     
-    local res = sendBytes(wrRequest); 
-    if (res == false) then 
-        DEBUG("Can't send request"); 
-        return false; 
-    end 
-     
-    -- читаем ответ  
-    res = readBytes(8)  
-     
-    if (res == false) then 
-        DEBUG("Can't receive reply") 
-        return false 
-    end  
-     
-    if (table.concat(res) ~= table.concat(wrRequest)) then  
-        DEBUG("Response does not match!") 
-        return false 
-    end  
-     
-    if (#dataTable == 4) then  
-        -- DWORD 
-        -- repeat steps for 2nd Word  
-        wrRequest[3] = GetHiByte(reg.internalAddr + 1) 
-        wrRequest[4] = GetLoByte(reg.internalAddr + 1) 
-        wrRequest[5] = dataTable[3] 
-        wrRequest[6] = dataTable[4] 
-        crc, crcLo, crcHi = GetCRC(wrRequest, 0), GetLoByte(crc) , GetHiByte(crc)  
-        wrRequest[7] = crcLo 
-        wrRequest[8] = crcHi  
-        res = sendBytes(wrRequest); 
-        if (res == false) then 
-            DEBUG("Can't send request"); 
-            return false; 
-        end 
-    end  
-    return true 
-end 
- 
- 
--- Calculating CRC for RTU  
-function GetCRC(req, offset)  
-     
-  local crc = 0xffff 
-  local mask = 0 
-   
-  -- iterate bytes 
-for i=1,#req-offset do 
-      crc = bit.bxor(crc,req[i]) 
-      -- iterate bits in byte  
-      for j=1,8 do 
-          mask = bit.band(crc,0x0001) 
-          if mask == 0x0001 then 
-              crc = bit.rshift(crc,1) 
-              crc = bit.bxor(crc,0xA001) 
-          else 
-              crc = bit.rshift(crc,1) 
-          end 
-           
-      end  
-end  
-     return crc 
-end 
- 
-function GetHiByte(c) 
-                                   DEBUG("Going to get high byte from "..c) 
-   return bit.rshift(c,8) 
-end 
- 
-function GetLoByte(input_val)  
-                                    DEBUG("Going to get low byte from "..input_val) 
-    return bit.band(input_val,0xFF) 
-end 
- 
-function GetHexFromTable(inputTab) 
-    -- get hex and concat it to number via string operatoin  
-                                    DEBUG("entered GetHexFromTable with table - "..table.concat(inputTab)) 
-    local numberAs_String = ""  
-    local tmpStr = ""  
-     
-        for i,v in pairs(inputTab) do  
-            tmpStr = string.format("%X",v) 
-            if (#tmpStr == 1) then  
-                tmpStr = "0"..tmpStr 
-            end  
-            numberAs_String = numberAs_String..tmpStr 
-        end  
-                                DEBUG("number is "..numberAs_String.." decimal = "..numberAs_String)     
-    return tonumber(numberAs_String, 16) 
-end 
- 
-function GetDataAsTable(value, datatype) 
-  
-    local highWord, lowWord, tmpTable = 0, 0, {} 
-     
-    if (datatype ~= 3) then  
-        DEBUG("getdataastable - going to process value  "..value) 
-        tmpTable[1] = GetHiByte(value) ; DEBUG(tmpTable[1]) 
-        tmpTable[2] = GetLoByte(value) ; DEBUG(tmpTable[2]) 
-    else  
-        highWord = bit.rshift(value,16) 
-        lowWord = bit.band(c,0xFFFF) 
-         
-        tmpTable[1] = GetHiByte(highWord) 
-        tmpTable[2] = GetLoByte(highWord) 
-        tmpTable[3] = GetHiByte(lowWord) 
-        tmpTable[4] = GetLoByte(lowWord) 
-    end  
-    return tmpTable 
-end 
-</code> 
  
  
custom_protocols.txt · Last modified: 2023/02/21 17:52 by emozolyak

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki