• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Решено не могу подружить esp8622 с ds18b20

blak soft

Member
это мой первый опыт
никак не могу сделать простой термометр
использую
1. NodeMCU Lua V2 wi-fi на базе ESP8266 (CP2102)
2. Датчик температуры DS18B20 в герметичном корпусе

нашел листинги
ds18b20.lua
Код:
--------------------------------------------------------------------------------
-- DS18B20 one wire module for NODEMCU
-- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT
-- Vowstar <vowstar@nodemcu.com>
-- 2015/02/14 sza2 <sza2trash@gmail.com> Fix for negative values
--------------------------------------------------------------------------------

-- Set module name as parameter of require
local modname = ...
local M = {}
_G[modname] = M
--------------------------------------------------------------------------------
-- Local used variables
--------------------------------------------------------------------------------
-- DS18B20 dq pin
local pin = nil
-- DS18B20 default pin
local defaultPin = 9
--------------------------------------------------------------------------------
-- Local used modules
--------------------------------------------------------------------------------
-- Table module
local table = table
-- String module
local string = string
-- One wire module
local ow = ow
-- Timer module
local tmr = tmr
-- Limited to local environment
setfenv(1,M)
--------------------------------------------------------------------------------
-- Implementation
--------------------------------------------------------------------------------
C = 'C'
F = 'F'
K = 'K'
function setup(dq)
  pin = dq
  if(pin == nil) then
    pin = defaultPin
  end
  ow.setup(pin)
end

function addrs()
  setup(pin)
  tbl = {}
  ow.reset_search(pin)
  repeat
    addr = ow.search(pin)
    if(addr ~= nil) then
      table.insert(tbl, addr)
    end
    tmr.wdclr()
  until (addr == nil)
  ow.reset_search(pin)
  return tbl
end

function readNumber(addr, unit)
  result = nil
  setup(pin)
  flag = false
  if(addr == nil) then
    ow.reset_search(pin)
    count = 0
    repeat
      count = count + 1
      addr = ow.search(pin)
      tmr.wdclr()
    until((addr ~= nil) or (count > 100))
    ow.reset_search(pin)
  end
  if(addr == nil) then
    return result
  end
  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.")
      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)
        if (t > 32767) then
          t = t - 65536
        end

        if (addr:byte(1) == 0x28) then
          t = t * 625  -- DS18B20, 4 fractional bits
        else
          t = t * 5000 -- DS18S20, 1 fractional bit
        end

        if(unit == nil or unit == 'C') then
          -- do nothing
        elseif(unit == 'K') then
          t = t + 2731500
        else
          return nil
        end
        -- Fix by noss. Returns formatted string.
        --t = t / 10000

        t1 = t / 10000
        t2 = (t >= 0 and t % 10000) or (10000 - t % 10000)
        t = t1 .. "."..string.format("%04d", t2)

        --end of fix
      
        return t
      end
      tmr.wdclr()
    else
    -- print("Device family is not recognized.")
    end
  else
  -- print("CRC is not valid!")
  end
  return result
end

function read(addr, unit)
  t = readNumber(addr, unit)
  if (t == nil) then
    return nil
  else
    return t
  end
end

-- Return module table
return M
main.lua
Код:
t = require('ds18b20')
-- ESP-01 GPIO Mapping
gpio0 = 3
t.setup(gpio0)
function getTmp(t)
local tempr = t.read()
print("Temp:"..tempr.." C\n")
end
tmr.alarm(1, 1000,1, function() getTmp(t) end )
init.lua
Код:
tmr.register (0, 15000, tmr.ALARM_SINGLE, function (t) tmr.unregister (0); print ( "запуск файла main.lui"); dofile ( "main.lua") end)
tmr.start (0)
заливаю через программу "ESPlorer" но выдает ошибку
unprotected error in call to Lua API (ds18b20.lua:44: attempt to index upvalue '?' (a nil value))

перед запуском программы выдает следующее
ets Jan 8 2013,rst cause:2, boot mode:(3,7)
load 0x40100000, len 27556, room 16
tail 4
chksum 0xf8
load 0x3ffe8000, len 2440, room 4
tail 4
chksum 0x48
load 0x3ffe8988, len 136, room 4
tail 4
chksum 0x4b
csum 0x4b
NodeMCU custom build by frightanic.com
branch: dev
commit: bb9a5977d3eddd65b653b76dc4769cfd35be630e
SSL: false
modules: bme280,cron,crypto,file,gpio,http,i2c,net,node,rtctime,sntp,spi,tmr,u8g2,uart,websocket,wifi,wifi_monitor,wps
build created on 2018-11-18 07:57
powered by Lua 5.1.4 on SDK 2.2.1(6ab97e9)

подскажите что делаю не так
 

blak soft

