• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

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

Melanolik

New member
Подскажите, а никто не переписывал модуль для ds18b20? смотрь его код на оф сайте и не совсем понимаю:
nodemcu-firmware/ds18b20.lua at master · nodemcu/nodemcu-firmware · GitHub

Строка 12:
_G[modname] = M

Строка 32:
setfenv(1,M)

Строка 65:
flag = false явно больше нигде не используется.

-- Return module table
return M

Как данные попадают в M?

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

nikolz

Well-known member
Подскажите, а никто не переписывал модуль для ds18b20? смотрь его код на оф сайте и не совсем понимаю:
nodemcu-firmware/ds18b20.lua at master · nodemcu/nodemcu-firmware · GitHub

Строка 12:
_G[modname] = M

Строка 32:
setfenv(1,M)

Строка 65:
flag = false явно больше нигде не используется.

-- Return module table
return M

Как данные попадают в M?

Мне кажется в модуле явно что-то лишнее, которого там не должно быть и все на много проще.
M - это таблица
_G[modname] = M -- это запись этой таблицы в глобальную под именем файла
Т е таким образом создается module под названием ds18b20
В него и загрузится код из этого файла
В результате Вы получите все функции которые в этом файле и будете обращаться к ним
типа ds18b20.setup(..)
flag действительно не используется внутри М, но он глобальный в таблице M, т е к нему можно обратится из вне. Возможно он для чего-то нужен.
-------------------------------------------
Я вообще писал на луа свою библиотеку для ds1820 она раз в пять быстрее работала.
Но сейчас на луа не пишу.
В настоящее время делаю библиотеку для интерфейса 1wire (в т числе и для 1820) на основе прерываний от пинов и таймера. В результате загрузка процессора подобными устройствами уменьшится раз в 1оо.
 

Melanolik

New member
Спасибо, пересмотрел как раз видео:
И теперь если позволите, еще возникло несколько вопросов:
он на 18.10 говорит что можно включить 9битный режим и тогда заберать температуру без дробных чисел, что значительно ускорит работу датчика. Еще вопрос есть по SKIP_ROM не совсем понятно в случае lua как будут 2 датчика отрабатывать. Не могли бы вы эти моменты не много подробней описать?
 

nikolz

Well-known member
Спасибо, пересмотрел как раз видео:
И теперь если позволите, еще возникло несколько вопросов:
он на 18.10 говорит что можно включить 9битный режим и тогда заберать температуру без дробных чисел, что значительно ускорит работу датчика. Еще вопрос есть по SKIP_ROM не совсем понятно в случае lua как будут 2 датчика отрабатывать. Не могли бы вы эти моменты не много подробней описать?
-------------------------------------------
Вообще-то нет особой разницы в реализации программы на луа или на си.
Вернее сказать, на луа все функции(чтение запись бита, байта, массива) Реализованы на СИ и загружаются в нативном коде ESP.
Команда SKIP_ROM выдается всем устройствам, чтобы они читали все и исполняли одновременно.
Т е после SKIP_ROM выдается команда запуска АЦП(преобразования температуры) 0xBE,
все датчики дружно преобразуют, если питание не паразитное, то датчики выдают сигнал готовности на шину и по нему можно приступить к чтению данных.
Для этого перебираем адреса устройств и читаем из них данные.
Если точность не требуется, то при инициализации устройств настраиваем их на 9 бит а не на 12,
для этого надо записать в 4 байт соответствующие значения в 6 и 5 биты.
Если надо точность 9 бит(время преобразования 93.75 ms) надо записать 00, а для 12 бит (750 ms) надо
записать 11.
----------------------------------------
 

Melanolik

New member
Хм, потихоньку двигаюсь дальше, спасибо за вашу помощь.
Вот теперь застрял в таком вопросе:
ow.select() принимает pin и rom.
у меня есть адрес датчика: 28FFB95244160320, вот интересно как этот адрес на lua можно преобразовать в этот самый rom чтобы обратиться сразу к датчику напрямую, может знаете?
 

nikolz

