io - Lua: Working with Bit32 Library to Change States of I/O's -
i trying understand how programming in lua can change state of i/o's modbus i/o module. have read modbus protocol , understand registers, coils, , how read/write string should look. right now, trying grasp how can manipulate read/write bit(s) , how functions can perform these actions. know may vague right now, following functions, along questions throughout them, me better convey having disconnect. has been long time since i've first learned bit/byte manipulation.
local funccodes = { --[[i understand part]] readcoil = 1, readinput = 2, readholdingreg = 3, readinputreg = 4, writecoil = 5, presetsinglereg = 6, writemultiplecoils = 15, presetmultiplereg = 16 } local function totwobyte(value) return string.char(value / 255, value % 255) --[[why both of these same value??]] end local function readinputs(s) local s = mperia.net.connect(host, port) s:set_timeout(0.1) local req = string.char(0,0,0,0,0,6,unitid,2,0,0,0,6) local req = totwobyte(0) .. totwobyte(0) .. totwobyte(6) .. string.char(unitid, funccodes.readinput)..totwobyte(0) ..totwobyte(8) s:write(req) local res = s:read(10) s:close() if res:byte(10) local out = {} = 1,8 local statusbit = bit32.rshift(res:byte(10), - 1) --[[what bit32.rshift doing string? , same true next line bit32.band. out[#out + 1] = bit32.band(statusbit, 1) end = 1,5 tdt.value["return_low"] = tostring(out[1]) tdt.value["return_high"] = tostring(out[2]) tdt.value["sensor1_on"] = tostring(out[3]) tdt.value["sensor2_on"] = tostring(out[4]) tdt.value["sensor3_on"] = tostring(out[5]) tdt.value["sensor4_on"] = tostring(out[6]) tdt.value["sensor5_on"] = tostring(out[7]) tdt.value[""] = tostring(out[8]) end end return tdt end
if need more specific questions, i'll try. right i'm having hard time connecting dots going on bit/byte manipulation here. i've read both books on bit32 library , sources online, still don't know these doing. hope these examples, can clarification.
cheers!
--[[why both of these same value??]]
there 2 different values here: value / 255 , value % 255. "/" operator represents divison, , "%" operator represents (basically) taking remainder of division.
before proceeding, i'm going point out 255 here should 256, let's make correction before proceeding. reason correction should become clear soon.
let's @ example.
value = 1000 print(value / 256) -- 3.90625 print(value % 256) -- 232
whoops! there problem. string.char wants integers (in range of 0 255 -- has 256 distinct values counting 0), , may given non-integer. let's fix problem:
value = 1000 print(math.floor(value / 256)) -- 3 -- in lua 5.3, use value // 256 mean same thing print(value % 256) -- 232
what have done here? let's 1000 in binary. since working two-byte values, , each byte 8 bits, i'll include 16 bits: 0b0000001111101000. (0b prefix used indicate following number should interpreted binary.) if split first 8 bits , second 8 bits, get: 0b00000011 , 0b11101000. these numbers?
print(tonumber("00000011",2)) -- 3 print(tonumber("11101000",2)) -- 232
so have done split 2-byte number 2 1-byte numbers. why work? let's go base 10 moment. suppose have four-digit number, 1234, , want split 2 two-digit numbers. well, quotient 1234 / 100 12, , remainder of divison 34. in lua, that's:
print(math.floor(1234 / 100)) -- 12 print(1234 % 100) -- 34
hopefully, can understand what's happening in base 10 pretty well. (more math here outside scope of answer.) well, 256? 256 2 power of 8. , there 8 bits in byte. in binary, 256 0b100000000 -- it's 1 followed bunch of zeros. means similar ability split binary numbers apart 100 did in base 10.
another thing note here concept of endianness. should come first, 3 or 232? turns out different computers (and different protocols) have different answers question. don't know correct in case, you'll have refer documentation. way set called "big endian" because big part of number comes first.
--[[what bit32.rshift doing string? , same true next line bit32.band.]]
let's @ whole loop:
local out = {} = 1,8 local statusbit = bit32.rshift(res:byte(10), - 1) out[#out + 1] = bit32.band(statusbit, 1) end
and let's pick concrete number sake of example, say, 0b01100111. first let's lookat band (which short "bitwise and"). mean? means line 2 numbers , see 2 1's occur in same place.
01100111 band 00000001 ------------- 00000001
notice first i've put bunch of 0's in front of one. preceeding zeros don't change value of number, want 8 bits both numbers can check each digit (bit) of first number each digit of second number. in each place there both numbers had 1 (the top number had 1 "and" bottom number had 1), put 1 result, otherwise put 0. that's bitwise and.
when bitwise , 0b00000001 did here, should able see 1 (0b00000001) or 0 (0b00000000) result. depends on last bit of other number. have separated out last bit of number rest (which called "masking") , stored in our out array.
now rshift ("right shift")? shift right one, discard rightmost digit, , move else on 1 space the right. (at left, add 0 still have 8 bits ... usual, adding bit in front of number doesn't change it.)
right shift 01100111 \\\\\\\\ 0110011 ... 1 <-- discarded
(forgive horrible ascii art.) shifting right 1 changes our 0b01100111 0b00110011. (you can think of chopping off last bit.)
now mean shift right different number? shift 0 not change number. shift more one, repeat operation many times shifting by. (to shift two, shift 1 twice, etc.) (if prefer think in terms of chopping, right shift x chopping off last x bits.)
so on first iteration through loop, number not shifted, , store rightmost bit.
on second iteration through loop, number shifted 1, , new rightmost bit second right, bitwise , mask out bit , store it.
on next iteration, shift 2, rightmost bit 1 third right, bitwise , mask out bit , store it.
on each iteration, store next bit.
since working byte, there 8 bits, after 8 iterations through loop, have stored value of each bit our table. table should in our example:
out = {1,1,1,0,0,1,1,0}
notice bits reversed how wrote them 0b01100111 because started looking right side of binary number, things added table starting on left.
in case, looks each bit has distinct meaning. example, 1 in third bit mean sensor1 on , 0 in third bit mean sensor1 off. 8 different pieces of information packed make more efficient transmit them on channel. loop separates them again form easy use.
Comments
Post a Comment