====== Omron SYSMAC CS/CJ/CP Series & NCJ series C-Command protocol ====== C-mode (Host Link) commands form a command/response system for serial communications (Host Link Mode) to perform various control operations between a CPU Unit and a host computer directly connected to it. These operations include reading from and writing to I/O memory, changing operating modes, executing forced set and forced reset operations, and so on. In WebHMI, this protocol is implemented using custom protocol. See the sample below. To create a protocol follow the link below: {{ :conn:conn-examples:link-to-custom-protocol-new.png?direct&800 |}} and add a new protocol: {{ :conn:conn-examples:add-custom-protocol-button.png?direct&800 |}} {{ :conn:conn-examples:omron_-_custom-protocol-settings.png?direct&800 |}} --[[ OMRON HOSTLINK PROTOCOL SUPPORTING THE FOLLOWING C-COMMANDS FOR SYSMAC CS/CJ/CP Series & NCJ 4-3-2 CIO AREA READ WRITE (ref. to w342 reference manual) 4-3-4 HR AREA READ WRITE 4-3-7 DM AREA READ WRITE --]] STX = '@' CR = 0x0D FRAME_TAIL = '*' .. string.char(CR) -- symbols positions STX_POS = 1 NODE_ID_POS = 2 HEADER_CODE_POS = 4 END_CODE_POS = 6 NORMAL_END_CODE = 0 WORD_DATA_START_POS = 8 WORD_DATA_FCS_POS = WORD_DATA_START_POS + 4 DWORD_DATA_FCS_POS = WORD_DATA_FCS_POS + 4 * 1 -- x by word count WR_CMD_PAYLOAD_END = 7 function createDevices () addDevice{name = "CIO", shift = 0, base = 10, xtraFields = {}} addDevice{name = "HR", shift = 0, base = 10, xtraFields = {}} addDevice{name = "DM", shift = 0, base = 10, xtraFields = {}} end -- commands READ_COMMANDS = {CIO = "RR", HR = "RH", DM = "RD"} WRITE_COMMANDS = {CIO = "WR", HR = "WH", DM = "WD"} -- field lengthes NODE_ADDR_LEN, MEM_ADDR_LEN = 2, 4 DEC_BASE, HEX_BASE = 10, 16 -- dataType – 0 = Bit, 1 = Byte, 2 = Word, 3 = Double Word, 4 = UnixTime REG_STRUC_BIT_TYPE = 0 REG_STRUC_WORD_TYPE = 2 REG_STRUC_DW_TYPE = 3 -- will read 2 words for these types REG_STRUC_UT_TYPE = 4 DATA_FORMAT_DICT = {[0] = "REG_STRUC_BIT_TYPE",[2] = "REG_STRUC_WORD_TYPE", [3] = "REG_STRUC_DW_TYPE", [4] = "REG_STRUC_UT_TYPE"} readCache = { CIO = { unsorted = {}, sorted = {} }, -- grouped ranges will be here HR = { unsorted = {}, sorted = {} }, -- cached data will be here DM = { unsorted = {}, sorted = {} } } VERY_FIRST_SCAN = 1 SECOND_SCAN = 2 scanCounter = VERY_FIRST_SCAN singleRegReadCounter = 0 -- to count single reads function onScanStart() if (singleRegReadCounter ~= 0) then DEBUG("Made " .. singleRegReadCounter .. " single reads on previos scan!") singleRegReadCounter = 0 end printOnceFlag = false -- MAKE GROUP READ LISTS ------------------------------------- if (scanCounter == SECOND_SCAN) then DEBUG("Second scan!") for devName, deviceData in pairs(readCache) do deviceData.sorted = getSortedTableKeys(deviceData.unsorted) -- tprint(deviceData.sorted) -- now grouped local groupsFound = getRangesFromTab(deviceData.sorted) ; -- DEBUG("Making grouped ranges for " .. devName) if groupsFound then deviceData['group'] = groupsFound deviceData['stored'] = {} -- create a key for cached data else ERROR("Could not build ranges for the " .. devName) end -- tprint(deviceData.group) end scanCounter = scanCounter + 1 end if (scanCounter == VERY_FIRST_SCAN) then DEBUG("First scan, will read all!") scanCounter = scanCounter + 1 return end -- GROUP READ ----------------------------------------------- if (scanCounter >= SECOND_SCAN) then DEBUG("scanCounter > 2 ...") for dname, ddata in pairs(readCache) do for gr, addrList in ipairs(ddata.group) do DEBUG("Making group# " .. gr .. " read for " .. dname ) local wordCount = #addrList local packetMade = makeReadPacket(DEVICE_NODE, dname, addrList[1], wordCount) if packetMade then sendString(packetMade) local response = readReply() if (not response) then ERROR("Could not read response!") else local payloadEndPosition = WORD_DATA_START_POS + wordCount * 4 - 1 if (not validate(response, DEVICE_NODE , READ_COMMANDS[dname] , payloadEndPosition) ) then ERROR("Could not validate group read reply") break else -- STORING DATA IN CACHE -------------- for w = 1, wordCount do local dataOffset = WORD_DATA_START_POS + (w - 1) * 4 local data = getNumberFromASCII(HEX_BASE, unpack(table.sub(response ,dataOffset ,dataOffset + 3))) ddata.stored[addrList[w]] = data end end end else ERROR("could not make packet!") break end -- packet made DEBUG("finished group read!") end -- addr list end -- dname, ddata end end -- end of protocol sample For full text protocol or more features, turn to your WebHMI supplier. In the connection properties, select this newly created protocol: {{ :conn:conn-examples:omron-conn-property-1.png?direct&800 |}} And set communication paramteres: {{ :conn:conn-examples:omron-conn-property-2.png?direct&800 |}}