ESP8266:Примеры/Отображение температуры и влажности на веб-странице при помощи прошивки NodeMCU: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
 
(не показаны 3 промежуточные версии 2 участников)
Строка 2: Строка 2:
{{Перевод от Сubewriter}}
{{Перевод от Сubewriter}}
{{Myagkij-редактор}}
{{Myagkij-редактор}}
{{Черновик}}


=Отображение температуры и влажности на веб-странице при помощи прошивки NodeMCU=
=Отображение температуры и влажности на веб-странице при помощи прошивки NodeMCU=
Строка 33: Строка 31:
* '''Глобальные переменные.''' Все переменные по умолчанию считаются глобальными (если в коде специально не задано, что они локальные).
* '''Глобальные переменные.''' Все переменные по умолчанию считаются глобальными (если в коде специально не задано, что они локальные).


::<syntaxhighlight lang="lua" enclose="div">
::<syntaxhighlight lang="lua">
pin = 3
pin = 3
test = "It works!"
test = "It works!"
Строка 40: Строка 38:
* '''Локальные переменные.''' Если переменная задана локальной, область ее видимости будет ограничена лишь ее функцией.
* '''Локальные переменные.''' Если переменная задана локальной, область ее видимости будет ограничена лишь ее функцией.


::<syntaxhighlight lang="lua" enclose="div">
::<syntaxhighlight lang="lua">
local pin = 3
local pin = 3
local test = "It works!"
local test = "It works!"
Строка 55: Строка 53:
В таблице ниже показаны типы данных для значений в языке [[Lua]].
В таблице ниже показаны типы данных для значений в языке [[Lua]].


