ds18b20.lua 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. --------------------------------------------------------------------------------
  2. -- DS18B20 one wire module for NODEMCU
  3. -- by @voborsky, @devsaurus
  4. -- encoder module is needed only for debug output; lines can be removed if no
  5. -- debug output is needed and/or encoder module is missing
  6. --
  7. -- by default the module is for integer version, comment integer version and
  8. -- uncomment float version part for float version
  9. --------------------------------------------------------------------------------
  10. return({
  11. pin=3,
  12. sens={},
  13. temp={},
  14. conversion = function(self)
  15. local pin = self.pin
  16. for i,s in ipairs(self.sens) do
  17. if s.status == 0 then
  18. print("starting conversion:", encoder.toHex(s.addr), s.parasite == 1 and "parasite" or " ")
  19. ow.reset(pin)
  20. ow.select(pin, s.addr) -- select the sensor
  21. ow.write(pin, 0x44, 1) -- and start conversion
  22. s.status = 1
  23. if s.parasite == 1 then break end -- parasite sensor blocks bus during conversion
  24. end
  25. end
  26. tmr.create():alarm(750, tmr.ALARM_SINGLE, function() self:readout() end)
  27. end,
  28. readTemp = function(self, cb, lpin)
  29. if lpin then self.pin = lpin end
  30. local pin = self.pin
  31. self.cb = cb
  32. self.temp={}
  33. ow.setup(pin)
  34. self.sens={}
  35. ow.reset_search(pin)
  36. -- ow.target_search(pin,0x28)
  37. -- search the first device
  38. local addr = ow.search(pin)
  39. -- and loop through all devices
  40. while addr do
  41. -- search next device
  42. local crc=ow.crc8(string.sub(addr,1,7))
  43. if (crc==addr:byte(8)) and ((addr:byte(1)==0x10) or (addr:byte(1)==0x28)) then
  44. ow.reset(pin)
  45. ow.select(pin, addr) -- select the found sensor
  46. ow.write(pin, 0xB4, 1) -- Read Power Supply [B4h]
  47. local parasite = (ow.read(pin)==0 and 1 or 0)
  48. table.insert(self.sens,{addr=addr, parasite=parasite, status=0})
  49. print("contact: ", encoder.toHex(addr), parasite == 1 and "parasite" or " ")
  50. end
  51. addr = ow.search(pin)
  52. tmr.wdclr()
  53. end
  54. -- place powered sensors first
  55. table.sort(self.sens, function(a,b) return a.parasite<b.parasite end)
  56. node.task.post(node.task.MEDIUM_PRIORITY, function() self:conversion() end)
  57. end,
  58. readout=function(self)
  59. local pin = self.pin
  60. local next = false
  61. if not self.sens then return 0 end
  62. for i,s in ipairs(self.sens) do
  63. -- print(encoder.toHex(s.addr), s.status)
  64. if s.status == 1 then
  65. ow.reset(pin)
  66. ow.select(pin, s.addr) -- select the sensor
  67. ow.write(pin, 0xBE, 0) -- READ_SCRATCHPAD
  68. data = ow.read_bytes(pin, 9)
  69. local t=(data:byte(1)+data:byte(2)*256)
  70. if (t > 0x7fff) then t = t - 0x10000 end
  71. if (s.addr:byte(1) == 0x28) then
  72. t = t * 625 -- DS18B20, 4 fractional bits
  73. else
  74. t = t * 5000 -- DS18S20, 1 fractional bit
  75. end
  76. if 1/2 == 0 then
  77. -- integer version
  78. local sgn = t<0 and -1 or 1
  79. local tA = sgn*t
  80. local tH=tA/10000
  81. local tL=(tA%10000)/1000 + ((tA%1000)/100 >= 5 and 1 or 0)
  82. if tH and (tH~=85) then
  83. self.temp[s.addr]=(sgn<0 and "-" or "")..tH.."."..tL
  84. print(encoder.toHex(s.addr),(sgn<0 and "-" or "")..tH.."."..tL)
  85. s.status = 2
  86. end
  87. -- end integer version
  88. else
  89. -- float version
  90. if t and (math.floor(t/10000)~=85) then
  91. self.temp[s.addr]=t/10000
  92. print(encoder.toHex(s.addr), t)
  93. s.status = 2
  94. end
  95. -- end float version
  96. end
  97. end
  98. next = next or s.status == 0
  99. end
  100. if next then
  101. node.task.post(node.task.MEDIUM_PRIORITY, function() self:conversion() end)
  102. else
  103. self.sens = nil
  104. if self.cb then
  105. node.task.post(node.task.MEDIUM_PRIORITY, function() self.cb(self.temp) end)
  106. end
  107. end
  108. end
  109. })