Support DS18S20 and fix negative temp handling

The DS18S20 has only 1 fractional bit whereas DS18B20 has 4, and their
temperature register alignment differs. Check the family code to choose
the correct multiplier for both devices.

Closes #610

Negative temperatures (less than 0°C) are returned as a sign-extended
two's complement number. Subtract 0x10000 to recover the proper
negative value.

Signed-off-by: Nick Andrew <nick@nick-andrew.net>
This commit is contained in:
Nick Andrew 2015-11-16 23:32:20 +11:00
parent 340edbbe2f
commit 0a7b730e23
2 changed files with 38 additions and 13 deletions

View File

@ -1,5 +1,5 @@
--' --'
-- 18b20 one wire example for NODEMCU -- ds18b20 one wire example for NODEMCU (Integer firmware only)
-- NODEMCU TEAM -- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT -- LICENCE: http://opensource.org/licenses/MIT
-- Vowstar <vowstar@nodemcu.com> -- Vowstar <vowstar@nodemcu.com>
@ -40,10 +40,30 @@ else
crc = ow.crc8(string.sub(data,1,8)) crc = ow.crc8(string.sub(data,1,8))
print("CRC="..crc) print("CRC="..crc)
if (crc == data:byte(9)) then if (crc == data:byte(9)) then
t = (data:byte(1) + data:byte(2) * 256) * 625 t = (data:byte(1) + data:byte(2) * 256)
t1 = t / 10000
t2 = t % 10000 -- handle negative temperatures
print("Temperature= "..t1.."."..t2.." Centigrade") if (t > 0x7fff) then
t = t - 0x10000
end
if (addr:byte(1) == 0x28) then
t = t * 625 -- DS18B20, 4 fractional bits
else
t = t * 5000 -- DS18S20, 1 fractional bit
end
local sign = ""
if (t < 0) then
sign = "-"
t = -1 * t
end
-- Separate integral and decimal portions, for integer firmware only
local t1 = string.format("%d", t / 10000)
local t2 = string.format("%04u", t % 10000)
local temp = sign .. t1 .. "." .. t2
print("Temperature= " .. temp .. " Celsius")
end end
tmr.wdclr() tmr.wdclr()
until false until false

View File

@ -101,18 +101,23 @@ function readNumber(addr, unit)
if (t > 32767) then if (t > 32767) then
t = t - 65536 t = t - 65536
end end
if(unit == nil or unit == C) then
t = t * 625 if (addr:byte(1) == 0x28) then
elseif(unit == F) then t = t * 625 -- DS18B20, 4 fractional bits
t = t * 1125 + 320000 else
elseif(unit == K) then t = t * 5000 -- DS18S20, 1 fractional bit
t = t * 625 + 2731500 end
if(unit == nil or unit == 'C') then
-- do nothing
elseif(unit == 'F') then
t = t * 1.8 + 320000
elseif(unit == 'K') then
t = t + 2731500
else else
return nil return nil
end end
t = t / 10000 t = t / 10000
-- print("Temperature="..t1.."."..t2.." Centigrade")
-- result = t1.."."..t2
return t return t
end end
tmr.wdclr() tmr.wdclr()