Przeglądaj źródła

Add CRC check (#2992)

Also clean-up a nasty `ow` module example.
Lukáš Voborský 4 lat temu
rodzic
commit
cd9da6463c
2 zmienionych plików z 44 dodań i 46 usunięć
  1. 27 33
      docs/modules/ow.md
  2. 17 13
      lua_modules/ds18b20/ds18b20.lua

+ 27 - 33
docs/modules/ow.md

@@ -145,48 +145,42 @@ Issues a 1-Wire rom select command. Make sure you do the `ow.reset(pin)` first.
 #### Example
 ```lua
 -- 18b20 Example
-pin = 9
+-- 18b20 Example
+pin = 3
 ow.setup(pin)
-count = 0
-repeat
-  count = count + 1
-  addr = ow.reset_search(pin)
-  addr = ow.search(pin)
-  tmr.wdclr()
-until (addr ~= nil) or (count > 100)
+addr = ow.reset_search(pin)
+addr = ow.search(pin)
+
 if addr == nil then
-  print("No more addresses.")
+  print("No device detected.")
 else
   print(addr:byte(1,8))
-  crc = ow.crc8(string.sub(addr,1,7))
+  local 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
       print("Device is a DS18S20 family device.")
-        repeat
+      tmr.create():alarm(1000, tmr.ALARM_AUTO, function()
           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)
-          print("P="..present)
-          data = nil
-          data = string.char(ow.read(pin))
-          for i = 1, 8 do
-            data = data .. string.char(ow.read(pin))
-          end
-          print(data:byte(1,9))
-          crc = ow.crc8(string.sub(data,1,8))
-          print("CRC="..crc)
-          if crc == data:byte(9) then
-             t = (data:byte(1) + data:byte(2) * 256) * 625
-             t1 = t / 10000
-             t2 = t % 10000
-             print("Temperature="..t1.."."..t2.."Centigrade")
-          end
-          tmr.wdclr()
-        until false
+          ow.write(pin, 0x44, 1) -- convert T command
+          tmr.create():alarm(750, tmr.ALARM_SINGLE, function()
+              ow.reset(pin)
+              ow.select(pin, addr)
+              ow.write(pin,0xBE,1) -- read scratchpad command
+              local data = ow.read_bytes(pin, 9)
+              print(data:byte(1,9))
+              local crc = ow.crc8(string.sub(data,1,8))
+              print("CRC="..crc)
+              if crc == data:byte(9) then
+                 local t = (data:byte(1) + data:byte(2) * 256) * 625
+                 local sgn = t<0 and -1 or 1
+                 local tA = sgn*t
+                 local t1 = math.floor(tA / 10000)
+                 local t2 = tA % 10000
+                 print("Temperature="..(sgn<0 and "-" or "")..t1.."."..t2.." Centigrade")
+              end
+          end)
+      end)
     else
       print("Device family is not recognized.")
     end

+ 17 - 13
lua_modules/ds18b20/ds18b20.lua

@@ -69,6 +69,7 @@ local function readout(self)
       -- 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)
+      local crc, b9 = ow_crc8(string.sub(data,1,8)), data:byte(9)
 
       if 1/2 == 0 then
         -- integer version
@@ -83,22 +84,22 @@ local function readout(self)
         local tL=(tA%10000)/1000 + ((tA%1000)/100 >= 5 and 1 or 0)
 
         if tH and (t~=850000) then
-          temp[addr]=(sgn<0 and "-" or "")..tH.."."..tL
-          debugPrint(to_string(addr),(sgn<0 and "-" or "")..tH.."."..tL)
+          debugPrint(to_string(addr),(sgn<0 and "-" or "")..tH.."."..tL, crc, b9)
+          if crc==b9 then temp[addr]=(sgn<0 and "-" or "")..tH.."."..tL end
           status[i] = 2
         end
         -- end integer version
       else
         -- float version
-        if t and (math_floor(t/10000)~=85) then
-          t = t / 10000
+        t = t / 10000
+        if math_floor(t)~=85 then
           if unit == 'F' then
             t = t * 18/10 + 32
           elseif unit == 'K' then
             t = t + 27315/100
           end
-          self.temp[addr]=t
-          debugPrint(to_string(addr), t)
+          debugPrint(to_string(addr), t, crc, b9)
+          if crc==b9 then temp[addr]=t end
           status[i] = 2
         end
         -- end float version
@@ -123,19 +124,22 @@ conversion = (function (self)
   if powered_only then
     debugPrint("starting conversion: all sensors")
     ow_reset(pin)
-    ow_skip(pin)  -- select the sensor
+    ow_skip(pin)  -- skip ROM selection, talk to all sensors
     ow_write(pin, CONVERT_T, MODE)  -- and start conversion
     for i, _ in ipairs(sens) do status[i] = 1 end
   else
+    local started = false
     for i, s in ipairs(sens) do
       if status[i] == 0 then
-        local addr, parasite = s:sub(1,8), s:byte(9)
-        debugPrint("starting conversion:", to_string(addr), parasite == 1 and "parasite" or " ")
+        local addr, parasite = s:sub(1,8), s:byte(9) == 1
+        if parasite and started then break end -- do not start concurrent conversion of powered and parasite
+        debugPrint("starting conversion:", to_string(addr), parasite and "parasite" or "")
         ow_reset(pin)
         ow_select(pin, addr)  -- select the sensor
         ow_write(pin, CONVERT_T, MODE)  -- and start conversion
         status[i] = 1
-        if parasite == 1 then break end -- parasite sensor blocks bus during conversion
+        if parasite then break end -- parasite sensor blocks bus during conversion
+        started = true
       end
     end
   end
@@ -169,7 +173,6 @@ local function _search(self, lcb, lpin, search, save)
     for i, _ in ipairs(sens) do status[i] = 0 end
   end
   local function cycle()
-    debugPrint("cycle")
     if addr then
       local crc=ow_crc8(addr:sub(1,7))
       if (crc==addr:byte(8)) and ((addr:byte(1)==DS1920FAMILY) or (addr:byte(1)==DS18B20FAMILY)) then
@@ -177,8 +180,9 @@ local function _search(self, lcb, lpin, search, save)
         ow_select(pin, addr)
         ow_write(pin, READ_POWERSUPPLY, MODE)
         local parasite = (ow_read(pin)==0 and 1 or 0)
-        sens[#sens+1]= addr..string_char(parasite) -- {addr=addr, parasite=parasite, status=0}
-        debugPrint("contact: ", to_string(addr), parasite == 1 and "parasite" or " ")
+        sens[#sens+1]= addr..string_char(parasite)
+        status[#sens] = 0
+        debugPrint("contact: ", to_string(addr), parasite == 1 and "parasite" or "")
       end
       addr = ow_search(pin)
       node_task_post(node_task_LOW_PRIORITY, cycle)