Well-known member
Хм, потихоньку двигаюсь дальше, спасибо за вашу помощь.
Вот теперь застрял в таком вопросе:
ow.select() принимает pin и rom.
у меня есть адрес датчика: 28FFB95244160320, вот интересно как этот адрес на lua можно преобразовать в этот самый rom чтобы обратиться сразу к датчику напрямую, может знаете?
--------------------------------------
На самом деле не надо знать заранее адреса устройств.
Функция addr = ow.search(pin) (стр 52) определяет адреса всех устройств и записывает их в таблицу.
pin - это номер контакта nodemcu
например
pin=2 --второй
rom - это код команды
например
rom=0xBE -- команда запустить преобразование
-----------------------------------
Рекоменду использовать готовые примеры.
с сайта
http://nodemcu.com/index_en.html#fr_5475f7667976d8501100000f
или из исходников nodemcu-firmware.
------------------------------------
Выкладываю в качестве примера свои функции (написаны год назад) "как есть"
--------------------------
Код:
--nk_start.lua  04.04.2015  kamnik@mail.ru
---print(wifi.sta.getap())
collectgarbage()
local ae={{96,209,111,6,0,0,149},{199,186,111,6,0,0,45}}
TT=0; adT={}; tstart=0; AT={};tAM={0;0;0};
if type(ae)=="table" then
  for j=1,#ae do local x=ae[j];local a=string.char(40);
  for m=1,7 do a=a..string.char(x[m]); end;
  adT[#adT+1]=a;
  end
end
local scl=4; local sda=5; tD={0,0};tstart=tmr.now()
i2c.setup(0, sda, scl, i2c.SLOW)
dofile("cof_1.lc")
dofile("get_adr.lc")
collectgarbage()
-----------------------------------
Код:
--cb18b20.lua  04.04.2015  kamnik@mail.ru
-----------------------------------------
collectgarbage()
ow.reset(pin) ow.skip(pin) ow.write(pin,0x44,0)
gpio.mode(pin,gpio.INT)
collectgarbage()
local function _cb()
if T1820==nil then T1820={}; end
for i=1,#adT do T1820[i]=0;
  ow.reset(pin);
  ow.select(pin,adT[i]);
  ow.write(pin,0xBE,0);
  local data=ow.read_bytes(pin,8)
  if ow.crc8(data)==0 then
  local x=(data:byte(1)+data:byte(2) * 256)
  if bit.isset(x,15) then x=1-bit.bxor(x, 0xffff) end
  x = x*0.0625; if x~=85 then TEMP[i]=x;  end
  end
end
gpio.mode(pin,gpio.OUTPUT)
end;
gpio.trig(pin, "high",function (lev)_cb();end);
-----------------------------------
это главная функция:
Код:
--main.lua  04.04.2015 kamnik@mail.ru
-----------------------------------------
dofile("nk_start.lc")
--print("1="..collectgarbage("count")..">"..node.heap());
collectgarbage()
function cb()
collectgarbage()
if ip==nil then dofile("wifi_1.lua") end
--print("2="..collectgarbage("count")..">"..node.heap());
if ip~=nil and is==nil then
dofile("srv_1.lua");
is=1;
end
--print("3="..collectgarbage("count")..">"..node.heap());
dofile("cbAM2302.lc");
--print("4="..collectgarbage("count")..">"..node.heap());
dofile("cb18b20.lua");
--print("5="..collectgarbage("count")..">"..node.heap());
dofile("get_tp.lc"); dofile("norm.lc");
--print("6="..collectgarbage("count")..">"..node.heap());
end
tmr.alarm(3,5000,1,cb)
----------------------------------
уберите в ней то, что не нужно
и исправьте расширение функций, так как я использую внешний компилятор для луа и загружаю сразу байт-код.
уберите комментарии у print и получите вывод на экран.
---------------------------------
 

Melanolik

New member
Спасибо вам огромное, сегодня почитаю как вы реализовывали.

Да, на готовых примерах из прошивки все завелось, но мне это не нравится. Как уже писал раньше там можно вырезать все лишнее и еще лучше когда ты понимаешь как оно работает а не занимаешься копипастом.
Спасибо вам.

К стати еще одна не совсем понятная для меня функция:
ow.crc8()
В документации говорится:
>Compute a Dallas Semiconductor 8 bit CRC, these are used in the ROM and scratchpad registers.

В базовой библиотеке они делают:
crc = ow.crc8(string.sub(addr,1,7))
if (crc == addr:byte(8)) then

не могли бы вы обьяснить зачем они используют crc если у нас и так извстен адрес устройства?
 

Ronin

New member
Господа, всем добрый день
Помогайте плз.
делаем wi fi кнопку для рабочего проекта и нужно ее будет часто перемещать с места на место и подключать к разным сетям соотвественно
Сделали web сервер и написали к нему типа стартовой странички на которой вводить имя сети и пароль к ней нужно.
Но есть две вещи которые бы тоже хотелось реализовать но че то не получается
1) Как вставить картинку в стартовую страницу? И чтобы она еще и отображалась.
2) Как сделать сканирование и выбор доступных сетей из списка на этой же странице? ( чтобы на вспоминать имя сети к которой надо подключиться)
 

