ESP8266:Примеры/Погодная станция на базе ESP8266, регистрирующая данные в Excel
Погодная станция на базе ESP8266, регистрирующая данные в Excel[1]
Эта статья рассказывает, как установить беспроводное соединение между двумя модулями ESP и отправлять данные от трех датчиков в электронную таблицу Excel. По сути, этот проект – погодная станция, которая имеет функцию регистрации данных и может быть реализована в домашних условиях.
Но сначала вам нужно будет пройти следующие руководства:
- Как начать работать с трансиверным WiFi-модулем на базе ESP8266
- Как наладить коммуникацию между двумя ESP8266
- Как загрузить прошивку на ESP8266 при помощи NodeMCU на Windows
Общий план проекта
Ниже – рисунок, объясняющий принцип работы проекта:
Необходимые компоненты
- Рекомендуемый вариант – два модуля ESP-12E; альтернативный вариант – два модуля ESP-201 + один программатор FTDI
- Один температурный датчик DS18B20
- Одна макетная плата
- Три кнопки
- Три резистора на 10 кОм
- Один резистор на 4700 Ом
- Один потенциометр на 10 кОм
Справочная информация
Основы программирования на Lua
Это скриптовый язык программирования, написанный на C. Разработка этого проекта началась в 1993 году силами Роберту Иерузалимски, Луиша Энрике де Фигейреду и Валдемара Келе, работавшими тогда в подразделении Tecgraf при Католическом университете Рио-де-Жанейро.
Более подробно об этом языке программирования можно почитать в «Википедии».
Прошивка NodeMCU для ESP8266 основана на Lua, поэтому если вы хотите писать собственные скрипты для ESP8266, вам важно знать основы этого языка.
Переменные
Переменные в языке Lua не делятся по типу данных, но делятся по области видимости. Это значит, что переменные в Lua могут быть глобальными или локальными.
- Глобальные переменные. Все переменные по умолчанию считаются глобальными (если в коде специально не задано, что они локальные).
pin = 3 test = "It works!"
- Локальные переменные. Если переменная задана локальной, область ее видимости будет ограничена лишь ее функцией.
local pin = 3 local test = "It works!"
- Поля таблиц. Это особый тип переменных, в которых может храниться все, за исключением «nil» (мы это затрагивать не будем).
Типы данных (типы значений)
Lua – это язык с динамической типизацией, поэтому у переменных нет типов данных. Типы данных есть только у значений. Значения могут храниться в переменных, передаваться в виде параметров и возвращаться в виде результатов.
В таблице ниже показаны типы данных для значений в языке Lua.
Тип значения | Описание |
---|---|
Строка (string) | Массив символов |
Число (number) | Действительное (двойной точности с плавающей запятой) число |
Булево значение (boolean) | Значение «true» или «false». Как правило, используется для проверки выполнения условий |
Функция (function) | Функция, написанная на Lua |
Неопределенное значение (nil) | В такой переменной не хранится никаких данных |
Таблица (table), пользовательские данные (userdata) и поток (thread) | Эти три типа данных мы затрагивать не будем |
Вот примеры некоторых из этих типов значений:
print(type("Hello world!")) –- строка
print(type(7)) -- число
print(type(true)) -- булево значение
print(type(print)) -- функция
print(type(nil)) -- неопределенное значение
Комментарии
Комментарии – это просто текст, в котором программист объясняет, как работает его код. Если какой-то фрагмент кода помечен как комментарий, то ESP-модуль проигнорирует его и не будет обрабатывать. Комментарии начинаются с двух тире («--»). Вот два типа комментариев:
- Однострочные комментарии:
print("Hello World!") –- комментарий в одну строчку
- Многострочные комментарии:
--[[ print("Hello World!") – это многострочный комментарий --]]
Операторы
Оператор – это символ, который говорит интерпретатору выполнить определенное математическое или логическое действие. В язык Lua встроено много операторов разных типов:
- Арифметические операторы;
- Операторы сравнения;
- Логические операторы;
- Прочие операторы;
Читая таблицы и примеры ниже, представьте, что имеете дело с двумя переменными: «А», в которой хранится значение «1», и «B», в которой хранится значение «2».
A = 1
B = 2
Арифметические операторы
Оператор | Пример | Результат |
---|---|---|
+ | A + B | 3 |
- | A - B | -1 |
* | A * B | 2 |
/ | B / A | 2 |
% | B % A | 0 |
^ | B^2 | 4 |
- | -A | -1 |
Операторы сравнения
Оператор | Пример | Результат |
---|---|---|
== | (A == B) | false |
~= | (A ~= B) | true |
> | (A > B) | false |
< | (A < B) | true |
>= | (A >= B) | false |
<= | (A <= B) | true |
Логические операторы
Оператор | Пример | Результат |
---|---|---|
and (и) | (A and B) | false |
or (или) | (A or B) | true |
not (не) | !(A and B) | true |
Оператор конкатенации
Теперь представьте, что у нас две новые переменные:
a = "Hello!"
b = "World!"
Оператор | Пример | Результат |
---|---|---|
.. | a..b | "Hello World!" |
Циклы
Цикл позволяет выполнить блок кода несколько раз, пока выполняется заданное условие. Во фрагменте кода ниже – пока значением в переменной «boolean_value» является «true».
-- цикл while
while boolean_value
do
-- код будет выполняться, пока в «boolean_value» будет «true»
end
-- и цикл for
for min, max, increment
do
-- код будет выполняться, пока не будет достигнуто макс. значение
end
Операторы if… else
Операторы if... else (т.е. «если... иначе») – один из самых важных инструментов для управления программой. Они используются следующим образом:
if boolean_value then
-- если в переменной «boolean_value» значение «true»
else
-- если в переменной «boolean_value» значение «false»
end
Названия этих операторов говорят сами за себя. Если выполнено условие «boolean_value=true», то программа выполнит код, идущий после «if». Но если условием является «boolean_value=false», то программа выполнит код, идущий после «else».
Функции
Функции – отличный способ организации кода. Если вы хотите сделать в программе что-либо несколько раз, вам необязательно по несколько раз прописывать этот код. Можно просто создать отдельную функцию, содержащую этот код, а затем вызывать ее, когда вам нужно.
Ниже показано, как создать новую функцию, принимающую один параметр (температуру в градусах Кельвина) и преобразующую это значение в градусы Цельсия и Фаренгейта.
function displayTemperature(kelvin)
celsius = kelvin – 273.15
print("Temperature in Celsius is: ", celsius)
fahrenheit = (celsius*9/5+32)
print("Temperature in Fahrenheit is: ", fahrenheit)
end
k = 294 –- температура в градусах Кельвина
displayTemperature(k) –- эта строчка вызывает функцию, созданную выше
DS18B20 – цифровой температурный датчик с шиной 1-Wire
В этом проекте мы воспользуемся датчиком DS18B20. Давайте разберемся, как его подключать.
DS18B20 можно питать напряжением от 3,0 до 5,5 вольт, поэтому вы можете смело подключить GND к GND, а VDD – к 3.3V на ESP8266.
Затем подключите контакт DQ к IO04 на ESP8266. На контакте DQ также понадобится подтягивающий резистор на 4,7 кОм, чтобы подтянуть напряжение к 3,3 вольт.
Считывание АЦП-значения
Для считывания аналоговых данных мы воспользуемся контактом ADC на ESP. Впрочем, этот контакт называют по-разному (и все эти названия взаимозаменяемы):
- ADC (от «analog-to-digital converter», т.е. «аналогово-цифровой преобразователь»)
- TOUT
- Контакт 6
- A0
- Аналоговый контакт 0
Все эти термины – для одного и того же контакта на ESP8266. Более подробно о нем можно почитать в этой статье.
На данный момент контакт ADC имеет 10-битное разрешение, а также входное напряжение от 0 до 1,0 вольт (если питается от внешней цепи).
Доступ к контакту ADC на ESP8266
На ESP-201 получить доступ к контакту ADC очень просто – вам нужно лишь подключить провод-перемычку к контакту, выделенному красным цветом на рисунке ниже:
Прошивка обоих ESP при помощи NodeMCU
Для этого проекта мы воспользуемся прошивкой NodeMCU, и о том, как загрузить ее на ESP, читайте тут.
Загрузка ESPlorer IDE
Для загрузки скриптов на ESP8266 рекомендую использовать программу ESPlorer IDE (она создана пользователем 4refr0nt). Чтобы скачать и установить ее, проделайте следующее:
- Кликните здесь, чтобы скачать ZIP-архив с ESPlorer IDE
- Распакуйте архив
- Перейдите в главную папку
- Запустите файл «ESPlorer.jar»
- Откройте ESPlorer IDE
Загрузка скрипта на ESP8266 (при помощи 3,3-вольтового программатора FTDI)
Чтобы загрузить скрипт на ESP8266 (и для клиента, и для сервера), вам нужно лишь настроить последовательное соединение между программатором FTDI и модулем ESP8266. Делается это следующим образом:
- Контакт VCC на ESP8266 – к контакту 3.3V на программаторе
- Контакт GND – к контакту GND
- Контакт TX – к контакту RX
- Контакт RX – к контакту TX
- GPIO-контакт 0 – к контакту 3.3V
- GPIO-контакт 15 – к контакту GND
Скрипты для клиента
На клиента нужно будет загрузить три скрипта:
- init.lua
- counterMax.lua
- sa18b20.lua (по этой ссылке – версия, измеряющая температуру в °C, а по этой – в °F)
Начните с загрузки скрипта «counetMax.lua». По сути, этот скрипт – просто цифра «1», которая работает счетчиком и помогает сбросить плату при разрыве соединения с сервером:
1
Когда вы загрузите скрипт, ESPlorer IDE напечатает вот такую ошибку:
Затем загрузите на ESP8266 скрипт под названием «ds18b20.lua» (убедитесь, что он назван именно так). Он есть в двух версиях: одна позволяет считывать температуру в градусах Цельсия, а другая – в градусах Фаренгейта.
--------------------------------------------------------------------------------
-- Скрипт к температурному датчику DS18B20 (1-Wire) для NODEMCU
-- ЛИЦЕНЗИЯ: http://opensource.org/licenses/MIT
-- Автор - Vowstar <vowstar@nodemcu.com>
-- Оптимизировал: Питер Скэргилл (Peter Scargill)
--------------------------------------------------------------------------------
-- Задаем название модуля, чтобы потом
-- сделать его параметром для setfenv()
local modname = ...
local M = {}
_G[modname] = M
--------------------------------------------------------------------------------
-- Локально используемые модули
--------------------------------------------------------------------------------
-- Модуль для таблицы
local table = table
-- Модуль для строки
local string = string
-- Модуль для шины 1-Wire
local ow = ow
-- Модуль для таймера
local tmr = tmr
-- Расчеты ограничены окружением «local»
setfenv(1,M)
--------------------------------------------------------------------------------
-- Реализация – постарался сделать как можно короче
--------------------------------------------------------------------------------
function readNumber(pin)
ow.setup(pin)
ow.reset(pin)
ow.write(pin, 0xCC, 1)
ow.write(pin, 0xBE, 1)
data = nil
data = ""
for i = 1, 2 do
data = data .. string.char(ow.read(pin))
end
t = (data:byte(1) + data:byte(2) * 256) / 16
if (t>100) then
t=t-4096
end
ow.reset(pin)
ow.write(pin,0xcc,1)
ow.write(pin, 0x44,1)
return t
end
-- Возвращаем модуль «table»
return M
Наконец, загружаем на ESP главный скрипт под названием «init.lua».
-- Беспроводная погодная станция с регистрацией данных
-- в таблицу Excel при помощи Things Gateway
-- Автор: Ив Абур (Yves Arbour)
--
-- Скрипт основан на следующих работах:
--
-- Руи Сантос (Rui Santos) – Клиент ESP8266
-- Скрипт к температурному датчику DS18B20 (1-Wire) для NODEMCU
-- Vowstar <vowstar@nodemcu.com>
-- Питер Скэргилл (Peter Scargill)
-- Wimp Weather Station; автор: Нейтан Сидле (Nathan Seidle), sparkfun
wifi.sta.disconnect()
wifi.setmode(wifi.STATION)
wifi.sta.config("test","12345678")
wifi.sta.connect()
print("Looking for a connection") // "Поиск соединения"
temp=0
function readds18b20sensor()
t=require("ds18b20.lua")
-- print(t.readNumber(2)) for debuging
temp = (t.readNumber(2)) --GPIO 04
end
winDirection=0
gpio.mode(0,gpio.INPUT)
function readWindDirection ()
windDirection = adc.read(0)
if (windDirection < 26) then windDirection=90 --E
--if (windDirection < 17) then windDirection=113 -- ESE
--elseif (windDirection < 21) then windDirection=68 -- ENE
--elseif (windDirection < 26) then windDirection=90 -- E
--elseif (windDirection < 36) then windDirection=158 -- SSE
elseif (windDirection < 43) then windDirection=135 --SE
--elseif (windDirection < 60) then windDirection=203 -- SSW
elseif (windDirection < 85) then windDirection=180 --S
--elseif (windDirection < 98) then windDirection=23 -- NNE
elseif (windDirection < 120) then windDirection=45 --NE
--elseif (windDirection < 170) then windDirection=248 -- WSW
elseif (windDirection < 210) then windDirection=225 -SW
--elseif (windDirection < 275) then windDirection=338 -- NNW
elseif (windDirection < 380) then windDirection=0 --N
--elseif (windDirection < 500) then windDirection=293 -- WNW
elseif (windDirection < 750) then windDirection=315 --NW
elseif (windDirection < 1005) then windDirection=270 --W
else windDirection=-1
end
end
irqPin = 1 --GPIO5
windSpeed = 0
windClicks = 0
lastWindCheck = 0
function debounce (func)
local delay = 100000
return function (...)
now = tmr.now()
now = now - lastWindCheck
if now < delay then return end
lastWindCheck = tmr.now()
return func (...)
end
end
function windSpeedIrq ()
windClicks = windClicks+1 * 10000000
print (windClicks)
end
function calcWindSpeed ()
local deltaTime = tmr.now () - lastWindCheck
windSpeed = windClicks / deltaTime
print(deltaTime)
windSpeed = windSpeed * 1492 /10000 -- Replace " *1492/10000 " with " *24/100 " for Km/h instead of Mp/h
windClicks = 0
lastWindCheck = tmr.now()
end
gpio.mode(irqPin,gpio.INT)
gpio.trig(irqPin,"down",debounce(windSpeedIrq))
file.open("counterMax.lua","r")
counter=(file.read())
file.close()
tmr.alarm(0, 2000, 1, function()
if(wifi.sta.getip()~=nil) then
tmr.stop(0)
print("Client IP Address:",wifi.sta.getip())
// "IP-адрес клиента:"
cl=net.createConnection(net.TCP, 0)
cl:connect(80,"192.168.4.1")
tmr.alarm(1, 5000, 1, function()
counter=counter+1
readds18b20sensor()
readWindDirection()
calcWindSpeed()
print (temp)
print(windSpeed)
-- Next is the properly formated string that Things Gateway needs to show Date,Time,Wind speed,Wind direction and Temp.
cl:send("XLS,write,Example,A"..counter..",%date%\nXLS,write,Example,B"..counter..",%time%\nXLS,write,Example,C"..counter..","..windSpeed.."\nXLS,write,Example,D"..counter..","..windDirection.."\nXLS,write,Example,E"..counter..","..temp)
cl:on("disconnection",function(reconnect)
file.open("counterMax.lua","w+")
file.writeline(counter)
file.close()
end)
end)
else
print("Connecting...") // "Подключение..."
end
end)
function reconnect()
wifi.setmode(wifi.STATION)
wifi.sta.config("test","12345678")
wifi.sta.connect()
end
Схема для клиента
Соберите клиентскую часть согласно картинке ниже (если используете модуль ESP-12, воспользуйтесь этой схемой):
Кнопка справа, подключенная к IO05, используется для симуляции данных о скорости ветра. Впрочем, это скорость ветра не в реальном времени, а средний показатель за последние 5 секунд.
То есть не важно, как часто вы будете нажимать на эту кнопку. Если нажать на нее 5 раз в течение 5 последних секунд, это будет частота 1 раз в секунду, что даст 1,492 миль/ч или 2,4 км/ч. Впрочем, на данный момент в проекте используются целые числа, поэтому в результате получится 1492 м/ч и 24 км/ч. Вам нужно будет разделить эти значения уже в самой в таблице Excel – соответственно, на 100 и 10.
Скрипт для сервера
-- Создал: Руи Сантос (Rui Santos) – Сервер ESP8266
-- Модифицировал: Ив Абур (Yves Arbour); после модификации строка
-- печатается напрямую в таблицу Excel при помощи Things Gateway
print("ESP8266 Server") // "Сервер ESP8266"
wifi.setmode(wifi.STATIONAP);
wifi.ap.config({ssid="test",pwd="12345678"});
print("Server IP Address:",wifi.ap.getip()) // "IP-адрес сервера: "
sv = net.createServer(net.TCP)
sv:listen(80, function(conn)
conn:on("receive", function(conn, receivedData)
--print("Received Data"..receivedData)
// "Полученные данные..."
print(receivedData)-- string "Received Data" removed...
-- Things Gateway игнорирует строки, которые не начинаются
-- правильной команды...
-- В данном случае для таблицы Excel нужна команда XLS
end)
conn:on("sent", function(conn)
collectgarbage()
end)
end)
Схема для сервера
Соберите серверную часть согласно картинке ниже (если используете модуль ESP-12, воспользуйтесь этой схемой):
Я создал для ESP-201 специальную плату. Ее особенности:
- Желтый провод: Его можно подключить либо между 0-ым GPIO-контактом и GND (чтобы загружать прошивку NodeMCU), либо между 0-ым GPIO-контактом и VCC (чтобы сохранять скрипты на ESP)
- 15-ый GPIO-контакт припаян к контакту GND
- К контакту RST подключена кнопка и подтягивающий резистор на 10 кОм (то есть, если нажать на эту кнопку, резистор притянет сигнал к «земле», а затем вернется в исходное положение)
Сборка
Запитайте оба ESP и убедитесь, что между серверным ESP и компьютером по-прежнему установлена последовательная коммуникация, потому что именно через нее сервер будет отправлять данные в таблицу Excel.
Загрузка и установка Things Gateway
В этом проекте мы воспользуемся программой Things Gateway, написанной Роберто Валголио (Roberto Valgolio), чтобы в реальном времени записывать в таблицу Excel данные, которые будут постоянно обновлять сами себя.
Things Gateway – это PC-программа, которая подключается к микроконтроллеру и способна делать следующее:
- Извлекать данные из файлов Excel
- Записывать данные в файлы Excel
- Записывать логи в файлы *.csv
- Отправлять электронные письма (при соблюдении заданных условий)
- Показывать значения и графики (графики независимы от Excel)
Things Gateway также умеет подключаться к GPS и показывать на экране...
- Скорость, направление, высоту и другую навигационную информацию
- Маршрут в реальном времени на Google Maps
Зайдите на сайт Things Gateway, загрузите программу и установите ее. Данный проект тестировался с версией Beta4.
Запуск Things Gateway
Открывается Things Gateway очень просто. Просто пройдите в Этот компьютер > Документы > ThingsGateway и откройте программу.
Затем сделайте следующее:
- Перейдите на вкладку «Config»
- В поле «port» впишите порт сервера
- В поле «speed» впишите 9600
Все нужные пункты выделены на картинке ниже красным цветом:
Демонстрация
Откройте вкладку RealTime и в столбце «From» выберите пункт «Serial», а в столбце «To» – пункт «Excel».
Если все настроено правильно, далее откроется таблица Excel и начнет заполняться данными, которые будут появляться каждые несколько секунд.
Ваши данные будут записываться в таблицу Excel, находящуюся в этой папке:
Дальнейшие улучшения
Этот пример позволяет попробовать и другие функции Things Gateway:
- Графики, обновляющиеся самостоятельно и в реальном времени (независимо от Excel)
- Запись логов в файлы формата *.csv
- Автоматическая отправка электронных писем при соблюдении заданных условий (к примеру, если скорость ветра возрастет на столько-то или температура упадет на столько-то, если в морозильнике недостаточно холодно и т.д.)
- Запись логов в файл «stream.txt» с коэффициентом обновления 0.1, 0.5, 1.5, 10, 60 или 3600
- GPS-отслеживание маршрута на Google Maps с коэффициентом обновления 0.1, 0.5, 1.5, 10, 60 или 3600
Улучшения, которые планируется добавить в будущем:
- Другие датчики вроде датчика атмосферного давления BMP180
- Датчики света
- Датчики влажности
- Любой другой цифровой или аналоговый датчик, использующий мультиплексинг
Также помните, что Things Gateway создавался с прицелом на использование с платой Arduino, но если отправлять через последовательную коммуникацию правильные строки, эту программу можно использовать с любой платой.
См.также
Внешние ссылки
ESP8266 AT-команды | |
---|---|
Список AT-команд | |
Базовые команды |
|
Команды для WiFi |
|
Команды для TCP/IP |
|