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

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

  1. ИгорьК

    ИгорьК Гуру

    k - это ключи таблицы, те что в квадратных скобках. Перебираются они.
    В результате - добавил вывод min, max после каждого цикла:

    upload_2021-9-10_14-47-6.png

    И добавляем ключ с "0":

    upload_2021-9-10_14-49-1.png
     
    SergeiL нравится это.
  2. ИгорьК

    ИгорьК Гуру

    Логика фильтра очень простая:
    1. в циклах определяем ближайшие ключи, между которыми лежит пришедшая с датчика температура. Первый определяет меньший ключ, второй - бОльший;
    2. (та странная строка, что валилась) (1) вычисляем пропорцию температуры от датчика между ключами и через нее (2) рассчитываем температуру между значениями ключей.
    upload_2021-9-10_15-41-5.png
     
    Последнее редактирование: 10 сен 2021
    SergeiL нравится это.
  3. ИгорьК

    ИгорьК Гуру

    upload_2021-9-22_14-26-52.png

    Проект NodeMCU некоторое время назад заимел ветку dev-esp32-idf4
    Прошивку из нее нельзя заказать в облаке, но можно компилировать локально.
    При компиляции есть возможность выбора Lua 5.1 / Lua 5.3.

    На картинке график кучи - код опроса счетчика Энергомера.

    1. Lua 5.3 без явного вызова collectgarbage() в конце каждого цикла опроса.
    2. Lua 5.3 тот же код с добавлением единственной строки collectgarbage().
    3. Lua 5.1 без вызова collectgarbage(), то есть код, идентичный п.1.
     
  4. serg3295

    serg3295 Гик

    Сборщик мусора Lua5.3 в esp8266 вёл себя также. Этот новый алгоритм TerryE описывал в документации,
    а в ветку esp32-idf4 Lua5.3 просто портировали.
    Также перенесли LFS с синтаксисом, полностью совпадающим с esp8266.
    Добавлен модуль heaptrace для трассировки кучи. Но с ним я еще не разбирался.
     
    ИгорьК нравится это.
  5. ИгорьК

    ИгорьК Гуру

    О, увидел. Чет все сложнее и сложнее и (мне) не очевидна полезность всего этого для МК :-(
     
  6. serg3295

    serg3295 Гик

    Для отладки, возможно, heaptrace и полезна. В IDF от Espressif эта функция встроена, вот к ней интерфейс и прикрутили.
    Из полезных, на мой взгляд, вещей уже давно была добавлена возможность хранения произвольных файлов в LFS (только esp8266) благодаря добавлению модуля file_lfs.lua
    То есть, теперь файл favicon и подобные могут лежать в LFS, если кто-то пишет сайты на esp8266.
     
  7. ИгорьК

    ИгорьК Гуру

    Новички, если касается DIY. Те которые "из любой точки мира".
    У меня сейчас к роутеру штук 20 espшек подключено, если к каждой вебморду приделывать - убьешься IP-адреса вбивать.
    И LFS толком не пользуюсь: хватает ресурсов даже на 8266, не говоря о ESP32 .
     
    SergeiL нравится это.
  8. Доброго дня Игорь, посоветуйте, чем Вы пользуетесь при необходимости заменить фалы/логику на одном из своих модулей? по форуму видел тему про создание сервера для переименнования изамены файлов, но это как раз про "IP-адреса"

    Планируется несколько модулей nodemcu32, некотороые могут оказаться в труднодоступных местах, и было б шикарно их от туда не доставать, а заменить файлый по wifi
     
    Последнее редактирование: 2 дек 2021
  9. chambo

    chambo Нуб

    Всем доброй ночи!
    Может не туда пишу, но помогите, пожалуйста!
    Вот работающий код с переменной ppm

    Код (C++):
    #define  REMOTEXY_MODE__ESP8266WIFI_LIB_CLOUD
    #include <ESP8266WiFi.h>
    #include <RemoteXY.h>
    #include "DHTesp.h"
    #include <WiFiUdp.h>
    #include <TimeLib.h>
    WiFiUDP _ntpUdpServer;
    DHTesp _dht1;
    extern "C"
    {
        #include "user_interface.h"
    }
    #define REMOTEXY_WIFI_SSID "paraberry"
    #define REMOTEXY_WIFI_PASSWORD "erlan123"
    #define REMOTEXY_CLOUD_SERVER "cloud.remotexy.com"
    #define REMOTEXY_CLOUD_PORT 6376
    #define REMOTEXY_CLOUD_TOKEN "3e25374227b7d6982dd8d6b589b656f8"
    #pragma pack(push, 1)
    uint8_t RemoteXY_CONF[] = {255, 2, 0, 12, 0, 184, 0, 13, 31, 1, 68, 49, 1, 19, 61, 16, 78, 8, 208, 162, 208, 181, 208, 188, 208, 191, 208, 181, 209, 128, 208, 176, 209, 130, 209, 131, 209, 128, 208, 176, 32, 208, 178, 208, 190, 208, 183, 208, 180, 209, 131, 209, 133, 208, 176, 0, 68, 49, 1, 38, 61, 16, 78, 8, 208, 146, 208, 187, 208, 176, 208, 182, 208, 189, 208, 190, 209, 129, 209, 130, 209, 140, 0, 2, 1, 44, 60, 17, 8, 78, 8, 31, 31, 79, 78, 0, 79, 70, 70, 0, 2, 0, 1, 3, 61, 13, 78, 8, 31, 31, 208, 146, 208, 154, 208, 155, 208, 174, 208, 167, 208, 152, 208, 162, 208, 172, 32, 208, 161, 208, 146, 208, 149, 208, 162, 0, 208, 146, 208, 171, 208, 154, 208, 155, 208, 174, 208, 167, 208, 152, 208, 162, 208, 172, 32, 208, 161, 208, 146, 208, 149, 208, 162, 0, 68, 49, 1, 57, 40, 16, 78, 8, 208, 163, 209, 128, 208, 190, 208, 178, 208, 181, 208, 189, 209, 140, 32, 67, 79, 50, 0};
    struct
    {
        unsigned char switch_1;
        unsigned char switch_2;
        float t_1;
        float h_1;
        float ppm;
        unsigned char connect_flag;
    }
    RemoteXY;
    #pragma pack(pop)
    bool ESPControllerWifiClient_HRD = 0;
    bool ESPControllerWifiClient_status = 1;
    bool ESPControllerWifiClient_isDHCP = 1;
    bool ESPControllerWifiClient_IsNeedReconect = 0;
    bool ESPControllerWifiClient_workStatus = 1;
    char ESPControllerWifiClient_SSID[40] = "paraberry";
    char ESPControllerWifiClient_password[40] = "erlan123";
    IPAddress ESPControllerWifiClient_ip(0, 0, 0, 0);
    IPAddress  ESPControllerWifiClient_dns (0, 0, 0, 1);
    IPAddress  ESPControllerWifiClient_gateway (0, 0, 0, 1);
    IPAddress ESPControllerWifiClient_subnet (255, 255, 255, 0);
    uint8_t ESPControllerWifiClient_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
    float _gtv1;
    float _dht1_humOut = 0.00;
    float _dht1_tempOut = 0.00;
    unsigned long _dht1Tti = 0UL;
    bool _tim2I = 0;
    bool _tim2O = 0;
    unsigned long _tim2P = 0UL;
    bool _trgrt1 = 0;
    bool _trgrt1I = 0;
    bool _trgrt2 = 0;
    bool _trgrt2I = 0;
    bool _NTPGetTime1_CR;
    unsigned long _NTPGetTime1_lrt;
    IPAddress _NTPGetTime1_tsip;
    bool _NTPGetTime1_hfp = 0;
    bool _NTPGetTime1_iws = 0;
    byte _NTPGetTime1_packetBuffer[48];
    unsigned long _tempVariable_unsignedlong;
    void setup()
    {
        pinMode(14, OUTPUT);
        digitalWrite(14, 0);
        pinMode(12, OUTPUT);
        digitalWrite(12, 0);
        RemoteXY_Init ();
        WiFi.mode(WIFI_STA);
        _esp8266WifiModuleClientReconnect();
        _dht1.setup(5, DHTesp::DHT11);
        _dht1Tti = millis();
        _ntpUdpServer.begin(2390);
        _NTPGetTime1_lrt = (millis()) + 30000;
    }
    void loop()
    {
        RemoteXY_Handler  ();
        if(ESPControllerWifiClient_IsNeedReconect)
        {
            _esp8266WifiModuleClientReconnect();
            ESPControllerWifiClient_IsNeedReconect = 0;
        }
        ESPControllerWifiClient_status = WiFi.status() == WL_CONNECTED;
        if (ESPControllerWifiClient_status)
        {
             if (! ESPControllerWifiClient_HRD)
            {
                ESPControllerWifiClient_ip =  WiFi.localIP();
                ESPControllerWifiClient_subnet =  WiFi.subnetMask();
                ESPControllerWifiClient_gateway =  WiFi.gatewayIP();
                ESPControllerWifiClient_dns =  WiFi.dnsIP();
                WiFi.macAddress(ESPControllerWifiClient_mac);
                ESPControllerWifiClient_HRD = 1;
            }
        }
         else
        {
            ESPControllerWifiClient_HRD = 0;
        }
        //Плата:1
        if (_NTPGetTime1_CR)
        {
            _NTPGetTime1_CR = 0;
        }
         else
        {
            if (ESPControllerWifiClient_status)
            {
                if (_NTPGetTime1_iws)
                {
                     if(_isTimer(_NTPGetTime1_lrt, 1000))
                    {
                        _tempVariable_unsignedlong = _ntpUdpServer.parsePacket();
                        if(_tempVariable_unsignedlong)
                        {
                            _ntpUdpServer.read(_NTPGetTime1_packetBuffer, 48);
                            _tempVariable_unsignedlong = (unsigned long)_NTPGetTime1_packetBuffer[40] << 24;
                            _tempVariable_unsignedlong |= (unsigned long)_NTPGetTime1_packetBuffer[41] << 16;
                            _tempVariable_unsignedlong |= (unsigned long)_NTPGetTime1_packetBuffer[42] << 8;
                            _tempVariable_unsignedlong |= (unsigned long)_NTPGetTime1_packetBuffer[43];
                            _tempVariable_unsignedlong=  _tempVariable_unsignedlong- 2208988800UL + 1;
                            _tempVariable_unsignedlong = _tempVariable_unsignedlong + 10800;
                            setTime(_tempVariable_unsignedlong);
                            _NTPGetTime1_iws = 0;
                            _NTPGetTime1_CR = 1;
                            _NTPGetTime1_hfp = 1;
                        }
                         else
                        {
                            _NTPGetTime1_iws = 0;
                        }
                    }
                }
                 else
                {
                    if (! _NTPGetTime1_hfp)
                    {
                        _tempVariable_unsignedlong = 30000;
                    }
                     else
                    {
                         _tempVariable_unsignedlong = 1800000;
                    }
                    if (_isTimer(_NTPGetTime1_lrt,  _tempVariable_unsignedlong))
                    {
                        WiFi.hostByName("ntp1.stratum2.ru", _NTPGetTime1_tsip);
                        memset(_NTPGetTime1_packetBuffer, 0, 48);
                        _NTPGetTime1_packetBuffer[0] = 0b11100011;
                        _NTPGetTime1_packetBuffer[1] = 0;
                        _NTPGetTime1_packetBuffer[2] = 6;
                        _NTPGetTime1_packetBuffer[3] = 0xEC;
                        _NTPGetTime1_packetBuffer[12] = 49;
                        _NTPGetTime1_packetBuffer[13] = 0x4E;
                        _NTPGetTime1_packetBuffer[14] = 49;
                        _NTPGetTime1_packetBuffer[15] = 52;
                        _ntpUdpServer.beginPacket(_NTPGetTime1_tsip, 123);
                        _ntpUdpServer.write(_NTPGetTime1_packetBuffer, 48);
                        _ntpUdpServer.endPacket();
                        _NTPGetTime1_iws  = 1;
                        _NTPGetTime1_lrt = millis();
                    }
                }
            }
        }
        if(_isTimer(_dht1Tti, 5000))
        {
            _dht1_humOut = _dht1.getHumidity();
            _dht1_tempOut = _dht1.getTemperature();
            _dht1Tti = millis();
        }
        RemoteXY.t_1 = _dht1_tempOut;
        RemoteXY.h_1 = _dht1_humOut;
        RemoteXY.ppm = _gtv1;
        if ((((RemoteXY.switch_2)) || ((_gtv1) < (1500.00))))
        {
             if (_trgrt1I)
            {
                 _trgrt1 = 0;
            }
             else
            {
                _trgrt1 = 1;
                _trgrt1I = 1;
            }
        }
         else
        {
            _trgrt1 = 0;
            _trgrt1I = 0;
        }
        ;
        digitalWrite(12, _trgrt1);
        if((RemoteXY.switch_1))
        {
            _tim2O = 1;
            _tim2I = 1;
        }
         else
        {
             if(_tim2I)
            {
                _tim2I = 0;
                _tim2P = millis();
            }
             else
            {
                 if (_tim2O)
                {
                    if (_isTimer(_tim2P, 300000)) _tim2O = 0;
                }
            }
        }
        if ((((((0) >= (0)) && (((hour())) < (17)))) || (_tim2O)))
        {
             if (_trgrt2I)
            {
                 _trgrt2 = 0;
            }
             else
            {
                _trgrt2 = 1;
                _trgrt2I = 1;
            }
        }
         else
        {
            _trgrt2 = 0;
            _trgrt2I = 0;
        }
        ;
        digitalWrite(14, _trgrt2);
    }
    bool _isTimer(unsigned long startTime, unsigned long period)
    {
        unsigned long currentTime;
        currentTime = millis();
        if (currentTime>= startTime)
        {
            return (currentTime>=(startTime + period));
        }
         else
        {
            return (currentTime >=(4294967295-startTime+period));
        }
    }
    int hexStrToInt(String instring)
    {
        byte len = instring.length();
        if  (len == 0) return 0;
        int result = 0;
        for (byte i = 0; i < 8; i++)    // только первые 8 цыфар влезуть в uint32
        {
            char ch = instring[i];
            if (ch == 0) break;
            result <<= 4;
            if (isdigit(ch))
            result = result | (ch - '0');
            else result = result | (ch - 'A' + 10);
        }
        return result;

    И вот схема с FLprog
    [ATTACH=full]24499[/ATTACH]

    Как интегрировать туда простое получение ppm из библиотеки mq135?

     

    Как интегрировать туда простое получение ppm из библиотеки mq135?
    Время 5 утра а я не могу победить((( Помогите прошу заклинаю[/code]
     
  10. ИгорьК

    ИгорьК Гуру

    Без IP не обойтись.
    Логика у меня такая. Каждое устройство подключено к MQTT брокеру и подписано, среди прочих, на топик, отправка команды на который заставляет его:
    1. передать свой IP адрес на брокер,
    2. перезагрузиться в режиме HTTP сервера для работы с файлами.
    После того, как вы сделали что вам требуется, устройство вновь перегружается.

    Посмотрите мои проекты в разделе http://forum.amperka.ru/forums/projects/
    Там практически в каждом это реализовано. В пакете файлов должен находиться "ide.lua", а чтобы понять как это работает - вызов, перезагрузка, смотрите файлы "mqttanalize.lua", "init.lua".

    Передаем команду и получаем адрес:

    upload_2021-12-28_22-5-47.png

    Переходим по адресу и видим список файлов, возможность редактировать, удалять, создавать новые:

    upload_2021-12-28_22-6-56.png

    Редактируем init.lua:

    upload_2021-12-28_22-7-43.png
     
    Последнее редактирование: 28 дек 2021
    DetSimen нравится это.
  11. t76480

    t76480 Нуб

    Добрый день!
    Захотелось вот заняться программированием esp32.
    Так как немного знаком с Python, то решил делать это на Micropython.
    И сразу вышел облом - многие функции esp32 не реализованы на Micropython.
    Например Mesh WiFi.
    Теперь смотрю в сторону Lua. Но беглым взглядом пока не могу понять как с этим делом обстоит в Lua.
    Могу ли я использовать через Lua все возможности и функции esp32? Или это тоже зависит от наличия своих библиотек?
     
  12. alp69

    alp69 Форумчанин

    На мой взгляд вопрос совершенно некорректен. Как на него ответить? Что Вы подразумеваете под ВСЕМИ возможностями и функциями esp32?
    Если устройство работает под Lua, то и библиотеки тоже будут на этом же языке (если не устраивать цирк с трансляцией из другого языка). И наличие или отсутствие библиотек не ограничивает возможный функционал контроллера (МК) в пределах возможностей языка программирования. Функционал может ограничить только юзер кривым кодом или кривыми руками. 'Библиотека' в общем виде - лишь сборник рутинных операций, используемых в коде, которая может содержать много лишнего, что не требуется для решения конкретной задачи, но потребует ресурсов.
    Все зависит от того, насколько Вы собираетесь загружать работой МК. Порой лишние несколько строк в коде выгоднее использования библиотеки (относительно термина 'библиотека' - см. P.S.). А если библиотека 'noname', то отказ от нее в пользу самописного кода (подпрограммы) порой является благом.
    P.S. Исключительно ИМХО - насколько вообще корректно употреблять термин 'библиотека' в контексте использования Lua?
     
    Последнее редактирование: 5 янв 2022
  13. ИгорьК

    ИгорьК Гуру

    Я же говорю, что Python - это ардуино будущего. Главная Ардуина - Raspberry Pico и ее будущее развитие.

    Это зависит от умения программировать и читать документацию. С меш не сталкивался, сказать точнее не могу.

    Модуль, библиотека - какая разница. Суть то одна.
     
  14. Mikola120

    Mikola120 Нуб

    Добрый день знатокам lua
    начал с нуля осваивать это дело и совсем застрял, бухнул тему на форум, но видимо уместнее здесь спросить
    http://forum.amperka.ru/threads/wemos-d1-mini-sim800.22925/
    Сюда тему переселять или пусть так будет?
    И что делать с этим softuartom?
     
  15. obuhanoe

    obuhanoe Гик

    Добрый день.
    Имеется собственный проект для удаленного полива участка на даче.

    Железо: Arduino Mega + Shield (RTC + SD карта) + SIM800L + SSR (Solid State Relay) 2 штуки (налив в емкость и вылев из нее)
    Код: C++

    Умеет выполнять следующие действия:
    1. Принимать СМС (перезагружать железо, график полива и т.д.)
    2. Отправлять СМС при включении
    3. Отправка EMAIL
    4. Управление при помощи DTMF
    5. Включение нагрузки при помощи DTMF/SMS
    6. Отправка лога работы на FTP
    7. Скачивание файла графика полива с FTP
    8. Скачивание графика полива с сайта

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

    Решил перевести проект на eSP8266 + Lua, реализовать пункты: 3,6,7,8 и добавить возможность работать с Telegram Bot (включить/выключить нагрузку, скачать/отослать файл на FTP и т.д.).

    И сразу натолкнулся на то, что все примеры работы с FTP, EMAIL и Telegram - все примеры на С++.
    Мои хотелки возможно реализовать на Lua?
    С Lua знаком, но не так близко как хотелось, но учиться как говориться никогда не поздно :)

    Спасибо.
     
  16. ИгорьК

    ИгорьК Гуру

    Привет!
    У меня также есть проект боле-менее того же свойства, но он умеет лишь поливать овощи и наполнять бочку для прогрева воды.

    Я не понимаю зачем ему управление в принципе - с рассветом он поливает и наполняет емкость, на закате он делает то же самое. О своем состоянии он сообщает MQTT брокеру, от него же может иногда получить команду внепланово наполнить емкость, водой, которую могут днем растащить для каких-то нужд.

    Не понимаю, зачем нужно это "управление из любой точки мира".
    Вот лог наполнения емкости, что ведет Home Assistant (и на который я посмотрел только для ответа Вам):
    upload_2022-6-8_9-25-57.png
    Вот первый скролл окна Home Assistant. Здесь уместился и весь полив:
    upload_2022-6-8_9-28-30.png

    Вот его окно, уменьшенное до предела, чтобы Вы увидели общее количество элементов, которые все равно не вместились:
    upload_2022-6-8_9-29-54.png
    Каждый элемент имеет свой собственный лог. И графики. Например, более значимые чем график полива:

    upload_2022-6-8_9-32-51.png

    upload_2022-6-8_9-34-40.png

    К чему это все?

    Предлагаю, искренне и с уважением к вашему труду, пересмотреть подход к любому устройству, отказавшись от управления им. Каждое устройство имеет свой алгоритм действий и лишь оповещает о своем состоянии MQTT брокер. С последним работает агрегатор умного дома по вашему выбору, протокол mqtt унифицирован для любого.

    Ваш подход мне не близок и я не знаю чем вам помочь. Работать с FTP и Е-MAIL ESP может, но никогда плотно я этим не занимался, ибо не видел смысла. MQTT куда мощнее для IoT.
     
    Последнее редактирование: 8 июн 2022
  17. obuhanoe

    obuhanoe Гик

    Возможно, но так как никогда с ним не работал - думал, что с Telegram проще, но могу конечно же ошибаться.
    Если MQTT заменит все выше указанное (почта, FTP, сайт) - то конечно я только рад что все будет в одном месте - но чувствую проект быстро не стартанет - а себе срок поставил до следующей весны.

    Теперь по этому:
    Управление нужно всего лишь для одного: увеличить, уменьшить время наполнения, отключения полива (дожди понимаете :) ) Доверять датчикам влажности (которых нужно по натыкать не одно устройство) я не могу.

    Таким образом: мне нужен будет только ESP (8266 или 32) код писать буду на Lua и MQTT - все верно?
    Ах, ну да забыл главное: время для написания и отладки своего кода ;)
     
  18. ИгорьК

    ИгорьК Гуру

    Посмотрите на моем сайте про mqtt, статья касается nooLite, но раскрывает почему mqtt и как устроено в целом.
     
    obuhanoe нравится это.
  19. ИгорьК

    ИгорьК Гуру

    Но надо сказать, кто наблатыкался в ардуино-си, JavaScript понимает с трудом. При чем здесь JavaScript? Дело в том, что NodeMCU Lua - это логика JavaScript (без последних ухищрений) в нотации Lua.
    Писать на всем этом быстро и (условно) просто, но мозг перестроить приходится очень, слишком серьезно.

    То есть, надо изучить одновременно JS и Lua. Готовы?

    upload_2022-6-8_10-59-46.png
     
  20. b707

    b707 Гуру

    не собираюсь переубеждать. просто интересно - если весь предыдущий код был на С++ - почему хотите перейти на Луа?