• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Ошибка attempt to index global 'ds18b20'

sER

New member
Здравствуйте. Мучаю датчик температуры, получаю ошибку:
Код:
lua: dallas.lua:8: attempt to index global 'ds18b20' (a nil value)
ds18b20.lua
nodemcu-firmware/ds18b20.lua at master · nodemcu/nodemcu-firmware · GitHub

init.lua
Код:
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config("apname","password")
print(wifi.sta.getip())
dofile('dallas.lua')
dallas.lua
Код:
require('ds18b20')
gpio0 = 3
ds18b20.setup(gpio0)
function sendData()
t1=ds18b20.read()
t1=ds18b20.read()
print("Temp:"..t1.." C\n")
end
tmr.alarm(0, 60000, 1, function() sendData() end )

В чём у меня ошибка?
 

Gorodnov

New member
Во первых в прошивку должны быть включены модули 1-Wire и encoder.
Во вторых инициализация и обмен с датчиком происходят как я понял по другому.
Только вчера начал изучать ESP и тоже с этим столкнулся.
Пример как у тебя у меня тоже не работал, вылетал с этой ошибкой.
Скомпилировал прошивку и применил пример из SDK, всё сразу завелось.
Подставь этот код вместо своего в файл dallas.lua

Код:
t = require("ds18b20")
pin = 3 -- gpio0 = 3, gpio2 = 4

function readout(temp)
  for addr, temp in pairs(temp) do
    -- print(string.format("Sensor %s: %s 'C", addr, temp))
    print(string.format("Sensor %s: %s В°C", encoder.toHex(addr), temp)) -- readable address with base64 encoding is preferred when encoder module is available
  end

  -- Module can be released when it is no longer needed
  t = nil
  package.loaded["ds18b20"]=nil
end

-- t:readTemp(readout) -- default pin value is 3
t:readTemp(readout, pin)
if t.sens then
  print("Total number of DS18B20 sensors: "..table.getn(t.sens))
  for i, s in ipairs(t.sens) do
    -- print(string.format("  sensor #%d address: %s%s", i, s.addr, s.parasite == 1 and " (parasite)" or ""))
    print(string.format("  sensor #%d address: %s%s",  i, encoder.toHex(s.addr), s.parasite == 1 and " (parasite)" or "")) -- readable address with base64 encoding is preferred when encoder module is available
  end
end
 

sER

New member
Благодарю, заработало.

1-Wire я добавил,а encoder не было, собрал новую прошивку, заработало.
 

sER

New member
Подключил два датчика
Sensor 281398d70200005d: 26 В°C
Sensor 28ff57a3811603c0: 26.5 В°C

Как считать температуру только с нужного мне адреса?
 

sER

New member
Код:
-- main.lua --
tmr.alarm(0, 1000, 1, function()
if wifi.sta.getip() == nil then
print("Connecting to AP...\n")
else
ip, nm, gw=wifi.sta.getip()
print("IP Info: \nIP Address: ",ip)
print("Netmask: ",nm)
print("Gateway Addr: ",gw,'\n')
tmr.stop(0)
end
end)

text='pusto'
t = require('ds18b20')
pin = 3

-- a simple http server
srv = net.createServer(net.TCP, 30)
srv:listen(80,function(conn)
conn:on("receive",function(conn,get)
na=string.find(get,"z=");





function dallas(temp)
text=''
for addr, temp in pairs(temp) do
text = text .. string.format("Sensor %s: %s", encoder.toHex(addr), temp.."n")
end
end





function zagolovok()
con=string.find(get,"HTTP");
zag=string.sub(get, na,con-2);
if zag == "z=1" then "Первая страничка"
elseif zag == "z=sensor1" then t:readTemp(dallas, pin)
elseif zag == "z=sensor2" then text="Второй сенсор"
else text="Иная" end
end
if na~=nil then zagolovok() end

conn:send('HTTP/1.1 200 OK\n')
conn:send('Access-Control-Allow-Origin:*\n\n')
conn:send(text)
conn:on("sent", function(conn) conn:close() end)
end)
end)
Так считываю оба датчика
 

Gorodnov

New member
Глянуть смогу только вечером.
У меня немного другая задача, мне нужен наглядный график работы термометров.
Вот что у меня будет.
 

Вложения

sER

New member
Модуль ds18b20.lua показывает отрицательную температуру?


HTML:
<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      google.charts.load('current', {'packages':['corechart']});
      google.charts.setOnLoadCallback(drawChart);

      function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Температура', 'Морозильная камера', 'Холодильная камера'],
          ['15:00:00',  -10,      -3],
          ['15:05:00',  -12,      -5],
          ['15:10:00',  -15,      -7],
          ['15:15:00',  -9,      -10]
        ]);

        var options = {
          title: 'Датчики температуры',
          hAxis: {title: 'Температура',  titleTextStyle: {color: '#333'}},
          vAxis: {minValue: 0}
        };

        var chart = new google.visualization.AreaChart(documыent.getElementById('chart_div'));
        chart.draw(data, options);
      }
    </script>
  </head>
  <body>
    <div id="chart_div" style="width: 100%; height: 500px;"></div>
  </body>
