Example - measure temperature using 1-wire DS1820
Posted: Sun Dec 07, 2014 10:50 am
Thanks to the newest nodeMCU firmware, the esp is now able to measure the temperature using Dallas 1-wire DS18S20 and DS18B20.
The original (and outdated DS1820) is not tested as I no longer have such chip.
The recommended resistor for pull-up is 2k7, but I tested everything from 5k6 to 1k and everything works just fine.
The delay in the code (1 second) can be lowered to 780ms, but it caused problems for me when more than 3 sensors were connected, so I extended it to full 1 second - now it works just fine.
Thanks to the feedback on this thread, I re-wrote the program a bit and fixed multiple issues - more sensors are reported, negative temperatures are handled correctly, DS18S20 works OK with better resolution, ...
Here is the fixed code:
The original (and outdated DS1820) is not tested as I no longer have such chip.
The recommended resistor for pull-up is 2k7, but I tested everything from 5k6 to 1k and everything works just fine.
The delay in the code (1 second) can be lowered to 780ms, but it caused problems for me when more than 3 sensors were connected, so I extended it to full 1 second - now it works just fine.
Thanks to the feedback on this thread, I re-wrote the program a bit and fixed multiple issues - more sensors are reported, negative temperatures are handled correctly, DS18S20 works OK with better resolution, ...
Here is the fixed code:
Code: Select all
pin = 4
ow.setup(pin)
counter=0
temps={}
function bxor(a,b)
local r = 0
for i = 0, 31 do
if ( a % 2 + b % 2 == 1 ) then
r = r + 2^i
end
a = a / 2
b = b / 2
end
return r
end
function getTemp()
addr = ow.reset_search(pin)
repeat
tmr.wdclr()
if (addr ~= nil) then
crc = ow.crc8(string.sub(addr,1,7))
if (crc == addr:byte(8)) then
if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then
sensor = ""
for j = 1,8 do sensor = sensor .. string.format("%02x", addr:byte(j)) end
ow.reset(pin)
ow.select(pin, addr)
ow.write(pin, 0x44, 1)
tmr.delay(1000000)
present = ow.reset(pin)
ow.select(pin, addr)
ow.write(pin,0xBE, 1)
data = nil
data = string.char(ow.read(pin))
for i = 1, 8 do
data = data .. string.char(ow.read(pin))
end
crc = ow.crc8(string.sub(data,1,8))
if (crc == data:byte(9)) then
t = (data:byte(1) + data:byte(2) * 256)
if (t > 32768) then
t = (bxor(t, 0xffff)) + 1
t = (-1) * t
end
t = t * 625
if(addr:byte(1) == 0x10) then
-- we have DS18S20, the measurement must change
t = t * 8; -- compensating for the 9-bit resolution only
t = t - 2500 + ((10000 * (data:byte(8) - data:byte(7))) / data:byte(8))
end
temps[sensor] = t
print(sensor .. ": " .. t)
end
tmr.wdclr()
end
end
end
addr = ow.search(pin)
until(addr == nil)
end
srv=net.createServer(net.TCP)
srv:listen(8080,function(conn)
getTemp()
output = wifi.sta.getmac() .. "\n"
for sensorID, temperature in pairs(temps) do
t1 = temperature / 10000
t2 = (temperature >= 0 and temperature % 10000) or (10000 - temperature % 10000)
output = output .. sensorID .. "\t"
output = output .. t1 .. "." .. string.format("%04d", t2) .. "\n"
end
conn:send(output)
conn:on("sent",function(conn) conn:close() end)
end)