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

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

  1. levae

    levae Нуб

    Спасибо, учту.
     
  2. levae

    levae Нуб

    У меня есть предложение: В начале темы сделать ссылку на скачивание прошивки для esp8266 , чтобы заработали те примеры, которые опубликованы на этой странице. Не один скрипт не работает. Я понимаю, что это моя беда, но чтобы не бросить это занятие должен быть какой-то стимул. Это , желательно, конкретные бинарники, а не ссылки на Git Hub
     
    Последнее редактирование: 11 апр 2021
  3. serg3295

    serg3295 Гик

    LFS в ESP32

    В прошивке NodeMCU ESP32 присутствует недокументированная функция - LFS, аналогичная имеющейся в ESP8266.
    Синтаксис немного отличается, но принципы работы сохранены.

    В данной заметке подразумевается, что все действия производятся в Linux и пользователь имеет возможность собирать прошивку из исходников. Это условие вытекает из необходимости сборки luac.cross под целевую систему.
    В принципе, возможно собрать luac.cross и под Windows, переписав make файл в mingw32-Makefile.mak для запуска в mingw32. Пример того как это можно сделать был чуть раньше в этой теме.

    После сборки прошивки в каталоге build/luac_cross/ окажется файл luac.cross, копируем его в какой-нибудь свой рабочий каталог, где будем проверять работу lfs.
    Из каталога /lua_examples/lfs/ взять файлы init.lua и dummy_strings.lua. По аналогии с esp8266 я переименовал init.lua в _init.lua (далее везде с нижним подчёркиванием).
    Создаём файл a.lua и пишем туда для проверки print("test from LFS esp32").
    Итак, в рабочем каталоге у нас собрались файлы: luac.cross, a.lua, _init.lua, dummy_strings.lua.
    Теперь надо получить образ LFS

    ./luac.cross -f -o lfs.img a.lua _init.lua dummy_strings.lua

    С помощью ESPlorer'a как обычно записываем получившийся образ lfs.img на spiffs и по очереди выполняем команды

    node.flashreload("lfs.img")
    тут система рестартует

    инициализируем LFS
    node.flashindex('_init')()

    Запускаем нашу программу
    LFS.a()

    Видим вывод
    Код (Lua):
    > LFS.a()
    test from LFS esp32
    >
     
    Также можно пользоваться следующими служебными функциями:
    _list - возвращает список загруженных в LFS модулей
    Код (Lua):
    for k, v in pairs(LFS._list) do
      print (k,v)
    end
     
    _config - возвращает конфигурацию LFS
    Код (Lua):
    do
    local s = {}
      for  k, v in pairs (LFS._config) do
      s[#s+1] = string.format("%s = 0x%06x", k, v)
      end
      print ("{ " .. table.concat(s, ', ') .. " }")
    end
     
    _time - возвращает время в тиках UNIX
    Код (Lua):
    print(LFS._time)
     
    ИгорьК нравится это.
  4. ИгорьК

    ИгорьК Гуру

    Получил баг на шесть часов слома мозга.
    Ситуация. Сделал устройство показа температуры в парной. Две железки для работы в паре.
    Одна - дисплей, другая - датчеГ. В итоге:

    itog.jpg

    ДатчеГ: еспшка, DS18b20 в гильзе, HC-12, Hi-Link блочок питания .
    Никакой монтажной платы - хардкор на разъемах, ибо было не известно как DS18b20 поведет себя ближе к 100 градусам, может быть вместо него будет термопара:
    upload_2021-9-10_9-3-35.png

    Здесь еспшка в немодной черной изоленте (правильно - синяя), по факту - в термоусадке, как HC-12 что внизу слева синий. DS18b20 справа в данном случае просто отладочный вариант, рабочий подключается через этот же разъем.

    DS18b20 через стену протащен в парную, снаружи все спрятано в распределительную коробку, причем в жуть каком неудобном месте для доступа.

    Отработало больше месяца, почти два. После чего датчеГ перестал работать. Почему устройство перестает работать? Контакты и неисправные детали, не так ли?

    Железка, как видно, просто супергодна для ремонта: на фото не показано, но в разъем где DS18b20 вставляется на таких же разъемах с защелками провод на питание.

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

    Иду в баню, отключаю электричество, откручиваю со стены распредкоробку с БП (там тоже на разъемах, но WAGO, можно током удариться если не выключить его), приношу в дом, включаю - все работает. Гружу БП - все норм.

    Чешу репу, собираю все обратно, иду в баню, отключаю электричество, все монтирую, включаю - не работает.

    Отключаю DS18b20 - еспшка запускается, работает. Жду некоторое время - все норм. На MQTT брокере вижу что устройство в сети.

    Ок, значит проблема в датчике. Снимаю, иду в дом, второго такого (в гильзе) найти не могу. Паяю новый датчик просто в термоусадке, делаю разъемы.

    Снимаю устройство для проверки, несу в дом, подключаю новый датчик - все работает. Иду в баню, возвращаю все на место.

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

    Значит все таки блок питания - не выдает ток, был такой случай.

    Отключаю электричество, все снимаю, несу в дом, переделываю блок питания. Такого как был у меня нет - делаю другой с пайкой на плате, новым предохранителем, etc.

    Проверяю - все работает, возвращаю датчик в гильзе, выключаю электричество в бане, все монтирую, запускаю - не работает.

    Значит еспшка. Отсоединяю, приношу в дом, беру новую, запаиваю (благо - разъемы обжимать не надо), заливаю код, проверяю, загоняю в термоусадку, возвращаюсь в баню: - НЕ РАБОТАЕТ!!!

    По факту - переделал устройство полностью. Прошло в общей сложности около шести часов - проблема как была так и осталась!
     
    Последнее редактирование: 10 сен 2021
  5. ИгорьК

    ИгорьК Гуру

    Что делать... Беру ноутбук и тащусь с ним в баню - попробую посмотреть что же там происходит.
    По факту там так не удобно подлезть к устройству...

    На весу подключаюсь к железке и вижу, что баг - программный!!!

    Еспшка запускается, получает температуру с датчика (выводит в порт), отправляет ее на обработку и в функции перезагружается, объявляя что в строке один из ее аргументов - nil.

    Строка:

    Код (Lua):
    result = sor[min] + ((sor[max] - sor[min]) * ((t - min)/(max - min)))
    здесь t - полученная функцией температура, sor - таблица, которая забирается из глобальной области таким образом:

    Код (Lua):
    local sor = sor
    _G.sor = nil
     
    Если датчик отключить - то в коде стоит проверка на его неисправность, и устройство не ресетится (поэтому то мне и казалось пару раз что проблема в датчике), но в коде нет проверки на непередачу глобальной таблицы в локальную :)

    На весу правлю код: просто возвращаю из функции температуру без фильтрации - железка заработала. То есть проблема явно в приведенном выше коде.

    Но даже это не проблема - проблема в целом: оно работало больше месяца, оно продолжает работать в одном месте но перестало в другом!

    Короче, после шести часов битвы и при опустошенной голове оставил все как есть - на фильтр поставил "заглушку". Все работает с прошлого воскресенья.

    В чем, полагаю, проблема.

    Код основного рабочего файла "main..lua" не окружен парой "do ... end". Согласно руководству, все что находится внутри исполняемого файла и объявлено как local - становится локальным для всего кода файла. Получается, это не так в данном случае. Видимо, при определенных обстоятельствах, происходит какой-то "разрыв" потока определения локального окружения.


    Что может различаться в двух местах работы одного устройства, плюс измениться со временем - только условия установления связи wifi! Поскольку этот процесс асинхронный - не исключаю что он как-то все таки влияет на указанные выше процессы и в самый неподходящий момент.

    Чего только не пришло в воспаленный моск... :)

    А ларчик просто открывался! Температура в парилке опустилась ниже 20 градусов и это не учтено в коде. Пол лета он была больше, баг не вылазил. Сам себя наказал!
    В доме всяко теплее 20 - вот железка и работала. Пришел в баню, пока крутился - температура датчика упала. Вот и баг.

    Что я сделал не правильно? Надо было или оставить таблицу глобальной или окружить код do ... end и посмотреть что будет.
    ... но сил и мыслей хватило только на заглушку. Теперь ждать две недели - в ближайшее время на дачу не поеду.

    А железки - работают исправно:

    upload_2021-9-10_10-6-0.png

    "Неверная временная метка" здесь от того, что датчеГ передал данные по протоколу COAP, а через 433 мгц НС-12 работать не стал, ибо все хорошо.
     
    Последнее редактирование: 10 сен 2021
    b707 нравится это.
  6. b707

    b707 Гуру

    У меня тоже есть выносной датчик.... тоже на основе DS18B20 и HC-12....
    Уже догадываетесь. что за историю я хочу рассказать? :)

    Проработал он более 2х лет, после чего я случайно пропустил время зарядки АКБ. Заряд ушел в ноль, датчик выключился.
    Казалось бы, что за проблема? Акумулятор. я конечно. зарядил... Но после этого датчик через день завис.
    Передернул питание - через 3 часа завис снова.
    Принес домой, разобрал - все работает. На всякий случай поменял акумулятор... завис через 3 дня.
    Снова разобрал, поменял НС-12 на новую, из пакетика. ... хватило на 2 дня...
    Что остается? - только тини85. Но сменной у меня нет.

    и. главное - 2 года же все работало!

    прошу прощения за оффтоп
     
    ИгорьК нравится это.
  7. SergeiL

    SergeiL Оракул Модератор

    А почему COAP а не MQTT?
     
  8. ИгорьК

    ИгорьК Гуру

    Потому что этот проект делался на пользу людям, а не у всех людей (последовательно) есть MQTT брокер, WiFi в бане, просто WiFi на даче. У каждого людя, в зависимости от обстановки, можно вставлять или не вставлять HC-12, подключать или не подключать WiFi. То есть, устройство сразу делалось сильно универсальным для многих случаев. Дисплей в бане, если есть сеть, показывает время и внутреннюю температуру, может показывать и уличную. Нет WiFi - будет показывать температуру в парилке, если в него поставить датчик - плюс температуру в комнате отдыха.
    Дисплей, если есть сеть, сам передает данные на брокер, нет - не передает.

    upload_2021-9-10_11-55-7.png

    upload_2021-9-10_11-55-42.png

    upload_2021-9-10_11-56-31.png

    Только публиковать все это желание куда-то делось.

    Поэтому данные последовательно передаются на:
    1. HC-12;
    2. COAP;
    3. MQTT.
    Через MQTT данные читает дисплей, что установлен в доме.
    Через СОАР Данные читает дисплей, что установлен в комнате отдыха.
    Если нет WiFi - дисплей в комнате отдыха все равно читает данные.

    Если обнаружен WiFi, то датчик пропускает HC-12. То есть, у кого точно есть WiFi может не ставить HC-12.

    Кстати, по СОАР у меня в доме работает синхронная подсветка мебели. Вполне себе ничего работает.
     
    Последнее редактирование: 10 сен 2021
    SergeiL нравится это.
  9. SergeiL

    SergeiL Оракул Модератор

    На ESP дисплея поднимается AP и датчик цепляется к этой AP?
     
  10. ИгорьК

    ИгорьК Гуру

    Нет. Сначала хотел так, но ESP слабее роутера. Две еспшки через две толстые деревянные стены связь не устанавливали. Через роутер - да. Роутер-повторитель стоит в комнате отдыха, раздает ютуб. Поэтому на железке дисплея просто СОАР "сервер" - он "весит" по сравнению с HTTP копейки но работает зело устойчиво.
     
    SergeiL нравится это.
  11. ИгорьК

    ИгорьК Гуру

    А ларчик просто открывался... Подумал неспеша и увидел ошибку в коде :)
     
  12. ИгорьК

    ИгорьК Гуру

    Мысль. А watchdog? С устройствами такого рода, ведь, проблем не должно быть - должен перегружаться, а не зависать. Чудеса.

    В моем случае железка вошла в циклическую перезагрузку. Температура упала ниже "неподуманной" и пошла эта перезагрузка. Ошибка глупая, но вот выявить удалось только сейчас глядя в код .
     
    Последнее редактирование: 10 сен 2021
  13. SergeiL

    SergeiL Оракул Модератор

    Ниже 20 градусов?
    Представить даже не могу возможную ошибку.
    Если ниже 0 - то понятно, но 20...
     
  14. ИгорьК

    ИгорьК Гуру

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

    Вот для "исправления" сделал таблицу:
    Код (Lua):
    sor = {}
    sor[20] = 20
    sor[30] = 30
    sor[40] = 37
    sor[53] = 55
    sor[70] = 73
    sor[81] = 84
    sor[90] = 93
    sor[100] = 100
    sor[110] = 110
    sor[125] = 125
    Заполнялась путем периодического забегания в парную и фиксации данных - что показывает дисплей и что показывает термометр.

    Табличка обрабатывается в функции. Идет сравнение текущей с ней. А ниже 20 градусов то ничего нет! О чем думал когда это делал? О паре, а не о холоде :)
    Добавить строку sor[0] = 0 и все будет работать. Ниже 0 там температура не опускается. А опустится - это другая проблема :)

    А вот часть кода, которая валится. Перед вызовом функции наличие температуры от датчика проверяется, нет - вызова не будет:

    Код (Lua):
        local sor = sor
        _G.sor = nil

        ------------ Real Temperature ---------------
        local filter = function (t)
            t = tonumber(t)
            local min, max, result = 0, 200, 0
         
            for k in pairs(sor) do
                if k <= t and min < k then min = k end
            end
            for k in pairs(sor) do
                if k > min then
                    if k < max then max = k  end
                end
            end
            result = sor[min] + ((sor[max] - sor[min]) * ((t - min)/(max - min)))
            return string.format("%d", result)
            -- return string.format("%d", t)
        end
        ------------------------------------
     
     
    SergeiL нравится это.
  15. SergeiL

    SergeiL Оракул Модератор

    А я то все не мог понять, что эта строка делает. :)
     
  16. ИгорьК

    ИгорьК Гуру

    Валилось оно в этой строке. Я с устатку решил, что нет таблицы, а не было ее данных меньше 20.
     
  17. b707

    b707 Гуру

    отработало 2 месяца с ошибкой в коде?
     
  18. SergeiL

    SergeiL Оракул Модератор

    У меня в бане тоже DS18B20 стоит, если температура больше 125 показывает 125. Как то перетопил...
    Когда делал термометр еще ESP не было, термометр на Меге 8 с LCD.
    А еще в печке бублик, греющий воду на чердаке, которая заливается по привычке, но редко используется. Только для подкидывания на камни в основном, кран в парилке.
    Переключиться на нее можно, просто два переключающих крана переключить и вместо бойлера и водопровода от насосной станции подключается бочка холодной и бак с горячей.
    Но нужно еще менять смеситель на обычный, с двумя крутилками, вместо одной ручки. У того, что с одной ручкой сечение маловато, под давление рассчитано, из лейки душа плохо течет.
     
    ИгорьК нравится это.
  19. ИгорьК

    ИгорьК Гуру

    Там сравнение данных происходит. Пока необходимые данные были учтены в таблице - все было хорошо.

    Пожалуй, это не ошибка в коде, а логическая ошибка. Оно было проверено :) Внимание то сосредоточено на увеличении температуры в парилке, а не на уменьшении :)

    upload_2021-9-10_13-46-28.png

    А ведь мог:

    upload_2021-9-10_13-52-8.png


    Но не сообразил. Не на том внимание.
     
    Последнее редактирование: 10 сен 2021
  20. SergeiL

    SergeiL Оракул Модератор

    Да, не понимаю я LUA:

    upload_2021-9-10_14-14-56.png

    В for перебираются элементы массива, в которых записаны значения. Так?
    после дух циклов в min будет 20, а в max будет 115? или все таки 110?

    Потом вычисляется температура и в строке есть
    Код (C++):
    ( rtt[max]-rtt[min] )
    а массиве же нет элемента rtt[115] что в этот момент произойдет?
     
    Последнее редактирование: 10 сен 2021