Skip to content

Instantly share code, notes, and snippets.

@vsky279
Last active April 9, 2017 09:03
Show Gist options
  • Save vsky279/1476ac5176738a0cb9504ce132d3c7e7 to your computer and use it in GitHub Desktop.
Save vsky279/1476ac5176738a0cb9504ce132d3c7e7 to your computer and use it in GitHub Desktop.
--------------------------------------------------------------------------------
-- 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