ESP32 представляет собой относительно недорогой микроконтроллер с низким энергопотреблением с интегрированным в него Wi-Fi и двухрежимным Bluetooth. Он поставляется с микропроцессором Tensilica Xtensa LX6 в вариантах с двумя ядрами и одним ядром, содержит встроенную антенну, радиочастотный (RF) симметрирующий трансформатор, усилитель мощности, малошумящий усилитель в тракте приема, фильтры и модули управления мощностью.
Ранее на нашем сайте мы рассматривали подключение датчика DHT11 (создание метеостанции) к платам Raspberry Pi и Arduino, а также к модулю ESP8266. В этой же статье мы рассмотрим создание веб-сервера на основе модуля ESP32 для отображения значений температуры и влажности, считываемых с датчика DHT11. Модуль ESP32 будет считывать значения температуры и влажности с данного датчика и отображать их на веб-странице. Также в нашем проекте мы будем использовать сервис IFTTT для отправки уведомлений по Email в случаях, когда температура будет превышать установленное значение.
Необходимые компоненты
- Модуль ESP32 (купить на AliExpress).
- Датчик температуры и влажности DHT11 (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Схема проекта
Схема подключения датчика DHT11 к модулю ESP32 представлена на следующем рисунке.
Датчик DHT11 имеет всего 3 контакта, поэтому подключить его к модулю ESP32 достаточно просто. Подключите контакты VCC и GND датчика к контактам 3.3V и GND модуля ESP32. Контакт данных (Data pin) датчика подключите к контакту D2 модуля ESP32.
Внешний вид собранной конструкции проекта показан на следующем рисунке.
Настройка сервиса IFTTT
IFTTT представляет собой бесплатный онлайн-сервис, который позволяет пользователям создавать цепочки простых действий с условиями, называемые "рецептами", которые могут формировать определенные события в таких сервисах как Gmail, Facebook, Instagram и Pinterest. Расшифровывается название сервиса IFTTT как “If This Then That” (если произошло ЭТО, то сделать ТО).
В нашем проекте сервис IFTTT будет использоваться для передачи Email когда значения температуры или влажности превысят определенные нами границы. На нашем сайте вы можете посмотреть все проекты, в которых использовался сервис IFTTT.
Вначале войдите в свой аккаунт на сервисе IFTTT. Создайте себе аккаунт на данном сервисе если у вас его еще нет.
Затем в сервисе IFTTT выполните поиск ‘Webhooks’, после чего нажмите на Webhooks в секции Services.
Затем в окне Webhooks (веб-хуков) нажмите на ‘Documentation’ в правом верхнем углу чтобы получить приватный ключ (private key). Скопируйте этот ключ, в дальнейшем он потребуется нам в программе.
После получения приватного ключа создадим апплет (applet) используя сервисы Webhooks и Email. Для создание апплета нажмите на свой профиль, а затем нажмите на ‘Create’ (создать).
Затем в следующем окне нажмите на иконку ‘This’.
Далее выполните поиск Webhooks в строке поиска, затем в результатах поиска нажмите на ‘Webhooks.’
В следующем окне выберите триггер ‘Receive a Web Request’ и в следующем окне введите в качестве имени события temp_event, затем нажмите на create a trigger (создать триггер).
После этого нажмите на ‘Then That’ и затем нажмите на Email.
Далее в следующем окне нажмите на ‘send me an email’ (послать мне email), введите тему и содержание письма, после чего нажмите на create action (создать действие).
И на завершающем шаге нажмите ‘Finish’ чтобы закончить создание апплета.
Объяснение программы для модуля ESP32
В данном проекте мы будем программировать модуль ESP32 с помощью Arduino IDE.
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Первым делом в программе подключим используемые библиотеки. Нам понадобятся библиотеки WiFi, DHT (для работы с датчиком DHT) и Wire (для использования протокола I2C).
1 2 3 |
#include <WiFi.h> #include <Wire.h> #include "DHT.h |
Далее укажем тип датчика DHT и контакт, к которому он подключен. Создадим объект для работы с данным датчиком.
1 2 3 |
#define DHTTYPE DHT11 // DHT 11 uint8_t DHTPin = D2; DHT dht(DHTPin, DHTTYPE); |
Затем укажем имя Wi-Fi сети, к которой мы будем подключаться, и пароль для доступа к ней. Также укажем имя хоста сервиса IFTTT и приватный ключ (private key) с данного сервиса.
1 2 3 4 |
const char* ssid = "Wi-Fi Name"; const char* password = "Password"; const char *host = "maker.ifttt.com"; const char *privateKey = "Private key"; |
Далее создадим объект библиотеки WifiServer. Мы будем использовать порт 80 по умолчанию для доступа по HTTP.
1 |
WiFiServer server(80); |
Внутри функции Void setup() мы инициализируем последовательную связь со скоростью 115200 бод, инициализируем датчик DHT с помощью функции dht.begin() и затем подключимся к сети Wi-Fi, используя имя пользователя и пароль. Как только модуль ESP32 подключится к сети Wi-Fi, в окно монитора последовательного порта будет выведен IP адрес модуля.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Serial.begin(115200); pinMode(DHTPin, INPUT); dht.begin(); Serial.print("Connecting to Wifi Network"); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("Connected to WiFi."); Serial.println("IP address of ESP32 is : "); ……………………………….. …………………………………. |
В функции void loop() мы будем считывать значения температуры и влажности и сохранять их в двух различных переменных.
1 2 |
Temperature = dht.readTemperature(); Humidity = dht.readHumidity(); |
После этого начнем программирование дизайна нашей веб-страницы и выведем скрипт с помощью функции client.println().
1 2 3 4 5 6 7 8 9 10 |
WiFiClient client = server.available(); if (client) { Serial.println("Web Client connected "); String request = client.readStringUntil('\r'); client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println("Refresh: 10"); // update the page after 10 sec client.println(); |
Для оформления стиля текста и фона мы будем использовать CSS – вы можете их изменить по своему желанию.
1 2 3 4 5 6 7 |
client.println("<style>html { font-family: Cairo; display: block; margin: 0px auto; text-align: center;color: #333333; background-color: ##f3ffee;}"); client.println("body{margin-top: 50px;}"); client.println("h1 {margin: 50px auto 30px; font-size: 50px; text-align: center;}"); client.println(".side_adjust{display: inline-block;vertical-align: middle;position: relative;}"); client.println(".text1{font-weight: 180; padding-left: 15px; font-size: 50px; width: 170px; text-align: left; color: #3498db;}"); …………. …………. |
В HTML коде мы будем использовать тэги <div> для отображения наших обоих параметров – температуры и влажности.
1 2 3 4 5 6 7 8 9 10 11 12 |
client.println("<div class=\"side_adjust text1\">Humidity:</div>"); client.println("<div class=\"side_adjust data1\">"); client.print(Humidity); client.println("<div class=\"side_adjust text1\">%</div>"); client.println("</div>"); client.println("<div class=\"data\">"); client.println("<div class=\"side_adjust text2\">Temperature:</div>"); client.println("<div class=\"side_adjust data2\">"); client.print(Temperature); client.println("<div class=\"side_adjust text2\">*C</div>"); ……….. ……….. |
Далее с помощью условного оператора if мы будем проверять превысила ли температура значение 20 градусов или нет. Если превысила, то мы будем передавать триггер на сервис IFTTT.
1 2 3 |
if ( Temperature >= 20) { send_event("temp_event"); } |
Тестирование работы проекта
Подключите модуль ESP32 к вашему компьютеру/ноутбуку, выберите в Arduino IDE корректную плату и порт, к которому подключен модуль, после чего нажмите кнопку Upload для загрузки программы в модуль.
Убедитесь в том, что ваш компьютер/ноутбук и модуль ESP32 подключены к одной и той же сети Wi-Fi. После загрузки программы в модуль откройте окно монитора последовательной связи и установите в нем скорость 115200. После этого ваше окно монитора последовательной связи должно выглядеть примерно следующим образом:
А формируемая нашим веб-сервером веб-страница будет иметь следующий вид:
Теперь, всегда когда температура будет превышать значение 20 градусов, будет срабатывать событие IFTTT чтобы передать вам email о том, что температура достигла критического значения.
Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Исходный код программы (скетча)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
#include <WiFi.h> #include <Wire.h> #include "DHT.h" // Uncomment one of the lines below for whatever DHT sensor type you're using! #define DHTTYPE DHT11 // DHT 11 //DHT Sensor; uint8_t DHTPin = D2; DHT dht(DHTPin, DHTTYPE); float Temperature; float Humidity; void send_event(const char *event); const char* ssid = "Wi-Fi Name"; const char* password = "Password"; const char *host = "maker.ifttt.com"; const char *privateKey = "Private Key"; // введите здесь ваш приватный ключ (private key), который вы получили в сервисе IFTTT WiFiServer server(80); String header; void setup() { Serial.begin(115200); pinMode(DHTPin, INPUT); dht.begin(); Serial.print("Connecting to Wifi Network"); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("Successfully connected to WiFi."); Serial.println("IP address of ESP32 is : "); Serial.println(WiFi.localIP()); server.begin(); Serial.println("Server started"); } void loop() { Temperature = dht.readTemperature(); Humidity = dht.readHumidity(); WiFiClient client = server.available(); if (client) { Serial.println("Web Client connected "); String request = client.readStringUntil('\r'); client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // соединение будет закрыто после получения ответа client.println("Refresh: 10"); // будем обновлять страницу каждые 10 секунд client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<style>html { font-family: Cairo; display: block; margin: 0px auto; text-align: center;color: #333333; background-color: ##f3ffee;}"); client.println("body{margin-top: 50px;}"); client.println("h1 {margin: 50px auto 30px; font-size: 50px; text-align: center;}"); client.println(".side_adjust{display: inline-block;vertical-align: middle;position: relative;}"); client.println(".text1{font-weight: 180; padding-left: 15px; font-size: 50px; width: 170px; text-align: left; color: #3498db;}"); client.println(".data1{font-weight: 180; padding-left: 70px; font-size: 50px;color: #3498db;}"); client.println(".text2{font-weight: 180;padding-left: 15px; font-size: 50px; width: 170px; text-align: left; color: #ff6600;}"); client.println(".data2{font-weight: 180; padding-left: 120px; font-size: 50px;color: #ff6600;}"); client.println(".data{padding: 10px;}"); client.println("</style>"); client.println("</head>"); client.println("<body>"); client.println("<div id=\"webpage\">"); client.println("<h1>ESP32 Interfacing with DHT11</h1>"); client.println("<div class=\"data\">"); client.println("<div class=\"side_adjust text1\">Humidity:</div>"); client.println("<div class=\"side_adjust data1\">"); client.print(Humidity); client.println("<div class=\"side_adjust text1\">%</div>"); client.println("</div>"); client.println("<div class=\"data\">"); client.println("<div class=\"side_adjust text2\">Temperature:</div>"); client.println("<div class=\"side_adjust data2\">"); client.print(Temperature); client.println("<div class=\"side_adjust text2\">*C</div>"); client.println("</div>"); client.println("</div>"); client.println("</body>"); client.println("</html>"); delay(4000); if ( Temperature >= 20) { send_event("temp_event"); } } } void send_event(const char *event) { Serial.print("Connecting to "); Serial.println(host); // Use WiFiClient class to create TCP connections WiFiClient client; const int httpPort = 80; if (!client.connect(host, httpPort)) { Serial.println("Connection failed"); return; } // формируем URI для запроса String url = "/trigger/"; url += event; url += "/with/key/"; url += privateKey; Serial.print("Requesting URL: "); Serial.println(url); // передаем запрос на сервер client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); while(client.connected()) { if(client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); } else { // No data yet, wait a bit delay(50); }; } Serial.println(); Serial.println("closing connection"); client.stop(); } |