This manual describes connection of float gauge to type S0 IoT convertor. Device can be used for example to indicate flooding of some spaces or for checking water level in tanks.
Used floating gauge have three wires, middle contact (black), contact connected at up position (brown) and contact connected at bottom position of gauge (blue). In case of changing of float gauge, it is important to check correct wiring.
Used solution with three wires have advantage in detection of broken connection to gauge or fault device - if convertor doesn't have input from any contact, it sends error message.
|baterry voltage||input status||error detected|
|payload example||96 0E||01 00 00 00||00 00 00 00|
|interpretation||voltage in mV||1- gauge up/0 - gauge down||1 - error/0-OK|
|< - little endian||> - big endian|
Immediately after startup of device, LUA script sets up LoRa communication method and waking up of device at any change of both inputs. Then Convertor switches to sleep mode. If there is not any change on inputs, convetor wakes up every two hours and executes function
processInputs, which checks all inputs and battery voltage. When convertor detects that both float gauge inputs are equal, it checks their states again with delay of 200 ms and increases error counter. In case of reading equal inputs ten times in a row, convertor evaluates this as an error (possible interrupting of wires or faulty float gauge) and sends error state throug LoRaWAN. When acknowledged communiction mode is used, convertor is waiting for acknowledge from LoRaWAN Network Server. After receiving of acknowledge is wake up time set to two hours, if acknowledge is not received, device will wake after two minutes.
When floating gauge changes its state, convertor switches from sleep mode to function
onInputChanged and compares timestamp of last change of stat with actual event. If time between changes is shorter than 10 seconds, change is ignored, which is preventing false positive readings. In other case, function
processInputs is called and convertor works as described in previous paragraph.
-- once in 120 minutes periodicWakeup = 120 -- join method to use, "OTAA" or "ABP" joinMethod = "ABP" -- LoRaWAN port to use port = 1 -- use confirmed communication useAcking = 1 -- if no acknowledge, retry after x seconds noAckRetryAfter = 120 -- retry after 200 miliseconds in case of bad state errorStateRetryPeriod = 200 -- retry 10 times, then report bad input errorStateRetryCount = 10 -- ignore onInputChanged if happening faster than once per x ms ignoreChangeFasterThan = 10000 -- non-inverted direct input, log. 1 when gauge floating high directInput = 1 -- inverted input of the float gauge, log. 1 when reservoir empty invertedInput = 2 version = "1.0" function processInputs() txbuf = "" -- get battery voltage v = api.getBatteryVoltage() txbuf = txbuf .. pack.pack("<H", v) directState = api.DIOreadPin(directInput) invertedState = api.DIOreadPin(invertedInput) retry = 0 detectedError = 0 -- if equal, then we have error with the sensor while directState == invertedState do print( "Detected bad sensor state, direct = " .. tostring(directState) .. ", indirect = " .. tostring(invertedState) ) retry = retry + 1 if retry >= errorStateRetryCount then -- report an error! print("Detected error condition " .. tostring(retry) .. " times in row, report it!") detectedError = 1 break end -- delay for next trial api.delayms(errorStateRetryPeriod) -- try read again directState = api.DIOreadPin(directInput) invertedState = api.DIOreadPin(invertedInput) end txbuf = txbuf .. pack.pack("<I2", directState, detectedError) api.dumpArray(txbuf) acked = api.loraSend(useAcking, 6000, txbuf, port) if useAcking == 1 then if acked >= 0 then print("Ack received, next message in " .. tostring(periodicWakeup) .. " minutes") api.wakeUpIn(0, 0, periodicWakeup, 0) else print("No ack! Send again in ".. tostring(noAckRetryAfter) .." seconds!") api.wakeUpIn(0, 0, 0, noAckRetryAfter) end else print("Unconfirmed delivery used, next message in " .. tostring(periodicWakeup) .. " minutes") api.wakeUpIn(0, 0, periodicWakeup, 0) end end function onWake() print("Periodic wake up - send a ping, that we are alive") processInputs() api.setVar(1, api.getTick()) -- update also the timestamp end function onInputChanged(src) print("Event occured on pin " .. tostring(src)) nowTimestamp = api.getTick() lastTimestamp = api.getVar(1) if nowTimestamp < lastTimestamp then diff = nowTimestamp -- handle overflow of ms tick counter else diff = nowTimestamp - lastTimestamp end if diff > ignoreChangeFasterThan then api.setVar(1, nowTimestamp) processInputs() else print("Too fast input change (time difference = " .. tostring(diff) .. " ms), drop!") end end function onStartup() print("Starting up Lua VM...") print("Float Gauge script ver. " .. version) print("Switch to " .. joinMethod .. " activation") api.loraSetup("ACTIVATION", joinMethod) print( "Set input " .. tostring(directInput) .. " and " .. tostring(invertedInput) .. " to rising/falling edge event source" ) api.DIOwaitForEvent(directInput, 3) api.DIOwaitForEvent(invertedInput, 3) api.setVar(1, 0) -- initial value for "lastTimestamp" in ms end