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

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

  1. ИгорьК

    ИгорьК Гуру

    Самое распространенное явление - DS18b20. Там между запросом и съемом показаний по максимуму 750 мс.
    Все лень посмотреть, как задержка в Даллас библиотеке сделана.

    Но здесь Lua. Здесь, в основном, все на Callback функциях и таймерах.

    Хотел сделать показ на корутинах, но что-то громоздким показалось. В реальности, при показе погоды каждый шаг смещения по дисплею установлен 35 мс, умножается на количество точек, что надо протащить, и возвращается диспетчеру. Все работает.
     
    Последнее редактирование: 31 июл 2025
  2. Asper Daffy

    Asper Daffy Иксперд

  3. ИгорьК

    ИгорьК Гуру

    Слышу впервые. Он к МК как-то относится? Евгений, я сам DIY, который назавтра забывает что сегодня делал. Это хобби. Это ни хорошо и ни плохо. Это чуть лучше чем лежать на диване, но не так круто, как всходить на Эверест. У всех хобби разные.
     
  4. Asper Daffy

    Asper Daffy Иксперд

    Не понял вопроса. Если про реализацию, то там платформа пофиг, там кросс-компилятор из Т++ в С++.
     
  5. ИгорьК

    ИгорьК Гуру

    Это и есть вопрос новобранца :) Я давно развлекаюсь с Lua, а не с С++.
     
  6. ИгорьК

    ИгорьК Гуру

    ---------------------------------
    Очень дешевый сенсор расстояния LD2402.

    Пытаюсь понять что из него можно достать полезного таким кодом:

    Код (Lua):

    do
        -- Если DEBUG - вывод от 'print' иначе молчок
        PRT = function(...) if DEBUG == true then print(...) end end
        PRT1 = function(...) if DEBUG == 1 then print(...) end end
        PRT2 = function(...) if DEBUG == 2 then print(...) end end
        local prt = PRT or print
        local prt1 = PRT1 or print
        local prt2 = PRT2 or print

        -- Установка порта
        TX = 17
        RX = 16

        MAXDIST = 150                -- Максимальная дистанция для реагирования
        DELTA_DIST = 30              -- Изменение дистанции, когда следует реагировать

        if not dat then dat = {} end -- таблица, для совместимости с другим кодом

        if TX and RX then
            uart.setup(2, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, { tx = TX, rx = RX })
            uart.start(2)
            dat.uart2 = true -- Чтобы в других местах знать, что порт установлен
            prt('Set UART at TX, RX', TX, RX)
            TX, RX = nil, nil
        end

        if not wth then wth = {} end -- Таблица, куда собираем необходимые данные

        wth.distance = 0             -- Начальная дистанция
        wth.showdata = 0             -- Чтобы поменьше выводить в консоль, переменная с коророй идет сравнение
        wth.rawdist = 0
        local startUART = false      -- Для улова первого читаемого байта из UART
        local makedata, uartstring, uartdist, rawdist
        local delta = DELTA_DIST
        local maxdist = MAXDIST or 200                        -- Локалим переменную максимпльной дистанции для реагирования
        MAXDIST, DELTA_DIST = nil, nil
        uartstring = ''                                       -- Для сбора текста из UART

        makedata = function(dt)                               -- Обработчик байтов из UART
            if string.byte(dt, 1) ~= 0x0D then                -- Пока не знак возврата каретки - собираем данные в строковую переменную
                uartstring = uartstring .. dt
            else                                              -- Обрабатываем собранные данные
                prt('uartstring:', uartstring)                -- Выводим в консоль что ы итоге получилось
                startUART = false                             -- Говорим UART что будем работать заново
                uartdist = string.match(uartstring, ':(%d+)') -- Выгрызаем числовую составляющую
                prt('Got Distance:', uartdist)

                uartstring = ''
                rawdist = tonumber(uartdist) -- Стринг в число

                if rawdist and wth.rawdist ~= rawdist then  -- Изменения в таблицу
                    -- Если больше 5 см - на печать
                    if math.abs(wth.rawdist - rawdist) > 5 then prt1(wth.rawdist) end
                    wth.rawdist = rawdist
                end

                -- Если ошибка или расстояние больше чем надо - хватит!
                if not rawdist or rawdist > maxdist then
                    wth.showdata = 0
                    return
                end                                                        
                prt('Now Distance:', uartdist)
                wth.distance = rawdist

                -- Реагируем, когда изменение больше чем DELTA_DIST
                if math.abs(wth.distance - wth.showdata) > delta then
                    print('Distance is', wth.distance)
                    wth.showdata = wth.distance
                    -- dofile 'mqttpub.lua'
                end
            end
        end

        uart.on(2, "data", 1,
            function(data)
                local bt = string.byte(data, 1) -- bt - один байт из UART
                prt2(string.format("bt = 0x%02X", bt))
                prt2(data)
                if startUART == false and bt ~= 0x0A then -- Ждем перевода строки
                    return
                elseif startUART == false then            -- Дождались - разрешаем чтение
                    startUART = true
                    return
                end
                makedata(data) -- Отправляем байт в переработку
            end, 0)
    end

     

    Это просто скетч для размышления. Чтобы увидеть все что происходит, дать в консоль "DEBUG = true", убрать данные - "DEBUG = false", так как датчик гонит в UART данные раз в 500 мс. и все ими забивается.

    upload_2025-9-2_11-2-57.png

    Почему датчик по умолчанию считает, что расстояние в данном случае 272 см - вообще не понятно. Перед ним - шкаф в полутора метрах. 145 - 150 - показывает когда я к нему подхожу сантиметров на 90.

    В общем, пока изучаю. Реагирует на движение он стабильно, но, судя по всему, его можно применять лишь как "выключатель" с настройкой "по месту". Понять его данные пока не удается.

    ПС. Датчик лежит на столе, пока с ним "разборки". Оказывается, от расположения верх/низ кое-что зависит.
     
    Последнее редактирование: 3 сен 2025
  7. ИгорьК

    ИгорьК Гуру

    serg3295 нравится это.
  8. ИгорьК

    ИгорьК Гуру

    Вот такую держалку для датчика нарисовал. Файлы Компаса в приложении.

    upload_2025-9-4_9-12-41.png

    upload_2025-9-4_9-25-35.png

    Но напечатал не такую :)

    upload_2025-9-4_9-14-36.png


    Чет она мне напомнила, и я ее перечертил. Хотя все равно чет напоминает :)

    Все в приложении.

    Датчик в такой коробочке стабилизировался, теперь можно размышлять о его деятельности :)
    В верхней части отверстие под фоторезистор. Хочу сделать датчик движения/освещенности.
    Таких датчиков продается пруд пруди, но здесь еще будет выход на реле и, возможно, само реле.

    Алгоритм, полагаю, будет посложнее, чем, обнаружил движение/свет - сообщил. Но это пока замыслы.

    В общем, это просто "держалка" датчиков, а не проект.
     

    Вложения:

    • LD2402.zip
      Размер файла:
      448,8 КБ
      Просмотров:
      10
  9. Credo

    Credo Нуб

    Скажите вообще реально запустить без краша системы? Что пробовал: агресивную очистку памяти, разнести по времени вплоть до 05,10,15,20. Убрать 1н индекс ( хотя не плохо бы 2). Разные сервера получения. Парсинг txt, json, html - вообще мрак крашится. Http сервер не нашел Устанавливал пропустить если размер памяти меньше . Парсинг 1 раз в 60 минут. Монитор показывает
    11:12:33.181 -> [MEM] Weather_str_start: 27192
    11:12:33.181 -> [MEM] Weather_str_end: 27088
    11:12:42.575 -> [MEM] Weather_end: 29824
    11:13:12.592 -> [MEM] Weather_end: 29824
    11:13:33.430 -> [MEM] Weather_str_start: 26416
    11:13:33.430 -> [MEM] Weather_str_end: 26312 на переменные и тд не смотрите , это один из файлов проекта.
     

    Вложения:

    • weather.txt
      Размер файла:
      21,7 КБ
      Просмотров:
      3
  10. ИгорьК

    ИгорьК Гуру

    Здесь не реально.
    Вы не в ту тему вопрос задали, тут про язык Lua.

    ========

    Что касается стабильности, то у меня часы и данные с погодного сервера парсят, и с narodmon, и отправляют данные, и http сервер для настройки поднимают. То есть стабильность достижима.
     
    Последнее редактирование: 21 ноя 2025
  11. ИгорьК

    ИгорьК Гуру

    MAX7219 семисегментный дисплей. ESP32!
    Вот такой:
    max7219md.png

    Модуль:
    Код (Lua):
    -- _max7219md.lua
    local M = {}
    local SSPin = 18
    local DECOD = 0x09
    local INTENS = 0x0A
    local SCAN = 0x0B
    local SHUT = 0x0C
    local DIST = 0x0F
    local ESP = 'esp32'
    local device

    local function sendByte(register, data)
        gpio.write(SSPin, 0)
        device:transfer(string.char(register, data))
        gpio.write(SSPin, 1)
    end

    function M.setup(esp, mosi, sspin, sclk, miso)
        local busmaster
        local lsclk = sclk or 19
        local lmosi = mosi or 23
        local lmiso = miso or 26
        local lesp = esp or ESP

        if lesp == 'esp32' then
            busmaster = spi.master(spi.HSPI, { sclk = lsclk, mosi = lmosi, miso = lmiso })
        elseif lesp == 'esp32s3' then
            -- busmaster = spi.master(spi.SPI2, { sclk = lsclk, mosi = lmosi, miso = lmiso }, 0)
            busmaster = spi.master(spi.SPI2, { sclk = lsclk, mosi = lmosi }, 0)
        else
            print('esp32s3 or esp32 only')
            return
        end

        local device_config = { mode = 0, freq = 10000000 }
        device = busmaster:device(device_config)

        SSPin = sspin or SSPin
        gpio.config({ gpio = SSPin, dir = gpio.OUT })
        gpio.write(SSPin, 1)

        sendByte(SCAN, 7)
        sendByte(DECOD, 0x00)
        -- sendByte(DECOD, 0xFF) -- Scan All Digits
        sendByte(DIST, 0)
        sendByte(INTENS, 1)
        sendByte(SHUT, 1)
        for a = 1, 8 do
            sendByte(a, 0)
        end
        lsclk, lmosi, lmiso, lesp = nil, nil, nil, nil
    end

    function M.setIntensity(intensity)
        sendByte(INTENS, intensity)
    end

    function M.clear()
        for i = 1, 8 do sendByte(i, 0) end
    end

    function M.shutdown(sd)
        local sdRg
        sdRg = sd and 0 or 1
        sendByte(SHUT, sdRg)
        sdRg = nil
    end

    M.sb = sendByte
    return M

    Применять.
    Код (Lua):
    MOSI = 1
    CS = 2
    SCLK = 3
    -- MISO = 5
    ESP = 'esp32s3' --  или 'esp32', тогда править ноги выше
    max7219 = require('_max7219md')
    font = require('font7seg')

    -- function M.setup(esp, mosi, sspin, sclk, miso)
    max7219.setup(ESP, MOSI, CS, SCLK)
    max7219.clear()
    max7219.setIntensity(0)
    SCLK, MOSI, MISO, CS, ESP = nil, nil, nil, nil, nil

    WriteMAX = function(s)
        local d = {}
        local dc = 0
        for i = 1, #s do
            dc = font.GetChar(string.sub(s, i, i))
            if dc == 0x80 then
                if #d == 0
                then
                    d[1] = dc
                else
                    d[#d] = d[#d] + 0x80
                end
            else
                d[#d + 1] = dc
            end
        end
        if #d < 8 then
            for c = 1, 8 - #d do table.insert(d, c, 0x00) end
        end
        for k = 1, 8 do
            max7219.sb(9 - k, d[k])
        end
        if #d > 8 then
            dat.buff = d
        end
    end

    ------


    WriteMAX('21:23 000')

    Фонт в приложении.
     

    Вложения:

    • font7seg.zip
      Размер файла:
      638 байт
      Просмотров:
      2