Ronin

New member
Согласен enduser_setup штука крутая, но дело в том что в с этими последними версиями nodemcu как то странно у меня работает node.dsleep(0) во первых почему то повторно вызывается srv:eek:n(disconnection) и самое главное модуль уходит в слип а потом как бы чуть чуть просыпается, в терминал приходит пара символов с которой обычно начинается загрузка модуля

вообщем как то неправильно у меня новые версии nodeMcu работают, поэтому ищу альтернативу enduser_setup в старых версиях
 

NeoroN

Member
В старых версиях вообще небыло списка сетей, поэтому будет невозможно реализовать то что вам нужно. Нужно искать золотую середину где уже метод есть wifi - NodeMCU Documentation

Так что вам придется скорее всего без списка сетей, а картинку можно так вставить
 

Ronin

New member
Хм, вроде вот это выводит список сетей
  1. -- print ap list
  2. function listap(t)
  3. for k,v in pairs(t) do
  4. print(k.." : "..v)
  5. end
  6. end
  7. wifi.sta.getap(listap)
Как только это к Html привязать
 

NeoroN

Member
Чтобы страница не подвисала на момент сканирования сети лучше сделать дополнительный обработчик пути типа /aplist в вашем сервере в виде JSON, а на странице сделать JavaScript который переодически запрашивает этот JSON и выводит результат в список(табличку), по щелчку на строку поле с именем заполняется значением из таблицы, остается только ввести пароль.

тоесть на странице примерно такой скрипт Основы XMLHttpRequest
потом JSON.parse() получаем массив, перечисляем его через for(v in arr){arr[v].mac;arr[v].name }

вообще посмотреть как это сделано на страницах endusersetup - сделать что-то подобное.

Если нужен конкретный код, то давайте ваш код, будем допиливать.
 
Последнее редактирование:

Ronin

New member
NeoroN, сам я такое точно не напишу. Может сможешь помочь? Не бесплатно конечно
 

sergey200602

New member
Подскажите, пожалуйста, как многократно открывать serial порт в LUA
port = SerialPort.new(COMname, 9600, 8, 1, "NONE", 0, false)
это успешно открывает порт (тест на Windows7)
port = nil;
это успешно закрывает порт

... и повторно открыть его не получается никогда, не даром в мануале написано port = nil - уничтожение объекта. видимо насмерть
 

Foss

New member
Добрый день, подскажите пожалуйста как мне правильно принять данные, отправленные на esp8266 по ip адресу 192.168.4.1 на порт 80 андроид приложением, написанным для телефона?
прошивка NodeMCU 0.9.5 nodemcu_integer_0.9.5_20150318.bin
 

Foss