</html>
 

Gorodnov

New member
Да показывает.
Вот модуль целиком.
В строке 78 проверяется знак, и если он присутствует, то в строке 79 показания поправляются для отображения отрицательного результата.

Код:
--------------------------------------------------------------------------------
-- DS18B20 one wire module for NODEMCU
-- by @voborsky, @devsaurus
-- encoder module is needed only for debug output; lines can be removed if no
-- debug output is needed and/or encoder module is missing
--
-- by default the module is for integer version, comment integer version and
-- uncomment float version part for float version
--------------------------------------------------------------------------------

return({
  pin=3,
  sens={},
  temp={},

  conversion = function(self)
    local pin = self.pin
    for i,s in ipairs(self.sens) do
      if s.status == 0 then
        print("starting conversion:", encoder.toHex(s.addr), s.parasite == 1 and "parasite" or " ")
        ow.reset(pin)
        ow.select(pin, s.addr)  -- select the sensor
        ow.write(pin, 0x44, 1)  -- and start conversion
        s.status = 1
        if s.parasite == 1 then break end -- parasite sensor blocks bus during conversion
      end
    end
    tmr.create():alarm(750, tmr.ALARM_SINGLE, function() self:readout() end)
  end,

  readTemp = function(self, cb, lpin)
    if lpin then self.pin = lpin end
    local pin = self.pin
    self.cb = cb
    self.temp={}
    ow.setup(pin)

    self.sens={}
    ow.reset_search(pin)
    -- ow.target_search(pin,0x28)
    -- search the first device
    local addr = ow.search(pin)
    -- and loop through all devices
    while addr do
      -- search next device
      local crc=ow.crc8(string.sub(addr,1,7))
      if (crc==addr:byte(8)) and ((addr:byte(1)==0x10) or (addr:byte(1)==0x28)) then
        ow.reset(pin)
        ow.select(pin, addr)   -- select the found sensor
        ow.write(pin, 0xB4, 1) -- Read Power Supply [B4h]
        local parasite = (ow.read(pin)==0 and 1 or 0)
        table.insert(self.sens,{addr=addr, parasite=parasite, status=0})
        print("contact: ", encoder.toHex(addr), parasite == 1 and "parasite" or " ")
      end

      addr = ow.search(pin)
      tmr.wdclr()
    end

    -- place powered sensors first
    table.sort(self.sens, function(a,b) return a.parasite<b.parasite end)

    node.task.post(node.task.MEDIUM_PRIORITY, function() self:conversion() end)
  end,

  readout=function(self)
    local pin = self.pin
    local next = false
        if not self.sens then return 0 end
    for i,s in ipairs(self.sens) do
      -- print(encoder.toHex(s.addr), s.status)
      if s.status == 1 then
        ow.reset(pin)
        ow.select(pin, s.addr)   -- select the  sensor
        ow.write(pin, 0xBE, 0) -- READ_SCRATCHPAD
        data = ow.read_bytes(pin, 9)

        local t=(data:byte(1)+data:byte(2)*256)
        if (t > 0x7fff) then t = t - 0x10000 end
        if (s.addr:byte(1) == 0x28) then
          t = t * 625  -- DS18B20, 4 fractional bits
        else
          t = t * 5000 -- DS18S20, 1 fractional bit
        end

        if 1/2 == 0 then
          -- integer version
          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 (tH~=85) then
            self.temp[s.addr]=(sgn<0 and "-" or "")..tH.."."..tL
            print(encoder.toHex(s.addr),(sgn<0 and "-" or "")..tH.."."..tL)
            s.status = 2
          end
          -- end integer version
        else
          -- float version
          if t and (math.floor(t/10000)~=85) then
            self.temp[s.addr]=t/10000
            print(encoder.toHex(s.addr), t)
            s.status = 2
          end
          -- end float version
        end
      end
      next = next or s.status == 0
    end
    if next then
      node.task.post(node.task.MEDIUM_PRIORITY, function() self:conversion()  end)
    else
      self.sens = nil
      if self.cb then
        node.task.post(node.task.MEDIUM_PRIORITY, function()  self.cb(self.temp) end)
      end
    end

  end
})
 

sER

New member
Приветствую. Удалось считать датчики по отдельности (адресу)?
 

sER

New member
У Вас всегда считывается температура или модуль уходит в перезагрузку? PANIC...
 
Сверху Снизу