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 revisionBoth sides next revision
custom_protocols [2019/01/09 12:19] – [The examples of custom protocols] emozolyakcustom_protocols [2019/01/09 12:19] – [Modbus RTU in custom protocol version] emozolyak
Line 450: Line 450:
  
  
- 
-===== 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