В данной статье мы продолжим эксперименты с Wi-Fi модулем ESP8266 и попробуем реализовать опрос датчика CO2 K-30 через MODBUS.
В первой части мы прошили в ESP8266 NodeMCU, подключили DS18b20 и научились отправлять данные о температуре в облако. Попробуем добавить опрос датчика CO2.
Самое интересное реализовать весь функционал в ESP8266 не подключая внешний контроллер
Hardware и подключение
Добавляем к конфигу из предыдущей статьи датчик K-30.
Соединяем UART RX, UART TX и GND у датчика K-30 и ESP8266. Питание у них будет разное.
Сложность заключается в том, что UART у ESP8266 всего один, так что либо консоль и отладка, либо K-30
Внимание! Питание у K-30 5-14В, у ESP8266 — 3.3В.
Я решил данную проблему применив преобразователь 5->3.3В
Программная часть
1) init.lua — практически не изменился
--init.lua
print("Setting up WIFI...")
wifi.setmode(wifi.STATION)
--modify according your wireless router settings
wifi.sta.config("YOUR_SSID","YOUR_PASSWD")
wifi.sta.connect()
tmr.alarm(1, 1000, 1, function()
if wifi.sta.getip()== nil then
print("IP unavaiable, Waiting...")
else
tmr.stop(1)
print("Config done, IP is "..wifi.sta.getip())
dofile("all.lua")
end
end)
2) all.lua — код опроса датчиков и отправки данных на сервер
pin = 6
t = 0
function read(addr, unit)
ow.setup(pin)
result = nil
flag = false
if(addr == nil) then
ow.reset_search(pin)
count = 0
repeat
count = count + 1
addr = ow.search(pin)
tmr.wdclr()
until((addr ~= nil) or (count > 100))
ow.reset_search(pin)
end
if(addr == nil) then
return result
end
crc = ow.crc8(string.sub(addr,1,7))
if (crc == addr:byte(8)) then
if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then
ow.reset(pin)
ow.select(pin, addr)
ow.write(pin, 0x44, 1)
present = ow.reset(pin)
ow.select(pin, addr)
ow.write(pin,0xBE,1)
data = nil
data = string.char(ow.read(pin))
for i = 1, 8 do
data = data .. string.char(ow.read(pin))
end
crc = ow.crc8(string.sub(data,1,8))
if (crc == data:byte(9)) then
t = (data:byte(1) + data:byte(2) * 256) * 625
t = t / 10000
return t
end
tmr.wdclr()
else
end
else
end
return result
end
function sendt(t,co,key)
print("Temp:"..t.." C\n")
conn=net.createConnection(net.TCP, 0)
conn:on("receive", function(conn, payload) print(payload) end)
conn:connect(80,'184.106.153.149')
conn:send("GET /update?key="..key.."&field1="..t.."&field2="..co.." HTTP/1.1\r\n")
conn:send("Host: api.thingspeak.com\r\n")
conn:send("Accept: */*\r\n")
conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
conn:send("\r\n")
conn:on("sent",function(conn)
print("Closing connection")
conn:close()
end)
conn:on("disconnection", function(conn)
print("Got disconnection...")
end)
end
uart.setup(0,9600,8,0,1,0)
uart.on("data", 0,
function(data)
--print("receive from uart:", data)
if string.len(data) == 7 then
result = string.byte(data,4)*256 + string.byte(data,5)
print (result)
sendt(t,result,"YOUR_KEY")
end
end, 0)
function sendData()
t = read()
uart.write(0,0xFE,0x04,0x00,0x03,0x00,0x01,0xD5,0xC5)
end
tmr.alarm(0, 60000, 1, function() sendData() end )
Алгоритм работы:
- Инициализируем UART на 9600
- Устанавливаем callback на получение данных из UART. В случае получения пакета из 7 байт(ответ K-30 по MODBUS) отправляем данные на thingspeak.com
- Каждую минуту опрашиваем датчик температуры DS18b20 и отправляем в UART запрос данных по CO2. Запрос найден в даташите
Раскидать по отдельным файлам не получилось, не хватало памяти, поэтому реализовал как смог. Lua для меня до сих пор тёмный лес.
Результаты
Получилось очень интересное устройство. Питание сделал от USB, соответственно можно брать куда угодно. PowerBank сегодня есть почти у каждого. По поводу Wi-Fi — поднимаем точку на телефоне и наш датчик снова в сети.
По ощущениям — действительно появляется дискомфорт при превышении CO2 уровня в 800-1000 ppm.