• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Lua скрипты и модули

Victor

Administrator
Команда форума
ESPlorer часто использует куски LUA кода для выполнения некоторых операций (cat, save file to ESP и т.д.)
В конце выполнения кроме обнуления переменных я "обниляю" и обычные функции. После этого запускаю стандартную команду "collectgarbage()"
Поэтому рекомендую не делать так
Код:
sk:on("receive", function(sck, c) print('answer length is '..#c) end)
а делать так
Код:
function func1
print('func1')
end
sk:on("receive", func1)
...
...
func1=nil
collectgarbage()
как-то так...
 

Victor

Administrator
Команда форума
Точно!
А как сделать, чтоб этот скрипт всегда выполнялся? И после перезапуска модуля тоже?
Поместите код в init.lua или, что более красиво и надежно, поставьте в инит.луа настройку сети а потом по таймеру вызов другого файла с кодом для GPIO
 

skylocker

Member
Случайно увидел такой проект:
semi-HTTP-compliant lua libary to download files and send GET requests
Там в файле example.lua используется функция collectgarbage() как раз после освобождения памяти. Может, это оно?
Спасибо за отклик. Вроде бы похоже и на collectgarbage() из консоли не ругается, но в моем примере не работает:

заменил последнюю строчку на
sk:close() sk=nil sck=nil print(node.heap()) collectgarbage() print(node.heap()) tmr.delay(2000000) print(node.heap()) collectgarbage() print(node.heap()) tmr.delay(5000000) print(node.heap())

запустил, увидел в самом начале (перед выполнением) цифру 19608, а после выполнения всего - такой ответ:
18544
17784
17784
17728
17784
17728
>
> print(node.heap())
19344

Последнее - в интерпретаторе.. ((
 

skylocker

Member
В конце выполнения кроме обнуления переменных я "обниляю" и обычные функции. После этого запускаю стандартную команду "collectgarbage()"
Спасибо, попробую.

Но почему в процессе работы программы не видно результатов collectgarbage()?
 

Victor

Administrator
Команда форума
Спасибо, попробую.

Но почему в процессе работы программы не видно результатов collectgarbage()?
пока вы не разбили код на функции у вас все переменные глобальные. используйте именованные функции и локальные переменные. Обниляйте последовательно - локальные переменные в конце функции, затем по окончании работы функции онбиляйте и ее. Глобально используйте только если действительно необходимо.
collectgarbage() эффективен, когда вы обниляете большие строковые переменные и/или функции.
Код:
print(node.heap().."\r\n")
s="abc0123456789abc\r\n";
print(s)
print(node.heap().."\r\n")
s=nil
collectgarbage()
print(node.heap())
 

skylocker

Member
Обниляйте последовательно - локальные переменные в конце функции, затем по окончании работы функции онбиляйте и ее. Глобально используйте только если действительно необходимо.
collectgarbage() эффективен, когда вы обниляете большие строковые переменные и/или функции.
Спасибо! Попробую, отпишусь.
 

skylocker

Member
Чего-то не особо получилось.. ((

Вот лог:
> print(node.heap())
19864
> function func1(sck, c) print('answer length is '..#c) end
> print(node.heap())
19192
> sk=net.createConnection(net.TCP, 0)
> sk:eek:n("receive", func1)
> sk:connect(80, "api.skylocker.ru")
> sk:send("GET /get_data/test_str/ HTTP/1.1\r\nHost: api.skylocker.ru\r\n\r\n")
> answer length is 224
print(node.heap())
18584
> sk:close() sk=nil sck=nil func1=nil print(node.heap()) collectgarbage() print(node.heap()) tmr.delay(2000000) print(node.heap()) collectgarbage() print(node.heap()) tmr.delay(5000000) print(node.heap())
17808
17808
17768
17808
17768
> print(node.heap())
19400

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

Vasiks

Member
Почему, когда считываю состояние пина, то он вырубается? Делаю:
Код:
gpio.read(4)
и после этой строчки пин из HIGH переходит в LOW. Как считывать состояние не меняя этого состояния?
 

skylocker

Member
У меня тоже глюк при работе с GPIO или с самим Lua - я уже минут 30 зависаю, не знаю, куда копать:

Код:
s=net.createServer(net.TCP, 30)
s:listen(80, function(c)
    c:on("receive", function(c,pl)
        local i=adc.read(0)
        i=i*123/100
        print(i)
        gpio.mode(3,gpio.INPUT)
        local v=gpio.read(3)
        print(v)
        c:send("ADC:"..i.."\nGPIO(3):???\nTMR:"..tmr.now().." MEM:"..node.heap())
        c:on("sent",function(c) c:close() end)
        i,v=nil,nil
    end)
end)
Замечу, что работает нормально - в консоль вываливает значение ADC (переменная i) и GPIO0 (по новой таблице, 3 индекс, у меня переменная v).
Даже с ADC проблем нет, хотя в мануале написано было "The ADC cannot be used when the chip is transmitting", но там, вероятно, речь шла непосредственно о работе радиотракта (?).

Проблема (зависание и ребут SoC) возникает сразу после попытки вывести в HTTP-ответ значения переменной v - стоит изменить строку
c:send("ADC:"..i.."\nGPIO(3):???\nTMR:"..tmr.now().." MEM:"..node.heap())
на
c:send("ADC:"..i.."\nGPIO(3):"..v.."\nTMR:"..tmr.now().." MEM:"..node.heap())

Что тут не так? Я честно смотрю в мануал - там сказано, что gpio.read() возвращает number:0 - low, 1 - high, в консоли вижу, что v=1
Куда копать?
 
Что тут не так? Я честно смотрю в мануал - там сказано, что gpio.read() возвращает number:0 - low, 1 - high, в консоли вижу, что v=1
Куда копать?
Копать в node.heap(). Вот так работает:
Код:
s=net.createServer(net.TCP, 30)

s:listen(80, function(c)
  c:on("receive", function(c,pl)
  local i=adc.read(0)
  i=i*123/100
  print(i)
  gpio.mode(5,gpio.INPUT)
  local v=gpio.read(3)
  print(v)
   local h=node.heap()
   print(h)
  c:send("ADC:"..i.."\nGPIO(5):"..v.."\nTMR:"..tmr.now().." MEM:"..h)
  c:on("sent",function(c) c:close()  end)
  i,v,h=nil,nil,nil
  end)
end)
 

skylocker

Member
Копать в node.heap(). Вот так работает:
Код:
s=net.createServer(net.TCP, 30)

s:listen(80, function(c)
  c:on("receive", function(c,pl)
  local i=adc.read(0)
  i=i*123/100
  print(i)
  gpio.mode(5,gpio.INPUT)
  local v=gpio.read(3)
  print(v)
   local h=node.heap()
   print(h)
  c:send("ADC:"..i.."\nGPIO(5):"..v.."\nTMR:"..tmr.now().." MEM:"..h)
  c:on("sent",function(c) c:close()  end)
  i,v,h=nil,nil,nil
  end)
end)
Боюсь, Вы так и не ответили. В описании node.heap (нет ни слова про то, что нужно писать в переменную, только то, что "returns number"). Ваш способ похож на "метод научного тыка", без обид :)

Таким же способом я нашел, что и вот так будет работать:
Код:
s=net.createServer(net.TCP, 30)
s:listen(80, function(c)
    c:on("receive", function(c,pl)
        local i=adc.read(0)
        i=i*123/100
        print(i)
        gpio.mode(0,gpio.INPUT)
        local v=gpio.read(0)
        print(v)
        print(tmr.now())
        c:send("ADC:"..i.." GPIO(3):"..v.." MEM:"..node.heap())
        c:on("sent",function(c) c:close() end)
        i,v=nil,nil
        collectgarbage()
    end)
end)
У меня подозрения, что это какой-то баг nodeMCU или моя невнимательность (но я просто не вижу - где)..
 
Да без обид. В "сырых" (без тестирования) проектах данный метод незаменим))) Можно бесконечно читать доки. К сожалению исходники nodemcu недоступны?
 

skylocker

Member
Почему, когда считываю состояние пина, то он вырубается? Делаю:
gpio.read(4)
и после этой строчки пин из HIGH переходит в LOW. Как считывать состояние не меняя этого состояния?
Посмотрите в мануал к gpio.mode(), может, поможет - там речь идет о состоянии PULLUP-резистрора:

gpio.mode(pin, mode, pullup)
pullup: gpio.PULLUP or gpio.FLOAT, default: gpio.FLOAT
 
Работа GPIO в NodeMCU действительно не очевидна. В любом случае INPUT ЛУЧШЕ использовать с gpio.PULLUP, т.е. с подтягивающим (к питанию) внутренним сопротивлением! Если кнопка - то коммутировать на GND. Вход не будет "болтать"... А модуль очень чувствителен.
GND - коснитесь пальцем - модуль в reset.
GPIO0 - используется бутлоадером - лучше как вход (тем более без PULLUP) не использовать.
GPIO2 - заземлите и включите - вообще "крыша" у модуля сходит!!!
При GPIO16 - он же RESET - я вообще молчу.
 

skylocker

Member
Работа GPIO в NodeMCU действительно не очевидна. В любом случае INPUT ЛУЧШЕ использовать с gpio.PULLUP, т.е. с подтягивающим (к питанию) внутренним сопротивлением! Если кнопка - то коммутировать на GND. Вход не будет "болтать"... А модуль очень чувствителен.
GND - коснитесь пальцем - модуль в reset.
GPIO0 - используется бутлоадером - лучше как вход (тем более без PULLUP) не использовать.
GPIO2 - заземлите и включите - вообще "крыша" у модуля сходит!!!
При GPIO16 - он же RESET - я вообще молчу.
Не соглашусь. В корне.
Ибо, если подключать кнопку правильно (с подтягиванием внешним резистором - к VCC или земле) - работать будет 100% корректно. А уж если еще и с фильтром (см. инвертирующий триггер Шмитта + конденсатор), то аппаратно и от дребезга контактов можно избавиться.

Далее, ни разу не замечал того, что вы говорите про "палец на GND".. Может, у меня пальцы не такие? :)
Про GPIO2 расскажите подробнее (лучше - с картинкой с осциллографа при загрузке), а то так звучит, мягко говоря, очень поверхностно.

А что Вы имеете против "GPIO16 на RESET"? В мануале описано, что это нужно, если Вы хотите использовать DeepSleep-режим. И никаких глюков лично я тут не замечал - работает (проверял на новой ревизии ESP-07 с 16 пинами и на ESP-12).

В общем, мой мессадж такой - если пишете, то, плз, пишите детально - что именно делаете и что, на Ваш взгляд, работает не так.
И вот еще - проверьте, все ли нормально пропаяли )
 
Про GPIO2. ESP-01
Прошивка NodeMCU 2015 года или последняя 2014.
Без питания подключаем GPIO2 к GND. Включаем питание.
Непрерывно горит синий светодиод (ну и красный) и в COM порт что-то постоянно посылается.
У вас не так?
 

Vasiks

Member
Так что с чтением состояния GPIO? Получается не реально считать не отправляя пин в LOW?
 

skylocker

Member
Про GPIO2. ESP-01
Прошивка NodeMCU 2015 года или последняя 2014.
Без питания подключаем GPIO2 к GND. Включаем питание.
А зачем Вы при загрузке на GPIO2 подаете LOW?
В комментах к NodeMCU-devkit, например, черным по белому написано "On every boot/reset/wakeup: GPIO15 MUST keep LOW, GPIO2 MUST keep HIGH".
Умные люди тут наверняка даже ссылку на ESP8266_Pin_List_141105 и, возможно, даже объяснят, почему именно GPIO2 MUST keep HIGH (насколько я понял, MTDO, GPIO0 и GPIO2 совместно образуют 3 бита, которые определяют 8 разных конфигов загрузки; подавая LOW на GPIO2 Вы выбираете "remapping" вместо "UART Boot"; что такое remapping пусть лучше объяснят знатоки).
 

skylocker

Member
Так что с чтением состояния GPIO? Получается не реально считать не отправляя пин в LOW?
С чего бы вдруг? Все работает. Просто подтяжку используйте - программную (при инициализации порта указывайте pullup = gpio.PULLUP) или аппаратную (резистор к питанию).
 
Сверху Снизу