Skip to content

Instantly share code, notes, and snippets.

@TerryE
Created March 31, 2017 14:14
Show Gist options
  • Save TerryE/5ea4f51492468a46b095279b0fff6935 to your computer and use it in GitHub Desktop.
Save TerryE/5ea4f51492468a46b095279b0fff6935 to your computer and use it in GitHub Desktop.
ds18b20.lua
--------------------------------------------------------------------------------
-- DS18B20 one wire module for NODEMCU
-- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT
-- TerryE 26 Mar 2017
--------------------------------------------------------------------------------
-- Local variables
local modname = ...
-- DS18B20 dq and default pins
local defaultPin, pin, family = 9
local DS18B20FAMILY = 0x28
local DS1920FAMILY = 0x10 -- and DS18S20 series
local CONVERT_T
= 0x44
local READ_SCRATCHPAD = 0xBE
local dev_addrs, dev_hash
-- Used modules and functions
local table, string, ow, tmr, print, type, tostring =
table, string, ow, tmr, print, type, tostring
-- Local functions
local ow_setup, ow_search, ow_select, ow_skip, ow_read_bytes, ow_write, ow_crc8, ow_reset =
ow.setup, ow.search, ow.select, ow.skip, ow.read_bytes, ow.write, ow.crc8, ow.reset
local now = tmr.now
local debugPrint = function() return end
local MODE = 0
--------------------------------------------------------------------------------
-- Implementation
--------------------------------------------------------------------------------
local function init(dq, df)
pin = dq or pin or defaultPin
family = df or family or DS18B20FAMILY
end
local function enable_debug()
debugPrint = function (...) print(now(),' ', ...) end
end
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 search_addrs()
if not dev_addrs then
debugPrint ("Reset Status = ", ow_reset(pin))
ow_setup(pin)
debugPrint ('starting search')
ow.reset_search(pin)
ow.target_search(pin, family)
local addr = ow_search(pin)
dev_addrs, dev_hash = {}, {}
while addr do
debugPrint ('enter scan loop')
if addr:byte(8) == ow_crc8(addr:sub(1,7)) then
dev_hash[addr] = true
dev_addrs[#dev_addrs+1] = addr
end
debugPrint ("search returned ", to_string(addr), (dev_hash[addr] and 'found' or 'invalid CRC'))
addr = ow_search(pin)
tmr.wdclr()
end
debugPrint ('end of scan')
ow.depower(pin)
end
return dev_addrs
end
local function save_addrs()
if not dev_addrs then search_addrs() end
local addr_list = {}
for i =1, #dev_addrs do addr_list[i] = to_string(dev_addrs[i], true) end
local save_statement = 'return "ds18b20", {' .. table.concat(addr_list, ',') .. '}'
debugPrint (save_statement)
local save_file = file.open("ds18b20_save.lc","w")
save_file:write(string.dump(loadstring(save_statement)))
save_file:close()
end
local function get_addrs()
debugPrint ("Geting Addreses")
local s,check,a = pcall(dofile, "ds18b20_save.lc")
if s and check == "ds18b20" then
dev_addrs, dev_hash = a, {}
for i = 1, #a do dev_hash[a[i]] = true end
else
dev_addrs = nil
save_addrs()
end
debugPrint (#dev_addrs, "addreses found")
return dev_addrs
end
local function convert_T(addr)
if not dev_addrs then
get_addrs()
end
if addr ~= true and not dev_hash[addr] then
debugPrint ("Unknown address ", to_string(addr))
return nil
end
ow_reset(pin)
ow_setup(pin)
if addr == true then
ow_skip(pin)
else
ow_select(pin, addr)
end
ow_write(pin, CONVERT_T, MODE)
debugPrint ("Convert issued to ", ((addr == true) and "*" or to_string(addr)))
return true
end
local function read(addr, unit)
if dev_addrs and dev_hash[addr] then
ow_reset(pin)
ow_setup(pin)
ow_select(pin, addr)
ow_write(pin, READ_SCRATCHPAD, MODE)
local data = ow_read_bytes(pin,9)
if ow_crc8(data:sub(1,8)) == data:byte(9) then
local t = (data:byte(1) + data:byte(2) * 256)
-- t is actually signed so process the sign bit and adjust for fractional bits
-- the DS18B20 family has 4 fractional bits and the DS18S20s, 1 fractional bit
t = ((t <= 32767) and t or t - 65536) *
((addr:byte(1) == DS18B20FAMILY) and 625 or 5000)
if(unit == nil or unit == 'C') then
t = t * 0.0001
elseif(unit == 'F') then
t = t * 0.00018 + 32
elseif(unit == 'K') then
t = t * 0.0001 + 273.15
else
return nil
end
debugPrint(to_string(addr),"data read ",to_string(data:sub(1,8)), t)
return t
else
debugPrint(to_string(addr),"data read ",to_string(data:sub(1,8)), "CRC is not valid!")
end
else
debugPrint(to_string(addr),"unkown address")
end
return nil
end
-- Set module name as parameter of require and return module table
local M = {
C = 'C', F = 'F', K = 'K',
init = init, enable_debug = enable_debug, to_string = to_string,
search_addrs = search_addrs, save_addrs = save_addrs, get_addrs = get_addrs,
convert_T = convert_T, read = read,
}
_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