New member
1) убедитесь, что у ESP действительно такой ip адрес.
2) вот здесь пример простого HTTP сервера.
NodeMcu -- An open-source firmware based on ESP8266 wifi-soc.
На андроиде соответственно у Вас клиент.
3) Также рекомендую почитать документацию:
NodeMCU Documentation
а также перейти на новую версию выше 1.0
будет существенно больше свободной памяти.
Найдите на форуме адрес сайта, где можно заказать нужную сборку (уже не помню)
У ESP точно такой адрес как я указал в программе на андроид
Пробовал вот так принять данные на ESP:
sv = net.createServer(net.TCP, 30)

function receiver(sck, data)
print("услышали", data)
print("услышали")
sck:close()
end

if sv then
print("сервер запущен")
sv:listen(80, function(conn)
print("слушаем")
conn:eek:n("receive", receiver)
conn:send("hello world")
end)
end

И пробовал вот так принять данные на ESP:
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
conn:eek:n("receive",function(conn,payload)
print(payload)
conn:send("<h1> Hello, NodeMCU!!! </h1>")
end)
conn:eek:n("sent",function(conn) conn:close() end)
end)
Но оба варианта не работают, данные не принимаются, может у вас есть какие догадки?
 

Foss

New member
вместо этого
print("сервер запущен")
лучше написать так
print("сервер запущен sv="..sv)
--------------------------------------------
Какие сообщения получаете на терминал?
--------------
я делал на луа два года назад.
вот тут примеры:
net - NodeMCU Documentation
Показывает сервер запущен и все, во втором случае вообще ничего не показывает
 
Последнее редактирование:

PavelAndreev

New member
Всем здравствуйте. Нужна Ваша помощь. Имеется скрипт Lua, который отправляет данные с ds18b20 на мой сайт. На сайте для приема данных написан php код (см. ниже). Подскажите, можно ли подправить код так, чтобы данные отправлялись не с ds28b20, а с dht11? Понятно, что изменить просто название одного датчика на другой, этого будет мало.

Код:
require('ds18b20');
ds18b20.setup(1);
addres=ds18b20.addrs();
server="mysite.ru";
function sendData()
local params = "";
for key,value in pairs(addres) do
params = params..string.format("t%d=%f&",key+100,ds18b20.read(value));
end
conn=net.createConnection(net.TCP, 0)
conn:on("receive", function(conn, payload) print(payload) end)
conn:on("connection", function(sck) sck:send("GET /term/termometer.php?"..params.." HTTP/1.1\r\nHost: "..server.."\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n") end )
conn:on("sent",function(conn)conn:close()end)
conn:connect(80,server)
end
if addres~=nil then
for key,value in pairs(addres) do print(string.format("t%d=%f",key,ds18b20.read(value)));end;
sendData()
tmr.alarm(0, 60000, 1, function() sendData() end )
end
PHP:
<?php
$t=array();
$params=false;
for ($i = 1; $i <= 100; $i++) {
if(isset($_GET["t".$i])){$t[$i]=floatval($_GET["t".$i]);$params=true;}
}
foreach($t as $key=>$val){
$fp = fopen("t$key.txt", 'w');
fwrite($fp, sprintf("%s,%.2f",date("d.m.Y H:i:s"),$val));
fclose($fp);
$fp = fopen("t$key-log.csv", 'a+');
fwrite($fp, sprintf("%s,%.3f\n",date("d.m.Y H:i:s"),$val));
fclose($fp);
$image = imageCreateFromPng("termometer.png");
if(is_resource($image)) {
  $font_file = 'arial.ttf';
  imagefttext($image, 20, 0, 55, 55, $black, $font_file, sprintf("%.2f C",$val));
  imagefilledrectangle($image, 32, 90, 34, 48-$val, imagecolorallocate($image, 186, 53, 31));
  imagettftext ($image, 10, 0, 63, 103, $white, $font_file, date("H:i d.m"));
  imagepng($image,"thermometer$key.png");
}
}
if(!$params){
echo '<html lang="ru-RU"><body>';
for ($i = 1; $i <= 100; $i++) if(file_exists("thermometer$i.png")){echo"<img src=thermometer$i.png?t=".rand(1,1000000).">";}
echo '</body></html>';
}else{
echo "OK";
}
?>
 
Сверху Снизу