ESP-8266/ESP32 NodeMCU Lua: азы программирования.

Тема в разделе "ESP8266, ESP32", создана пользователем ИгорьК, 25 июл 2017.

  1. ИгорьК

    ИгорьК Гуру

    Такой годится?

    А в чем проблема в целом? DS18b20 дает одну сотую. Другое дело, что отклонение у него ±0.5°C Accuracy from -10°C to +70°C и это типовое для доступных датчиков.
     
  2. obuhanoe

    obuhanoe Гик

    Может я неверно сформулировал - хотелось бы чтобы температура отображалась с десятичными значениями, то есть увеличение уменьше ние было не по 0,5 градуса, а по 0,1

    Код (Text):
    20.1
    20.2
    20.8
    25.6
     
  3. ИгорьК

    ИгорьК Гуру

    И в чем проблема. Ds18b20 будет выдавать 20.11, 20.12. А уж 20.1 - это стандарт.
     
  4. obuhanoe

    obuhanoe Гик

    Видимо я где то накосячил - и у меня если выводится информация то так:
    1. 25.5
    2. 26,0
    3. 26.5 и так далее

    Буду разбираться где накосячил )
     
  5. ИгорьК

    ИгорьК Гуру

    Полагаю - нигде. Если это DS18b20, то он выдает данные с разрешением от 9 до 12 бит. Видимо вы когда-то изменили это разрешение в меньшую сторону и датчик запомнил это.

    upload_2023-7-11_14-24-4.png
     
  6. obuhanoe

    obuhanoe Гик

    В том то и дело не изменял, видимо пришел с таким разрешением.
    А изменить разрешение как-то можно?
     
  7. ИгорьК

    ИгорьК Гуру

    Если это нормальный датчик, то можно. Если это сильно подделка, то не известно.
    По умолчанию датчик работает в 12-битном режиме.
     
  8. ИгорьК

    ИгорьК Гуру

    Разглядите датчик: у вас точно ds18B20 а не DS18S20?

    upload_2023-7-11_15-40-6.png
     
  9. obuhanoe

    obuhanoe Гик

    покупался как ds18b20
    Нашел на просторах интернета как посмотреть разрешение, стоит 9 бит.
    Нашел код, который устанавливает в 12 бит
    Код (Text):
    ow.reset(pin)
          ow.select(pin, addr)
          ow.write(pin,0x4E,1)
          ow.write(pin,0x00,1)
          ow.write(pin,0x00,1)
          ow.write(pin,0x3F,1)
          ow.reset(pin)
          ow.select(pin, addr)
          ow.write(pin,0x48,1)
    , но не могу разобраться с адресом

    взял Вашу библиотеку где читается адреса датчиков, у меня выводится какая то ерунда:
    Код (Lua):
        ow.setup(M.pin)
        ow.reset_search(M.pin)
        -- в цикле ищем все датчики
        repeat
            local adr = ow.search(M.pin)
            if(adr ~= nil) then
                print(adr)
                -- заталкиваем адреса в таблицу
                table.insert(M.adrtbl, adr)
            end
        until (adr == nil)
        -- стряхиваем поиск с шины
        ow.reset_search(M.pin)
    Выводит так: (яАЃXE


    Даже упрощенно решил проверить:
    Код (Lua):
    ow.setup(4)
    ow.reset_search(4)
    print(ow.search(4))
    Результат тот же

    Температура через Вашу библиотеку выводится.
     
    Последнее редактирование: 11 июл 2023
  10. ИгорьК

    ИгорьК Гуру

    Что на нем написано то?
     
  11. ИгорьК

    ИгорьК Гуру

    Обзовите:"_ds18b20.lua"

    Код (Lua):
    local M={}
    M.adrtbl = {}
    M.pin = 4
    M.del = 750

    function M.getaddrs(ttable, call)
        ow.setup(M.pin)
        ow.reset_search(M.pin)
        repeat
            local adr = ow.search(M.pin)
            if(adr ~= nil) then
                table.insert(M.adrtbl, adr)
            end
        until (adr == nil)
        ow.reset_search(M.pin)
        if #M.adrtbl ~= 0 then
            M.askTemp(ttable, call)
        else
            print('No DS18b20!')
            return
        end
    end

    function M.askTemp(ttable, call)
        ow.setup(M.pin)
        for _, v in pairs(M.adrtbl) do
            ow.reset(M.pin)
            ow.select(M.pin, v)
            ow.write(M.pin, 0x44, 1)
        end
        v = nil

        tmr.create():alarm(M.del, tmr.ALARM_SINGLE, function (t)
            t = nil
            M.readResult(ttable, call)
        end)
    end

    function M.set12()
        ow.setup(M.pin)
        for _, v in pairs(M.adrtbl) do
            ow.reset(M.pin)
            ow.select(M.pin, v)
            -- ow.write(M.pin, 0x44, 1)
            ow.write(0x4E, 1)
            ow.write(0x7F, 1)
            ow.write(0xFF, 1)
            ow.write(0x60, 1)
            ow.write(0x48, 1)
            ow.reset(M.pin)
        end
    end


    function M.readResult(ttable, call)
        local data, crc, t
        for _, v in pairs(M.adrtbl) do
            ow.reset(M.pin)
            ow.select(M.pin, v)
            ow.write(M.pin,0xBE,1)
            data = ow.read_bytes(M.pin, 9)
            crc = ow.crc8(string.sub(data,1,8))
            if (crc == data:byte(9)) then
                t = (data:byte(1) + data:byte(2) * 256)
                if (t > 32767) then t = t - 65536 end
                t = t * 625 /10000
                --table.insert(ttable, t)
                -------
                local as = ""
                for ii = 1, #v do
                    local hx = string.format("%02X", (string.byte(v, ii)))
                    as = as ..hx
                end
                -- ttable[as] = t
                -- ttable[as] = string.format("%.2f",t)
                table.insert(ttable, {as, string.format("%.2f",t)})
                -------
            end
        end
        data, crc, t = nil, nil, nil
        if call then call(ttable) end
    end

    function M.getTemp(ttable, call, pin, del)
        if #M.adrtbl == 0 then
            M.pin = pin or M.pin
            M.del = del or M.del
            M.getaddrs(ttable, call)
        else
            M.askTemp(ttable, call)
        end
    end
    return M
    Накидал без проверки, данные функции взял из Интернета.
    Загрузите библиотеку, вызовите ее стандартным образом, не выгружайте в callback, попробуйте . функцию ....set12()

    Но ничего не гарантирую. Без проверки.
     
    Последнее редактирование: 11 июл 2023
  12. obuhanoe

    obuhanoe Гик

    не читаемо к сожалению.
    сохранил в файл, загрузил через upoad
    вызываю в левом окне через Block - верно?
    И что означает не выгружайте в callback ?
     
  13. ИгорьК

    ИгорьК Гуру

    Код (Lua):
    do
        temp = {}
        pin = 4
        del = 750
        function myWork()
            print("Got DS18b20: "..#temp)
            table.foreach(temp,
                function(k,v)
                    print("no", k)
                    table.foreach(v, print)
                end)
            -- ds = nil
           -- package.loaded["_ds18b20"]=nil
           ds.set12()
        end
        ds = require('_ds18b20')
        ds.getTemp(temp, myWork, pin, del )
    end
     
    Просто исполните этот код два раза. На втором разе показания МОГУТ стать 12-битными.
     
  14. obuhanoe

    obuhanoe Гик

    Падает на этой строке:
    Код (Text):
     ow.write(0x4E, 1)
    с текстом

    Код (Text):
    ds18b20_M12.lua:49: ow 78 does not exist
    stack traceback:
        [C]: in function 'write'
        ds18b20_M12.lua:49: in function 'set12'
        stdin:14: in function <stdin:5>
        ds18b20_M12.lua:88: in function 'readResult'
        ds18b20_M12.lua:37: in function <ds18b20_M12.lua:35>
     
     
  15. ИгорьК

    ИгорьК Гуру

    Ну ничем не могу помочь, это надо детальнее разбираться
     
    obuhanoe нравится это.
  16. obuhanoe

    obuhanoe Гик

    set12 вот так должна выглядеть и после заработало как надо. Спасибо Вам большое за помощь.
    Код (C++):
    function M.set12()
        ow.setup(M.pin)
        for _, v in pairs(M.adrtbl) do
            ow.reset(M.pin)
            ow.select(M.pin, v)
            -- ow.write(M.pin, 0x44, 1)
            ow.write(M.pin, 0x4E, 1)
            ow.write(M.pin, 0x7F, 1)
            ow.write(M.pin, 0xFF, 1)
            ow.write(M.pin, 0x60, 1)
            ow.write(M.pin, 0x48, 1)
            ow.reset(M.pin)
        end
    end
     
    ИгорьК нравится это.
  17. ИгорьК

    ИгорьК Гуру

    Ну да, славно! Торопился.
     
  18. ИгорьК

    ИгорьК Гуру

    56. Неспешный вызов на исполнение многих файлов

    Бывает, требуется периодически выполнять какую-то задачу. Для этого у нас есть таймеры, сколько пожелаешь. Однако при очень большом количестве задач, таймеры могут начать мешать друг другу. Если вы делаете несколько запросов к серверу, отправляете данные на брокер, опрашиваете датчики - задачи лучше не смешивать.

    Данный код - выжимка из реального проекта, где есть восемь задач, вызываемых с разной периодичностью от 900 до 17 секунд:

    Код (Lua):

    -- Таблица с именами файлов, интервалом, и временем последнего исполнения
    local wt = {}
    wt[1] = { 'file01.lua', 900, 0 }
    wt[2] = { 'file02.lua', 900, 0 }
    wt[3] = { 'file03.lua', 600, 0 }
    wt[4] = { 'file04.lua', 180, 0 }
    wt[5] = { 'file05.lua', 60, 0 }
    wt[6] = { 'file06.lua', 60, 0 }
    wt[7] = { 'file07.lua', 30, 0 }
    wt[8] = { 'file08.lua', 17, 0 }

    -- Функция проверки и вызова файлов
    dispatch = function(t)
        -- Текущее время в секундах
        local nowt = (time.get())
        -- Return, если не прошло 3 секунды
        if  nowt % 3 ~= 0 then
            return
        end
        -- Перебираем записи в таблице, проверяем интервал
        -- с последнего вызова
        for _, v in pairs(wt) do
            -- Если прошло больше чем положено
            if nowt - v[2] > v[3] then
                -- Записываем новое время в таблицу
                v[3] = nowt
                print('Run', v[1], v[2], v[3])
                -- Вызыввем на исполнение файл
                dofile(v[1])
                -- break, чтобы не вызвать несколько файлов одновременно
                break
            end
        end
    end

    tik = tmr.create()
    tik:alarm(1000, 1, dispatch)
    Ясно, что при таком управлении не соблюдается точный интервал запросов (увеличен до + 1-3 секуны). Но редко когда это действительно требуется. Для такого удивительного случая можно выделить отдельный таймер. А так - и одного достаточно.
     
    Последнее редактирование: 25 июл 2023
    obuhanoe и serg3295 нравится это.
  19. Sergku

    Sergku Нерд

    всем здрасти. я сегодня сломался, когда узнал, что "0" не трактуется как false в булевых операциях.Есть ли способ корректного приведения типа boolean к number (типа сишного byte a = !digitalRead(....)) или придется типа таких извращений делать:


    Код (C++):

    function myf(x)
       if not x or x == 0 then
         return 1
       else
         return 0
       end
    end
     
    Последнее редактирование: 3 авг 2023
  20. ИгорьК

    ИгорьК Гуру

    Жизнь без извращений неинтересна. Как посмотреть на ситуацию. Если проверять переменную с другой логикой: есть данные/нет данных, то тогда 0 вполне себе true. А именно такова логика lua.

    Так что приведённый код действительно можно признать извратом, но несколько с другой позиции.

    Смотрите в чем дело. В Си, к которому вы привыкли, не принято проверить переменную на nil, как в начале проверки.

    Здесь же вы делаете две принципиально разные проверки на наличие данных и на их значение.