Last active
April 9, 2017 09:03
-
-
Save vsky279/1476ac5176738a0cb9504ce132d3c7e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-------------------------------------------------------------------------------- | |
-- DS18B20 one wire module for NODEMCU | |
-- by @voborsky, @devsaurus | |
-- | |
-- by default the module is for integer version, comment integer version and | |
-- uncomment float version part for float version | |
-------------------------------------------------------------------------------- | |
local modname = ... | |
local ow_setup, ow_search, ow_select, ow_read, ow_read_bytes, ow_write, ow_crc8, ow_reset, ow_reset_search = | |
ow.setup, ow.search, ow.select, ow.read, ow.read_bytes, ow.write, ow.crc8, ow.reset, ow.reset_search | |
local node_task_post = node.task.post | |
local node_task_LOW_PRIORITY = node.task.LOW_PRIORITY | |
--local tmr_now = tmr.now | |
local pin = 3 | |
local sens = {} | |
local temp= {} | |
local cb | |
-- local function to_string(addr, esc) | |
-- if type(addr) == 'string' and #addr == 8 then | |
-- return ( esc == true and | |
-- '"\\%u\\%u\\%u\\%u\\%u\\%u\\%u\\%u"' or | |
-- '%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(addr:byte(1,8)) | |
-- else | |
-- return tostring(addr) | |
-- end | |
-- end | |
local function readout() | |
local next = false | |
if not sens then return 0 end | |
for i,s in ipairs(sens) do | |
-- print(encoder.toBase64(s.addr), s.status) | |
if s.status == 1 then | |
ow_reset(pin) | |
ow_select(pin, s.addr) -- select the sensor | |
ow_write(pin, 0xBE, 0) -- READ_SCRATCHPAD | |
data = ow_read_bytes(pin, 9) | |
local t=(data:byte(1)+data:byte(2)*256) | |
if (t > 0x7fff) then t = t - 0x10000 end | |
if (s.addr:byte(1) == 0x28) then | |
t = t * 625 -- DS18B20, 4 fractional bits | |
else | |
t = t * 5000 -- DS18S20, 1 fractional bit | |
end | |
-- integer version | |
local sgn = t<0 and -1 or 1 | |
local tA = sgn*t | |
local tH=tA/10000 | |
local tL=(tA%10000)/1000 + ((tA%1000)/100 >= 5 and 1 or 0) | |
if tH and (tH~=85) then | |
temp[s.addr]=(sgn<0 and "-" or "")..tH.."."..tL | |
--print(('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(s.addr:byte(1,8)),(sgn<0 and "-" or "")..tH.."."..tL) | |
s.status = 2 | |
end | |
-- end integer version | |
-- -- float version | |
-- if t and (math.floor(t/10000)~=85) then | |
-- self.temp[s.addr]=t | |
-- print(encoder.toBase64(s.addr), t) | |
-- s.status = 2 | |
-- end | |
-- -- end float version | |
end | |
next = next or s.status == 0 | |
end | |
if next then | |
node_task_post(node_task_LOW_PRIORITY, conversion) | |
else | |
--sens = {} | |
while #sens ~= 0 do rawset(sens, #sens, nil) end | |
if cb then | |
node_task_post(node_task_LOW_PRIORITY, function() return cb(temp) end) | |
end | |
end | |
end | |
local function conversion() | |
for i,s in ipairs(sens) do | |
if s.status == 0 then | |
--print("starting conversion:", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(s.addr:byte(1,8)), s.parasite == 1 and "parasite" or " ") | |
ow_reset(pin) | |
ow_select(pin, s.addr) -- select the sensor | |
ow_write(pin, 0x44, 1) -- and start conversion | |
s.status = 1 | |
if s.parasite == 1 then break end -- parasite sensor blocks bus during conversion | |
end | |
end | |
tmr.create():alarm(750, tmr.ALARM_SINGLE, readout) | |
end | |
local function readTemp(lcb, lpin) | |
--local start = tmr_now() | |
cb = lcb | |
--temp={} | |
while #temp ~= 0 do rawset(temp, #temp, nil) end | |
if lpin then pin = lpin end | |
ow_setup(pin) | |
--sens={} | |
while #sens ~= 0 do rawset(sens, #sens, nil) end | |
ow_reset_search(pin) | |
-- ow_target_search(pin,0x28) | |
-- search the first device | |
local addr = ow_search(pin) | |
-- and loop through all devices | |
while addr do -- !!!!!!!!!!!!!!!!!!!!!!! should be looped in a task, also separated to separate | |
-- search next device | |
local crc=ow_crc8(string.sub(addr,1,7)) | |
if (crc==addr:byte(8)) and ((addr:byte(1)==0x10) or (addr:byte(1)==0x28)) then | |
ow_reset(pin) | |
ow_select(pin, addr) -- select the found sensor | |
ow_write(pin, 0xB4, 1) -- Read Power Supply [B4h] | |
local parasite = (ow_read(pin)==0 and 1 or 0) | |
sens[#sens+1]={addr=addr, parasite=parasite, status=0} | |
--print("contact: ", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(addr:byte(1,8)), parasite == 1 and "parasite" or " ") | |
end | |
addr = ow_search(pin) | |
tmr.wdclr() | |
--print(1,tmr_now()-start,#sens) | |
end | |
-- place powered sensors first | |
table.sort(sens, function(a, b) return a.parasite<b.parasite end) | |
node_task_post(node_task_LOW_PRIORITY, conversion) | |
--print(2,tmr_now()-start) | |
end | |
local M = { | |
sens=sens, | |
temp=temp, | |
readTemp = readTemp | |
} | |
_G[modname or 'ds18b20'] = M | |
return M |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment