-->
Page 1 of 8

Example - measure temperature using 1-wire DS1820

PostPosted: Sun Dec 07, 2014 10:50 am
by sancho
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:
Code: Select allpin = 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)

Re: Example - measure temperature using 1-wire DS1820

PostPosted: Sun Dec 07, 2014 4:21 pm
by jourdant
Great thanks! Did you need to do anything special for calibration?

Re: Example - measure temperature using 1-wire DS1820

PostPosted: Mon Dec 08, 2014 12:55 am
by sancho
No calibration necessary - the DS chips comes pre-calibrated wit .5 deg precision and the output is digital. So almost plug-and-play ;)

Re: Example - measure temperature using 1-wire DS1820

PostPosted: Tue Dec 09, 2014 4:03 am
by hipsu
Being a lua noob this was a good starting point for my project.
Only problem is it does not work with negative numbers, there needs to be some bitshifting, but im unable to solve the problem my self seems this lua does not include the needed functions to acomplish this

Edit: -0.125 shows up as 4095.9375