Member
попробовал еще один вариант
ds18b20.lua
Код:
--------------------------------------------------------------------------------
-- DS18B20 one wire module for NODEMCU
-- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT
-- @voborsky, @devsaurus, TerryE  26 Mar 2017
----------------------------------------------------------------------------------------------------------------------------------------------------------------
local modname = ...

-- Used modules and functions
local table, string, ow, tmr, print, type, tostring, pcall, ipairs =
      table, string, ow, tmr, print, type, tostring, pcall, ipairs
-- Local functions
local ow_setup, ow_search, ow_select, ow_read, ow_read_bytes, ow_write, ow_crc8, ow_reset, ow_reset_search, ow_skip, ow_depower =
      ow.setup, ow.search, ow.select, ow.read, ow.read_bytes, ow.write, ow.crc8, ow.reset, ow.reset_search, ow.skip, ow.depower
local node_task_post, node_task_LOW_PRIORITY = node.task.post, node.task.LOW_PRIORITY
local string_char, string_dump = string.char, string.dump
local now, tmr_create, tmr_ALARM_SINGLE = tmr.now, tmr.create, tmr.ALARM_SINGLE
local table_sort, table_concat = table.sort, table.concat
local math_floor = math.floor
local file_open = file.open

table, string, tmr, ow = nil, nil, nil, nil

local DS18B20FAMILY   = 0x28
local DS1920FAMILY    = 0x10  -- and DS18S20 series
local CONVERT_T       = 0x44
local READ_SCRATCHPAD = 0xBE
local READ_POWERSUPPLY= 0xB4
local MODE = 1

local pin, cb, unit = 3
local status = {}

local debugPrint = function() return end

--------------------------------------------------------------------------------
-- Implementation
--------------------------------------------------------------------------------
local function enable_debug()
  debugPrint = function (...) print(now(),' ', ...) end
end

local function to_string(addr, esc)
  if type(addr) == 'string' and #addr == 8 then
    return ( esc == true and
             '"\\%u\\%u\\%u\\%u\\%u\\%u\\%u\\%u"' or
             '%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(addr:byte(1,8))
  else
    return tostring(addr)
  end
end

local function readout(self)
  local next = false
  local sens = self.sens
  local temp = self.temp
  for i, s in ipairs(sens) do
    if status[i] == 1 then
      ow_reset(pin)
      local addr = s:sub(1,8)
      ow_select(pin, addr)   -- select the  sensor
      ow_write(pin, READ_SCRATCHPAD, MODE)
      data = ow_read_bytes(pin, 9)

      local t=(data:byte(1)+data:byte(2)*256)
      -- t is actually signed so process the sign bit and adjust for fractional bits
      -- 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)
     
      if 1/2 == 0 then
        -- integer version
        if unit == 'F' then
          t = (t * 18)/10 + 320000
        elseif unit == 'K' then
          t = t + 2731500
        end     
        local sgn = t<0 and -1 or 1
        local tA = sgn*t
        local tH=tA/10000
        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)
          status[i] = 2
        end
        -- end integer version
      else
        -- float version
        if t and (math_floor(t/10000)~=85) then
          t = t / 10000
          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)
          status[i] = 2
        end
        -- end float version
      end
    end
    next = next or status[i] == 0
  end
  if next then
    node_task_post(node_task_LOW_PRIORITY, function() return conversion(self) end)
  else
    --sens = {}
    if cb then
      node_task_post(node_task_LOW_PRIORITY, function() return cb(temp) end)
    end
  end
end

local function conversion(self)
  local sens = self.sens
  local powered_only = true
  for _, s in ipairs(sens) do powered_only = powered_only and s:byte(9) ~= 1 end
  if powered_only then
    debugPrint("starting conversion: all sensors")
    ow_reset(pin)
    ow_skip(pin)  -- select the sensor
    ow_write(pin, CONVERT_T, MODE)  -- and start conversion
    for i, s in ipairs(sens) do status[i] = 1 end
  else
    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 " ")
        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
      end
    end
  end
  tmr_create():alarm(750, tmr_ALARM_SINGLE, function() return readout(self) end)
end

local function _search(self, lcb, lpin, search, save)
  self.temp = {}
  if search then self.sens = {}; status = {} end
  local temp = self.temp
  local sens = self.sens
  pin = lpin or pin
 
  local addr
  if not search and #sens == 0 then
    -- load addreses if available
    debugPrint ("geting addreses from flash")
    local s,check,a = pcall(dofile, "ds18b20_save.lc")
    if s and check == "ds18b20" then
      for i = 1, #a do sens[i] = a[i] end
    end
    debugPrint (#sens, "addreses found")
  end
 
  ow_setup(pin)
  if search or #sens == 0 then
    ow_reset_search(pin)
    -- ow_target_search(pin,0x28)
    -- search the first device
    addr = ow_search(pin)
  else
    for i, s 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
        ow_reset(pin)
        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 " ")
      end
      addr = ow_search(pin)
      node_task_post(node_task_LOW_PRIORITY, cycle)
    else
      ow_depower(pin)
      -- place powered sensors first
      table_sort(sens, function(a, b) return a:byte(9)<b:byte(9) end) -- parasite
      -- save sensor addreses
      if save then
        debugPrint ("saving addreses to flash")
       
        local addr_list = {}
        for i =1, #sens do
          local s = sens[i]
          addr_list[i] = to_string(s:sub(1,8), true)..('.."\\%u"'):format(s:byte(9))
        end
        local save_statement = 'return "ds18b20", {' .. table_concat(addr_list, ',') .. '}'       
        debugPrint (save_statement)
        local save_file = file_open("ds18b20_save.lc","w")
        save_file:write(string_dump(loadstring(save_statement)))
        save_file:close()
      end
      -- end save sensor addreses
      if lcb then node_task_post(node_task_LOW_PRIORITY, lcb) end
    end
  end
  cycle()