{| class="wikitable" style="margin:0 auto;"
{| class="wikitable" style="margin:0 auto" style="margin:0 auto;"
|-
|-
! Тип значения !! Описание
! Тип значения !! Описание
Строка 74: Строка 72:
Вот примеры некоторых из этих типов значений:
Вот примеры некоторых из этих типов значений:


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
print(type("Hello world!")) –- строка
print(type("Hello world!")) –- строка
print(type(7))              -- число
print(type(7))              -- число
Строка 90: Строка 88:
* Однострочные комментарии:  
* Однострочные комментарии:  


::<syntaxhighlight lang="lua" enclose="div">
::<syntaxhighlight lang="lua">
print("Hello World!") –- комментарий в одну строчку
print("Hello World!") –- комментарий в одну строчку
</syntaxhighlight>
</syntaxhighlight>
Строка 96: Строка 94:
* Многострочные комментарии:
* Многострочные комментарии:


::<syntaxhighlight lang="lua" enclose="div">
::<syntaxhighlight lang="lua">
--[[
--[[
print("Hello World!") – это многострочный комментарий
print("Hello World!") – это многострочный комментарий
Строка 112: Строка 110:
Читая таблицы и примеры ниже, представьте, что имеете дело с двумя переменными: '''«А»''', в которой хранится значение '''«1»''', и '''«B»''', в которой хранится значение '''«2»'''.
Читая таблицы и примеры ниже, представьте, что имеете дело с двумя переменными: '''«А»''', в которой хранится значение '''«1»''', и '''«B»''', в которой хранится значение '''«2»'''.


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
A = 1
A = 1
B = 2
B = 2
Строка 119: Строка 117:
===== Арифметические операторы =====
===== Арифметические операторы =====


{| class="wikitable" style="margin:0 auto;"
{| class="wikitable" style="margin:0 auto" style="margin:0 auto;"
|-
|-
! Оператор !! Пример !! Результат
! Оператор !! Пример !! Результат
Строка 140: Строка 138:
===== Операторы сравнения =====
===== Операторы сравнения =====


{| class="wikitable" style="margin:0 auto;"
{| class="wikitable" style="margin:0 auto" style="margin:0 auto;"
|-
|-
! Оператор !! Пример !! Результат
! Оператор !! Пример !! Результат
Строка 159: Строка 157:
===== Логические операторы =====
===== Логические операторы =====


{| class="wikitable" style="margin:0 auto;"
{| class="wikitable" style="margin:0 auto" style="margin:0 auto;"
|-
|-
! Оператор !! Пример !! Результат
! Оператор !! Пример !! Результат
Строка 174: Строка 172:
Теперь представьте, что у нас две новые переменные:
Теперь представьте, что у нас две новые переменные:


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
a = "Hello!"
a = "Hello!"
b = "World!"
b = "World!"
</syntaxhighlight>
</syntaxhighlight>


{| class="wikitable" style="margin:0 auto;"
{| class="wikitable" style="margin:0 auto" style="margin:0 auto;"
|-
|-
! Оператор !! Пример !! Результат
! Оператор !! Пример !! Результат
Строка 190: Строка 188:
Цикл позволяет выполнить блок кода несколько раз, пока выполняется заданное условие. Во фрагменте кода ниже – пока значением в переменной '''«boolean_value»''' является '''«true»'''.
Цикл позволяет выполнить блок кода несколько раз, пока выполняется заданное условие. Во фрагменте кода ниже – пока значением в переменной '''«boolean_value»''' является '''«true»'''.


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
-- цикл while
-- цикл while
while boolean_value
while boolean_value
Строка 208: Строка 206:
Операторы '''if... else''' (т.е. «если... иначе») – один из самых важных инструментов для управления программой. Они используются следующим образом:
Операторы '''if... else''' (т.е. «если... иначе») – один из самых важных инструментов для управления программой. Они используются следующим образом:


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
if boolean_value then
if boolean_value then
     -- если в переменной «boolean_value» значение «true»
     -- если в переменной «boolean_value» значение «true»
Строка 224: Строка 222:
Ниже показано, как создать новую функцию, принимающую один параметр (температуру в градусах Кельвина) и преобразующую это значение в градусы Цельсия и Фаренгейта.
Ниже показано, как создать новую функцию, принимающую один параметр (температуру в градусах Кельвина) и преобразующую это значение в градусы Цельсия и Фаренгейта.


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
function displayTemperature(kelvin)
function displayTemperature(kelvin)
   celsius = kelvin – 273.15
   celsius = kelvin – 273.15
Строка 242: Строка 240:
В таблице ниже показано, как номер контакта [[ESP8266]] в [[Lua-код]]е соотносится с его GPIO-номером. У платы [[ESP-01]] только два контакта: GPIO0 и GPIO2.
В таблице ниже показано, как номер контакта [[ESP8266]] в [[Lua-код]]е соотносится с его GPIO-номером. У платы [[ESP-01]] только два контакта: GPIO0 и GPIO2.


{| class="wikitable" style="margin:0 auto;"
{| class="wikitable" style="margin:0 auto" style="margin:0 auto;"
|-
|-
! Номер контакта в Lua-коде !! GPIO-номер контакта
! Номер контакта в Lua-коде !! GPIO-номер контакта
Строка 305: Строка 303:
}}
}}


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
-- Rui Santos
-- Rui Santos
-- Complete project details at http://randomnerdtutorials.com
-- Complete project details at http://randomnerdtutorials.com
Строка 375: Строка 373:
В следующей строчке функция '''print()''' печатает [[IP-адрес]] [[ESP8266]] в окне '''Output''' в [[IDE ESPlorer]] (этот [[IP-адрес]] понадобится вам, чтобы подключиться к [[веб-сервер]]у).
В следующей строчке функция '''print()''' печатает [[IP-адрес]] [[ESP8266]] в окне '''Output''' в [[IDE ESPlorer]] (этот [[IP-адрес]] понадобится вам, чтобы подключиться к [[веб-сервер]]у).


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
wifi.setmode(wifi.STATION)
wifi.setmode(wifi.STATION)
wifi.sta.config("YOUR_NETWORK_NAME","YOUR_NETWORK_PASSWORD")
wifi.sta.config("YOUR_NETWORK_NAME","YOUR_NETWORK_PASSWORD")
Строка 384: Строка 382:
Затем задаем контакт, к которому подключен [[DHT11]]. В данном случае это '''«pin = 1»''', что означает контакт GPIO5. Также создаем еще 3 переменные для хранения данных.
Затем задаем контакт, к которому подключен [[DHT11]]. В данном случае это '''«pin = 1»''', что означает контакт GPIO5. Также создаем еще 3 переменные для хранения данных.


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
pin = 1
pin = 1
bimb = 1
bimb = 1
Строка 393: Строка 391:
Затем создаем функцию с говорящим названием '''ReadDHT11()'''. Она считывает с датчика [[DHT11]] данные о температуре и влажности, а затем сохраняет их в правильные переменные. Она также печатает эти данные в окно '''Output''' в [[IDE ESPlorer]].
Затем создаем функцию с говорящим названием '''ReadDHT11()'''. Она считывает с датчика [[DHT11]] данные о температуре и влажности, а затем сохраняет их в правильные переменные. Она также печатает эти данные в окно '''Output''' в [[IDE ESPlorer]].


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
function ReadDHT11()
function ReadDHT11()
     status, temp, humi, temp_dec, humi_dec = dht.read(pin)
     status, temp, humi, temp_dec, humi_dec = dht.read(pin)
Строка 417: Строка 415:
Далее мы создаем объект [[веб-сервер]]а на порте 80 и вызываем функцию '''conn:send()'''.  
Далее мы создаем объект [[веб-сервер]]а на порте 80 и вызываем функцию '''conn:send()'''.  


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
tmr.alarm(1,5000, 1, function() ReadDHT11() bimb=bimb+1 if bimb==5 then bimb=0 wifi.sta.connect() print("Reconnect")end end)
tmr.alarm(1,5000, 1, function() ReadDHT11() bimb=bimb+1 if bimb==5 then bimb=0 wifi.sta.connect() print("Reconnect")end end)


Строка 432: Строка 430:
Внутри функции '''conn:send()''' мы пишем данные [[HTML]]-страницы (см. код ниже). Это простая веб-страница, использующая фреймворк [[Bootstrap]]. Более подробно о [[Bootstrap]] можно почитать [http://getbootstrap.com/ тут].
Внутри функции '''conn:send()''' мы пишем данные [[HTML]]-страницы (см. код ниже). Это простая веб-страница, использующая фреймворк [[Bootstrap]]. Более подробно о [[Bootstrap]] можно почитать [http://getbootstrap.com/ тут].


<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="lua" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
conn:send('HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
conn:send('HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
         <!DOCTYPE HTML>\
         <!DOCTYPE HTML>\
Строка 484: Строка 482:
Загрузив скрипт на [[ESP8266]], соберите цепь, показанную ниже. Для подключения [[DHT11]] вам также понадобится резистор номиналом [[4,7 кОм]] или выше, который будет служить подтягивающим [[резистор]]ом.
Загрузив скрипт на [[ESP8266]], соберите цепь, показанную ниже. Для подключения [[DHT11]] вам также понадобится резистор номиналом [[4,7 кОм]] или выше, который будет служить подтягивающим [[резистор]]ом.


'''Внимание:''' Чтобы цепь работала, вам понадобится 3.3-вольтовый источник питания с 250 мА.
{{Блок/Инфо4
|1=Внимание
|2=Чтобы цепь работала, вам понадобится 3.3-вольтовый источник питания с 250 мА.
}}


[[Файл:ESP8266 schematics bb ESP8266 DHT11DHT22 6.jpg|center]]
[[Файл:ESP8266 schematics bb ESP8266 DHT11DHT22 6.jpg|center]]
Строка 516: Строка 517:


=См.также=
=См.также=
{{ads}}


=Внешние ссылки=
=Внешние ссылки=
Строка 523: Строка 522:
<references />
<references />


{{Навигационная таблица/ESP8266}}
{{Навигационная таблица/Портал/ESP8266}}
{{Навигационная таблица/ESP8266 AT-команды}}
{{Навигационная таблица/Телепорт}}


[[Категория:ESP8266]]
[[Категория:ESP8266]]

Текущая версия от 12:59, 18 июня 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Отображение температуры и влажности на веб-странице при помощи прошивки NodeMCU

В этом руководстве мы создадим при помощи ESP8266 веб-сервер, доступ к которому можно будет получить с любого устройства с браузером. Этот веб-сервер будет обслуживать страницу, показывающую текущие температуру и влажность. Для считывания этих показателей мы воспользуемся датчиком DHT11.

Необходимое оборудование

  • Плата ESP8266 - 1шт.
  • Датчик температуры и влажности DHT11 - 1шт.
  • Резистор на 4,7 кОм - 1шт.
  • Макетная плата - 1шт.
  • Провода перемычки.

Справочная информация

Основы программирования на Lua

Это скриптовый язык программирования, написанный на C. Разработка этого проекта началась в 1993 году силами Роберту Иерузалимски, Луиша Энрике де Фигейреду и Валдемара Келе, работавшими тогда в подразделении Tecgraf при Католическом университете Рио-де-Жанейро.

Более подробно об этом языке программирования можно почитать в «Википедии».

Прошивка NodeMCU для ESP8266 основана на Lua, поэтому если вы хотите писать собственные скрипты для ESP8266, вам важно знать основы этого языка.

Переменные

Переменные в языке Lua не делятся по типу данных, но делятся по области видимости. Это значит, что переменные в Lua могут быть глобальными или локальными.

  • Глобальные переменные. Все переменные по умолчанию считаются глобальными (если в коде специально не задано, что они локальные).
pin = 3
test = "It works!"
  • Локальные переменные. Если переменная задана локальной, область ее видимости будет ограничена лишь ее функцией.
local pin = 3
local test = "It works!"
  • Поля таблиц. Это особый тип переменных, в которых может храниться все, за исключением «nil» (мы это затрагивать не будем).
Примечание

Lua – это язык, чувствительный к регистру. Поэтому переменная «PIN» – это не то же самое, что «Pin» или «pin».

Типы данных (типы значений)

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))            -- неопределенное значение
Примечание

Работая с ESP8266 и прошивкой NodeMCU, вы изредка будете встречать тип данных «nil». Это будет значить лишь, что такая переменная не определена. Также, если вы хотите удалить какое-то значение в какой-то переменной, просто присвойте ей значение «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) - эта строчка вызывает функцию, созданную выше

Как обращаться к контактам

В таблице ниже показано, как номер контакта ESP8266 в Lua-коде соотносится с его GPIO-номером. У платы ESP-01 только два контакта: GPIO0 и GPIO2.

Номер контакта в Lua-коде GPIO-номер контакта
0 [*] GPIO16
1 GPIO5
2 GPIO4
3 GPIO0
4 GPIO2
5 GPIO14
6 GPIO12
7 GPIO13
8 GPIO15
9 GPIO3
10 GPIO1
11 GPIO9
12 GPIO10

Использование датчика температуры и влажности DHT11

Датчики DHT – это относительно недорогие датчики для измерения температуры и влажности.

Внутри этого датчика есть чип, который выполняет аналогово-цифровое преобразование данных, выдавая в итоге цифровые данные о температуре и влажности.

Эти сигналы очень легко считываются любым микроконтроллером (MCU).

Характеристики DHT11

  • Абсолютная погрешность: ±5%
  • Воспроизводимость результатов: ±1%
  • Долговременность стабильность измерений: ±1% в год
  • Цена: между 1 и 5 долларами

Контакты

  • VCC (3.3 вольта)
  • Вывод данных
  • Не подключен
  • GND

Код для загрузки

Внимание!

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

-- Rui Santos
-- Complete project details at http://randomnerdtutorials.com

wifi.setmode(wifi.STATION)
wifi.sta.config("YOUR_NETWORK_NAME","YOUR_NETWORK_PASSWORD")
tmr.delay(5000)
print(wifi.sta.getip())

pin = 1
bimb = 1
fare = 0
fare_dec = 0

--Read DHT Sensor
function ReadDHT11()
    status, temp, humi, temp_dec, humi_dec = dht.read(pin)
    if status == dht.OK then
        print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
              math.floor(temp),
              temp_dec,
              math.floor(humi),
              humi_dec
        ))
        fare = (9 * math.floor(temp) / 5) + 32
        fare_dec = (9 * temp / 5) % 10
    elseif status == dht.ERROR_CHECKSUM then
        print( "DHT Checksum error." )
    elseif status == dht.ERROR_TIMEOUT then
        print( "DHT timed out." )
    end
end
ReadDHT11()

tmr.alarm(1,5000, 1, function() ReadDHT11() bimb=bimb+1 if bimb==5 then bimb=0 wifi.sta.connect() print("Reconnect")end end)

srv=net.createServer(net.TCP) srv:listen(80,function(conn)
    conn:on("receive",function(conn,payload)
   --print(payload) -- for debugging only
    --generates HTML web site
    conn:send('HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
        <!DOCTYPE HTML>\
        <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head>\
        <meta http-equiv="X-UA-Compatible" content="IE=edge">\
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">\
        <meta http-equiv="refresh" content="6">\
        </head><div class="container">\
        <h1>Sensor Data</h1></br><div class="row">\
        <div class="col-md-4"><div class="panel panel-primary"><div class="panel-heading"><h3 class="panel-title">Humidity</h3>\
        </div><div class="panel-body">\
        <div class="form-group form-group-lg"><input type="text" class="form-control" value="'..math.floor(humi)..'.'..humi_dec..' %">\
        </div></div></div></div>\
        <div class="col-md-4"><div class="panel panel-info"><div class="panel-heading"><h3 class="panel-title">Temperature</h3>\
        </div><div class="panel-body">\
        <div class="form-group form-group-lg"><input type="text" class="form-control" value="'..math.floor(temp)..'.'..temp_dec..' deg C">\
        <input type="text" class="form-control" value="'..fare..'.'..fare_dec..' deg F">\
        </div></div></div></div></div></div></html>')
    conn:on("sent",function(conn) conn:close() end)
    end)
end)

Как работает этот скрипт

Код начинается с переключения ESP8266 в режим станции. Затем мы задаем SSID и пароль WiFi-сети, к которой подключаемся. Соответственно, вам нужно будет заменить параметры "YOUR_NETWORK_NAME" и "YOUR_NETWORK_PASSWORD" на собственные, чтобы ESP8266 могла подключиться к вашей WiFi-сети.

Затем при помощи функции tmr.delay(5000) задается 5-секундная пауза. Это дает ESP8266 время для подключения к сети.

В следующей строчке функция print() печатает IP-адрес ESP8266 в окне Output в IDE ESPlorer (этот IP-адрес понадобится вам, чтобы подключиться к веб-серверу).

wifi.setmode(wifi.STATION)
wifi.sta.config("YOUR_NETWORK_NAME","YOUR_NETWORK_PASSWORD")
tmr.delay(5000)
print(wifi.sta.getip())

Затем задаем контакт, к которому подключен DHT11. В данном случае это «pin = 1», что означает контакт GPIO5. Также создаем еще 3 переменные для хранения данных.

pin = 1
bimb = 1
fare = 0
fare_dec = 0

Затем создаем функцию с говорящим названием ReadDHT11(). Она считывает с датчика DHT11 данные о температуре и влажности, а затем сохраняет их в правильные переменные. Она также печатает эти данные в окно Output в IDE ESPlorer.

function ReadDHT11()
    status, temp, humi, temp_dec, humi_dec = dht.read(pin)
    if status == dht.OK then
        print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
              math.floor(temp),
              temp_dec,
              math.floor(humi),
              humi_dec
        ))
        fare = (9 * math.floor(temp) / 5) + 32
        fare_dec = (9 * temp / 5) % 10
    elseif status == dht.ERROR_CHECKSUM then
        print( "DHT Checksum error." ) -- "Ошибка контрольной суммы"
    elseif status == dht.ERROR_TIMEOUT then
        print( "DHT timed out." ) -- "Таймаут"
    end
end
ReadDHT11()

Нам также нужно создать функцию tmr.alarm(), которая будет запускать функцию ReadDHT11() каждые 5 секунд. При каждом вызове она считывает текущие данные о температуре и влажности. Далее мы создаем объект веб-сервера на порте 80 и вызываем функцию conn:send().

tmr.alarm(1,5000, 1, function() ReadDHT11() bimb=bimb+1 if bimb==5 then bimb=0 wifi.sta.connect() print("Reconnect")end end)

srv=net.createServer(net.TCP) srv:listen(80,function(conn)
    conn:on("receive",function(conn,payload)
   --print(payload) – только для отладки
    -- генерирует HTML-страницу
    conn:send()
    conn:on("sent",function(conn) conn:close() end)
    end)
end)

Внутри функции conn:send() мы пишем данные HTML-страницы (см. код ниже). Это простая веб-страница, использующая фреймворк Bootstrap. Более подробно о Bootstrap можно почитать тут.

conn:send('HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nCache-Control: private, no-store\r\n\r\n\
        <!DOCTYPE HTML>\
        <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head>\
        <meta http-equiv="X-UA-Compatible" content="IE=edge">\
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">\
        <meta http-equiv="refresh" content="6">\
        </head><div class="container">\
        <h1>Sensor Data</h1></br><div class="row">\
        <div class="col-md-4"><div class="panel panel-primary"><div class="panel-heading"><h3 class="panel-title">Humidity</h3>\
        </div><div class="panel-body">\
        <div class="form-group form-group-lg"><input type="text" class="form-control" value="'..math.floor(humi)..'.'..humi_dec..' %">\
        </div></div></div></div>\
        <div class="col-md-4"><div class="panel panel-info"><div class="panel-heading"><h3 class="panel-title">Temperature</h3>\
        </div><div class="panel-body">\
        <div class="form-group form-group-lg"><input type="text" class="form-control" value="'..math.floor(temp)..'.'..temp_dec..' deg C">\
        <input type="text" class="form-control" value="'..fare..'.'..fare_dec..' deg F">\
        </div></div></div></div></div></div></html>')

Этот код создает симпатичную страницу, показывающую данные о температуре и влажности, а также способную адаптироваться под экраны мобильных устройств.

Загружаем скрипт «init.lua»

Чтобы загрузить этот Lua-скрипт на ESP8266, проделайте следующее:

  1. Подключите ESP8266 (напрямую или через FTDI-программатор) к ПК
  2. Выберите COM-порт, к которому подключен ESP8266
  3. Нажмите на кнопку «Open/Close»
  4. Выберите вкладку «NodeMCU+MicroPython»
  5. Создайте новый файл под названием «init.lua»
  6. Нажмите на кнопку «Save to ESP»

Кроме того, в окне Output будут напечатаны команды, отсылаемые ESP8266.

Примечание

Вы можете без труда удалить файл «init.lua» из ESP8266. Для этого просто впишите file.remove(“init.lua”) и нажмите на кнопку «Send» (см. скриншот выше). Если вам нужно удалить все файлы, хранящиеся на ESP8266, воспользуйтесь командой file.format().

Узнаем IP-адрес ESP8266

После того, как вы загрузите на ESP8266 веб-серверный Lua-скрипт, в окне Output в IDE ESPlorer должно появиться три IP-адреса.

Нам нужен самый первый IP-адрес. В моем случае это «192.168.1.70», но у вас, скорее всего, будет какой-то другой IP-адрес. Сохраните его где-нибудь, потому что чуть позднее он нам понадобится.

Примечание

Если IP-адрес не появился в окне Output, то его можно узнать, отправив ESP8266 команду print(wifi.sta.getip()).

Собираем цепь

Загрузив скрипт на ESP8266, соберите цепь, показанную ниже. Для подключения DHT11 вам также понадобится резистор номиналом 4,7 кОм или выше, который будет служить подтягивающим резистором.

Внимание

Чтобы цепь работала, вам понадобится 3.3-вольтовый источник питания с 250 мА.

Подключаемся к веб-серверу

Чтобы подключиться к веб-серверу, проделайте следующее:

  1. Перезапустите ESP8266
  2. Откройте браузер
  3. Впишите в адресную строку браузера IP-адрес, сохраненный ранее (в моем случае это «192.168.1.70»)

В результате должна загрузиться примерно такая веб-страница:

Клево, а? Смело пробуйте модифицировать этот Lua-скрипт и добавлять в него свои идеи. И помните, что эта веб-страница будет автоматически обновляться каждые 6 секунд.

Кроме того, эта HTML-страница способна адаптироваться под любые экраны, так что она будет хорошо выглядеть в том числе и на экране мобильного устройства.

Что дальше

Плата ESP-12E оснащена лишь одним аналоговым контактом, что очень неудобно, если вы хотите подключить к своему проекту больше одного аналогового датчика/модуля...

Как можно обойти эту проблему? Есть один вариант.

Можно настроить последовательную коммуникацию между Arduino и ESP8266 и подключить к Arduino нужные датчики.

Arduino будет делать всю черную работу, считывая данные с датчиков, а затем отправляя их по последовательному порту ESP8266. Сам ESP8266, тем временем, будет получать эти данные и показывать их на веб-странице!

Впрочем, вам нужно будет немного адаптировать некоторые фрагменты этого руководства, чтобы Arduino могла считывать данные с датчиков.

См.также

Внешние ссылки