![](http://habrastorage.org/files/d31/3f7/227/d313f722711840339e388037165370ba.png)
В данной статье мы продолжим эксперименты с 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В
![](http://habrastorage.org/files/baf/1aa/7e2/baf1aa7e24474325bda320e250f268c8.webp)
Программная часть
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 для меня до сих пор тёмный лес.
Результаты
![](http://habrastorage.org/files/9e1/7b4/196/9e17b4196f6142a1a5c7b3b629885d56.png)
Получилось очень интересное устройство. Питание сделал от USB, соответственно можно брать куда угодно. PowerBank сегодня есть почти у каждого. По поводу Wi-Fi — поднимаем точку на телефоне и наш датчик снова в сети.
По ощущениям — действительно появляется дискомфорт при превышении CO2 уровня в 800-1000 ppm.
Комментарии (16)
jcmvbkbc
17.05.2015 20:57Сложность заключается в том, что UART у ESP8266 всего один
Полтора (на втором доступен только TX), а если не использовать SPI-Flash то два.
Второй находится по адресу 0x60000F00 и его TX торчит из GPIO2.imwode
17.05.2015 23:30А что делать вот с этим «находится по адресу»? А то мне тут надо было инвертнуть уарт, но так и не понял как к регистрам получить доступ, пришлось транзистором инвертировать.
jcmvbkbc
18.05.2015 01:03+1так и не понял как к регистрам получить доступ
С SDK идут примеры, открываете какой-нибудь examples/IoT_Demo/driver/uart.c и видите что-то такое:
WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity | UartDev.parity | (UartDev.stop_bits << UART_STOP_BIT_NUM_S) | (UartDev.data_bits << UART_BIT_NUM_S));
Определения этих макросов — в include/eahle_soc.h и examples/IoT_Demo/include/driver/uart_register.h, это обычная запись в MMIO.imwode
20.05.2015 03:28+1Хо хо, работает
Только почему-то в uart_register.h ошибка, там бит инверсии прописан как 12-й. А вот тут как 22-й, и это правильно
uart_init(BIT_RATE_9600, BIT_RATE_9600); SET_PERI_REG_MASK(UART_CONF0(0), BIT(22));
jcmvbkbc
20.05.2015 04:18Хо хо, работает
Поздравляю (:
Только почему-то в uart_register.h ошибка
Я не сильно удивлён; конечно лучше сверяться с документацией.
dannote
18.05.2015 02:35data = 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))
Все же лучше так:
local data = {} for i = 1, 8 do table.insert(data, ow.read(pin)) end local crc = ow.crc8(table.concat(data))
Klukonin
18.05.2015 07:56Я как-то все не могу уловить смысл использования локальных переменных и функций.
Так быстрее? Или это в целях экономии памяти?
ignat99
18.05.2015 10:08+1harizanov.com/wiki/wiki-home/three-channel-wifi-relaythermostat-board
Воот это, вероятно, очень хороший проект. Всё реализовано на ESP8266.
ignat99
18.05.2015 10:41www.artik.io/developer — Однако, новое поколение. Можно сделать регистрацию себе и получить устройство.
eschava
18.05.2015 17:58Сколько мА потребляет вся эта конструкция? Я так понимаю, что датчик CO2 находится во включенном состоянии все время?
ssh1 Автор
18.05.2015 20:31На всех измерителях тока для USB пишет 0 мA(до 10), иногда мигает 50 — 100 ма Получается что жрет только ESP8266.
Работает двое суток от PowerBank емкостью ~ 5000 mAh, сожрал пока 35%.
Meklon
Вопрос по питанию. Можно ли было просто взять линейный стабилизатор напряжения LM7803 и пару конденсаторов?
ssh1 Автор
Не пробовал. Он дает 3V, а это нижняя граница для ESP8266 (судя по даташиту 3.0-3.6V).
imwode
Лучше LM7833, главное не 78_l_33.
Meklon
А чем лучше? Для меня это актуально.
imwode
У меня на 3.12В барахлит, на форумах тоже пописывают что к питанию сильно чувствителен модуль. Мож и не в этом проблема…
Попробовать просто же, ничего не сгорит на 3В