end

local function read_temp(self, lcb, lpin, lunit, force_search, save_search)
  cb, unit = lcb, lunit or unit
  _search(self, function() return conversion(self) end, lpin, force_search, save_search)
end
-- Set module name as parameter of require and return module table
local M = {
  sens = {},
  temp = {},
  C = 'C', F = 'F', K = 'K',
  read_temp = read_temp, enable_debug = enable_debug
}
_G[modname or 'ds18b20'] = M
return M
выдает ошибку
unprotected error in call to Lua API (ds18b20.lua:14: attempt to index global 'ow' (a nil value))
 

blak soft

Member
пробовал еще этот вариант
main.lua
Код:
local ow_pin = 3
ds18b20.setup(ow_pin)

-- read all sensors and print all measurement results
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
    end,{});

-- read only sensors with family type 0x28 and print all measurement results
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
    end,{},0x28);

-- save device roms in a variable
local addr = {}
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        addr[ind] = {string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)"))}
    end,{});

-- read only sensors listed in the variable addr
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
    end,addr);

-- print only parasitic sensors
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        if (par == 1) then
            print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
        end
    end,{});

-- print if temperature is greater or less than a defined value
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        if (t > 25) then
            print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
        end
        if (t < 20) then
            print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
        end
    end,{});
 

blak soft

Member
ds18b20.lua

пример взял отсюда

выдает ошибку

main.lua:2: attempt to index global 'ds18b20' (a nil value)
я подозреваю что в файле main.lua во второй строке ошибка но как ее исправить
и еще один вопрос если датчик ds18b20 не истравен что должна показать программа
 

Вложения

nikolz

Well-known member
пробовал еще этот вариант
main.lua
Код:
local ow_pin = 3
ds18b20.setup(ow_pin)


            print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
        end
    end,{});
вы не подключили модуль ds1820.lua
поэтому и ругается
а файл который вы приложили - это программа на СИ для VM Lua. Она нужна если будете собирать свою прошивку луа.
-------------------------
В вашей прошивке нет модуля ds1820 поэтому у Вас и не работает ничего.
modules: bme280,cron,crypto,file,gpio,http,i2c,net,node,rtctime,sntp,spi,tmr,u8g2,uart,websocket,wifi,wifi_monitor,wps
надо собрать новую на сайте (не помню название поищите в инете или на форуме)
 

blak soft

Member
спасибо за подсказку пересобрал прошивку залил файл
Код:
local ow_pin = 3
ds18b20.setup(ow_pin)

-- read all sensors and print all measurement results
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
    end,{});

-- read only sensors with family type 0x28 and print all measurement results
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
    end,{},0x28);

-- save device roms in a variable
local addr = {}
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        addr[ind] = {string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)"))}
    end,{});

-- read only sensors listed in the variable addr
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
    end,addr);

-- print only parasitic sensors
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        if (par == 1) then
            print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
        end
    end,{});

-- print if temperature is greater or less than a defined value
ds18b20.read(
    function(ind,rom,res,temp,tdec,par)
        if (t > 25) then
            print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
        end
        if (t < 20) then
            print(ind,string.format("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",string.match(rom,"(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)")),res,temp,tdec,par)
        end
    end,{});
ошибку не выдает но и на экран ничего не выводит
датчик пробовал уже ко всем ножкам подключать
и ещевопрос если переподключить датчик достаточно нажать кнопку ресет для повторного запуска или нет
 

blak soft

Member
а как можно проверить ds18b20 на работоспособность у меня в гермитичном корпусе
цеплял по схеме и "local ow_pin = 3" поменял на "local ow_pin = 2"
 

nikolz

Well-known member
а как можно проверить ds18b20 на работоспособность у меня в гермитичном корпусе
цеплял по схеме
почти уверен, что нормальная
у меня их более десятка и все работаю исправно.
проверить можно осциллографом или логическим анализатором
посмотреть на шине (пине)
 

blak soft

Member
А можно какой нибудь простой пример чтобы температуру с датчика снять
 
Сверху Снизу