Arduino, ESP8266 Lua, Raspberry Pi 2 && OpenHab. Умный дом: азы управления.

Тема в разделе "Глядите, что я сделал", создана пользователем ИгорьК, 12 май 2015.

  1. ИгорьК

    ИгорьК Гуру

    Пока в документации существует эта запись я в ОН2 ни ногой.
     
  2. Securbond

    Securbond Гуру

    Всем привет. Кто нибудь пробовал использовать модуль BME-280 с одноименным модулем? Что то не хочет он у меня работать. (Датчик живой, в arduinoIDE работает).
     
  3. ИгорьК

    ИгорьК Гуру

    Использовал.
    И код выкладывал. Смотрите.
     
    Securbond нравится это.
  4. Securbond

    Securbond Гуру

    пробую такой код

    Код (Javascript):
    bme280.init(3, 4)
    tmr.delay(100)
     
        local H = string.format("%.1f", (bme280.humi()/1000))
        local P, T = bme280.baro()
        P = string.format("%.1f", (P/1000*0.75))
        T = string.format("%.2f", T/100)
        print("Humidity = "..H.." %, \nPressure = "
        ..P.." mm.Hg"
        .."\nTemperatre = "..T.." C")
    Ничего не получается, ругается что не получены значения с датчика, грешу на ESP...
    модули:
    Код (Text):
     adc,bit,bme280,file,gpio,i2c,mqtt,net,node,ow,rtctime,spi,struct,tmr,uart,wifi,tls
     
     
  5. Securbond

    Securbond Гуру

    Поменял пины на 6, 7 и все заработало. Может порты подпалены :confused:
    UPD: Китайцы, мать их за ногу... пины подписали в нескольких вариантах, но не так как нужно.
     
    Последнее редактирование: 8 авг 2017
  6. Securbond

    Securbond Гуру

    Подключение датчика освещенности BH1750
    Первоисточник: https://github.com/nodemcu/nodemcu-firmware/tree/master/lua_modules/bh1750
    Не забываем модуль I2C.
    сначала закидываем файл bh1750.lua следующего содержания:
    Код (Javascript):
    -- ***************************************************************************
    -- BH1750 module for ESP8266 with nodeMCU
    -- BH1750 compatible tested 2015-1-22
    --
    -- Written by xiaohu
    --
    -- MIT license, http://opensource.org/licenses/MIT
    -- ***************************************************************************
    local moduleName = ...
    local M = {}
    _G[moduleName] = M
        --I2C slave address of GY-30
        local GY_30_address = 0x23
        -- i2c interface ID
        local id = 0
        --LUX
        local l
        --CMD
        local CMD = 0x10
        local init = false
        --Make it more faster
        local i2c = i2c
        function M.init(sda, scl)
            i2c.setup(id, sda, scl, i2c.SLOW)
        --print("i2c ok..")
        init = true
    end
    local function read_data(ADDR, commands, length)
        i2c.start(id)
        i2c.address(id, ADDR, i2c.TRANSMITTER)
        i2c.write(id, commands)
        i2c.stop(id)
        i2c.start(id)
        i2c.address(id, ADDR,i2c.RECEIVER)
        tmr.delay(200000)
        c = i2c.read(id, length)
        i2c.stop(id)
        return c
    end
    local function read_lux()
        dataT = read_data(GY_30_address, CMD, 2)
        --Make it more faster
        UT = dataT:byte(1) * 256 + dataT:byte(2)
        l = (UT*1000/12)
        return(l)
    end
    function M.read()
        if (not init) then
            print("init() must be called before read.")
        else
            read_lux()
        end
    end
    function M.getlux()
        return l
    end
    return M
     
    Затем пишем еще один скрипт (название не имеет значения)
    Код (Javascript):

    sda = 1
    scl = 2

        tmr.alarm(0, 5000, 1, function()
        bh1750 = require("bh1750")
        bh1750.init(sda, scl)
        bh1750.read(OSS)
        l = bh1750.getlux()
        l = string.format("%.2f", l/100)

        print("Lux = "..l.." lx")

    end)
     

    Наслаждаемся полученным результатом.
     
    Последнее редактирование: 8 авг 2017
  7. ИгорьК

    ИгорьК Гуру

    Все таки стоит пересмотреть этот модуль. Задержка 2000000 есть зело неправильно.
    Здесь нужно работать через callback функцию.
    Хотя там и первоисточник из NodeMCU - два года назад они тоже лажали.
     
  8. Securbond

    Securbond Гуру

    Это первый попавшийся, возможно есть и более оптимизированные варианты. Видимо от этого и были все перезагрузки при отсутствии данных. Как доберусь до компа (завтра) попробую уменьшить это значение. Callback ещё не освоил, надеюсь вчерашняя ссылочка на Ваши уроки прояснит этот вопрос.
     
  9. ИгорьК

    ИгорьК Гуру

    Если этот тормоз в библиотеке есть - значит он нужен. Скорее всего его нельзя сильно уменьшить.
    Почитайте здесь про тормоза. Они к применению практически запрещены:
    В общем, к коду двухгодичной давности от nodemcu надо относиться внимательно.

    Кроме того, эта конструкция:
    Код (Lua):
    local moduleName = ...
    local M = {}
    _G[moduleName] = M
    --...
    тоже не стоит применения.

    Воспользуйтесь топиком http://forum.amperka.ru/threads/esp-8266-азы-программирования-lua-nodemcu.12558/page-2#post-125034
    Посмотрите память после выгрузки модуля.
     
  10. ИгорьК

    ИгорьК Гуру

    Вот как, я думаю, это должно выглядеть. Проверить не могу - нет такого железа.
    bh1750.lua
    Код (Lua):
    local M = {}
    M.GY_30_address = 0x23
    M.id = 0
    M.l = 0
    M.CMD = 0x10
    M.init = false
    --local i2c = i2c

    function M.init(sda, scl)
        i2c.setup(M.id, sda, scl, i2c.SLOW)
        init = true
    end

    local function read_data(callback)
        i2c.start(M.id)
        i2c.address(M.id, M.GY_30_address, i2c.TRANSMITTER)
        i2c.write(M.id, M.CMD)
        i2c.stop(M.id)
        i2c.start(M.id)
        i2c.address(M.id, ADDR,i2c.RECEIVER)

        tmr.create():alarm(2000, 0, function(t)
            c = i2c.read(M.id, 2)
            i2c.stop(M.id)
            local UT = c:byte(1) * 256 + c:byte(2)
            M.l = (UT*1000/12)
            t = nil
            if callback then callback(M.l) end
        end)
    end

    function M.getlux(callthen)
        if (not M.init) then
            print("init() must be called before read.")
        else
            read_data(callthen)
        end
    end

    return M
     
    На выполнение:
    Код (Lua):

    sda = 1
    scl = 2
    bh1750 = require("bh1750")
    bh1750.init(sda, scl)

    function printlux(l)
        l = string.format("%.2f", l/100)
        print("Lux = "..l.." lx")
    end

    tmr.alarm(0, 10000, 1, function()
        bh1750.getlux(printlux)
    end)
     
    Последнее редактирование: 9 авг 2017
  11. Securbond

    Securbond Гуру

    Спасибо! Завтра попробую и отпишусь что получилось. Заодно попытаюсь понять как нужно избавляться от больших задержек.
     
  12. Securbond

    Securbond Гуру

    После небольшого исправления, библиотека заработала. Вот рабочий вариант:
    Код (Javascript):
    local M = {}
    M.GY_30_address = 0x23
    M.id = 0
    M.l = 0
    M.CMD = 0x10
    M.init = false
    --local i2c = i2c

    function M.init(sda, scl)
        i2c.setup(M.id, sda, scl, i2c.SLOW)
        init = true
    end

    local function read_data(callback)
        i2c.start(M.id)
        i2c.address(M.id, M.GY_30_address, i2c.TRANSMITTER)
        i2c.write(M.id, M.CMD)
        i2c.stop(M.id)
        i2c.start(M.id)
        i2c.address(M.id, M.GY_30_address, i2c.RECEIVER)

        tmr.create():alarm(2000, 0, function(t)
            c = i2c.read(M.id, 2)
            i2c.stop(M.id)
            local UT = c:byte(1) * 256 + c:byte(2)
            M.l = (UT*1000/12)
            t = nil
            if callback then callback(M.l) end
        end)
    end

    function M.getlux(callthen)
        if (not M.init) then
            print("init() must be called before read.")
        else
            read_data(callthen)
        end
    end

    return M

    Так и не сообразил как совсем убрать функцию printlux. Немного исправил получение значений, мне так удобнее.
    Код (Javascript):
    sda = 1
    scl = 2
    ls = 0

    bh1750 = require("bh1750")
    bh1750.init(sda, scl)

    function printlux(l)
        ls = string.format("%.2f", l/100)
    end

    tmr.alarm(0, 6000, 1, function()

    bh1750.getlux(printlux)
    print("Lux = "..ls.." lx")

    end)
    Если объясните, как забрать значение из библиотеки не прибегая к отдельной функции - printlux, буду очень признателен.
     
    Последнее редактирование: 11 авг 2017
  13. ИгорьК

    ИгорьК Гуру

    Никак. А зачем это?
    Нужно понять следующую логику:
    1. при опросе датчика результат появляется через две секунды;
    2. следовательно, дальнейшее движение программы будет возможно только через две секунды;
    3. это движение программы - есть (здесь, для вашего примера) функция;
    4. нужно подготовить функцию, которая будет выполнена после получения новых данных;
    5. эту функцию нужно передать в модуль - он ПОСЛЕ получения новых данных, вызовет эту функцию с передачей в нее данных.
    Спрашивайте еще, если плохо объяснил.
     
  14. ИгорьК

    ИгорьК Гуру

    Мешает на сложность вышеуказаного рассуждения, а заштамповка головы Сишными подходами.
    Программы на Луа нелинейны.
     
  15. Securbond

    Securbond Гуру

    Может как то в библиотеке условие прописать, что если значение еще не получено выдать - 0. Если значение получено выдать полученное значение ???
     
  16. ИгорьК

    ИгорьК Гуру

    :)

    Можно. Но зачем? Еще раз перечитайте что я написал.
    Зачем Вам ноль? Вам нужно значение и его надо ждать.

    Лучше понять что дальше (после получения данных) и писать callback функцию (здесь printlux). Она не только напечатает полученное значение через 2 секунды, но и, например, вызовет его публикацию.

    Еще раз, услышьте, пожалуйста: в Луа нужно уйти от линейной логики Си.

    Вы должны подготовить функцию, которая вызовет дальнейшее движение программы - печать данных, публикацию их, зажигание лампочки - все что угодно.

    Начните с ответа на вопрос - ЗАЧЕМ ВАМ НОЛЬ?
     
    Последнее редактирование: 11 авг 2017
  17. ИгорьК

    ИгорьК Гуру

  18. Securbond

    Securbond Гуру

    Если я правильно понял, то функция printlux нужна для того, чтобы ждать полученных значений от библиотеки и не тормозить работу остального кода....
     
  19. ИгорьК

    ИгорьК Гуру

    Не ждать, а обработать полученное значение и пнуть его куда надо.
     
    Securbond нравится это.
  20. ИгорьК

    ИгорьК Гуру

    60. Еще один DS18b20.
    Модуль:
    Код (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)
        M.askTemp(ttable, call)
    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)
            M.readResult(ttable, call)
            t = nil
        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 = string.char(ow.read(M.pin))
            for i = 1, 8 do
                data = data .. string.char(ow.read(M.pin))
            end
            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)
            end
        end
        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

    Применение:
    Код (Lua):
    do
    temp = {}
    pin = 4
    del = 750

    function myWork()
        print("Got DS18b20: "..#temp)
        table.foreach(temp, print)
        ds = nil
        package.loaded["ds18b20m"]=nil
    end

    ds = require('ds18b20m')
    ds.getTemp(temp, myWork, pin, del )

    end

    Код (Lua):
    do
    temp = {}    -- склад температуры
    pin = 4        -- нога датчиков, можно не передавать, если 4
    del = 750    -- задержка чтения температуры, можно не передавать если 750

    -- callback функция обработки полученной температуры
    function myWork()
        -- нашли датчиков:
        print("Got DS18b20: "..#temp)
        -- значения датчиков
        table.foreach(temp, print)
        -- kill'em all:
        ds = nil
        package.loaded["ds18b20m"]=nil
    --[[
        Здесь можно вызывать функции, которые обеспечат
        дальнейшую обработку значений датчиков.
     
        Модуль датчиков выгружен,
        а значения остались в таблице temp.
    -]]

     
    end

    ds = require('ds18b20m')
    ds.getTemp(temp, myWork, pin, del )

    --[[
        -- Или создать таймер и читать температуру:
    tmr.create():alarm(20000, 1, function()
        ds = require('ds18b20m')
        ds.getTemp(temp, myWork, pin, del )
    end)
    --]]

    end

    Разъяснения.
     
    Последнее редактирование: 11 авг 2017