Облачная метеостанция на ESP32/ESP8266 (база данных MySQL и PHP)
Создайте панель мониторинга облачной метеостанции для визуализации показаний датчиков вашего ESP32 или ESP8266 из любой точки мира. Вы будете визуализировать данные датчиков, отображаемые на шкалах и в таблице. ESP32 или ESP8266 будет выполнять HTTP POST запрос к PHP-скрипту для вставки данных в базу данных MySQL.
Ранее мы сохраняли показания датчиков в базе данных и отображали их в таблице или на графиках, к которым можно получить доступ из любого места, используя собственный сервер. Теперь я решил сделать несколько шагов вперед и добавить больше информации на веб-страницу.
Я добавил две шкалы для отображения последних показаний температуры и влажности, а также некоторую статистику о минимальных, максимальных и средних значениях из определенного количества показаний, которое вы можете задать. Вы также можете просмотреть все последние показания в таблице и выбрать, сколько показаний хотите отобразить.
Для создания этого проекта вам понадобятся следующие технологии:
ESP32 или ESP8266, программируемый с помощью Arduino IDE
Хостинг-сервер и доменное имя
PHP-скрипт для вставки данных в MySQL и их отображения на веб-странице
База данных MySQL для хранения показаний
Оглавление
Этот проект разделен на следующие основные разделы:
`PHP-скрипт HTTP POST -- прием и вставка данных в базу данных MySQL`_
`PHP-скрипт -- отображение показаний базы данных на шкалах и в таблице`_
Смотрите видеоурок
0. Скачать исходный код
Для этого проекта вам понадобятся следующие файлы:
SQL-запрос для создания таблицы: SensorData_Table.sql
Вставка и доступ к данным базы данных: esp-database.php
Обработка HTTP POST запросов: esp-post-data.php
CSS-файл для стилизации вашей веб-страницы: esp-style.css
Отображение показаний датчиков: esp-weather-station.php
Скетч Arduino для ESP32: HTTPS_ESP32_Cloud_Weather_Station.ino
Скетч Arduino для ESP8266: HTTPS_ESP8266_Cloud_Weather_Station.ino
Если ваш сервер не поддерживает HTTPS, используйте этот скетч Arduino (совместим с ESP32 и ESP8266): ESP_HTTP_POST_MySQL.ino
1. Хостинг вашего PHP-приложения и базы данных MySQL
Цель этого проекта – иметь собственное доменное имя и хостинг-аккаунт, позволяющий хранить показания датчиков с ESP32 или ESP8266. Вы можете визуализировать показания из любой точки мира, обращаясь к домену своего собственного сервера.
Вот общий обзор того, как работает проект:
У вас есть ESP32 или ESP8266, который отправляет показания датчиков на ваш собственный сервер. Для этого ваша плата подключена к вашему роутеру;
На вашем сервере есть PHP-скрипт, который позволяет сохранять показания в базе данных MySQL;
Затем другой PHP-скрипт отображает веб-страницу со шкалами, таблицей и всей другой информацией;
Наконец, вы можете визуализировать показания из любой точки мира, обращаясь к вашему собственному доменному имени.
Хостинг-сервисы
Я рекомендую использовать один из следующих хостинг-сервисов, которые могут обеспечить все требования проекта:
Bluehost (удобный с cPanel): бесплатное доменное имя при подписке на 3-летний план. Я рекомендую выбрать опцию с неограниченным количеством сайтов;
Digital Ocean: Linux-сервер, которым вы управляете через командную строку. Я рекомендую эту опцию только для продвинутых пользователей.
Эти два сервиса – те, которые я использую и лично рекомендую, но вы можете использовать любой другой хостинг-сервис. Любой хостинг-сервис, предлагающий PHP и MySQL, будет работать с этим руководством. Если у вас нет хостинг-аккаунта, я рекомендую зарегистрироваться на Bluehost.
Получить хостинг и доменное имя с Bluehost >>
При покупке хостинг-аккаунта вам также нужно будет приобрести доменное имя. Именно это делает проект интересным: вы сможете перейти по своему доменному имени (https://example.com) и увидеть показания ESP.
Если вам нравятся наши проекты, вы можете рассмотреть возможность подписки на один из рекомендованных хостинг-сервисов, потому что таким образом вы поддержите нашу работу.
Примечание
Вы также можете запустить LAMP-сервер (Linux, Apache, MySQL, PHP) на Raspberry Pi для доступа к данным в локальной сети. Однако цель этого руководства – публикация показаний на вашем собственном домене, к которому вы можете получить доступ из любой точки мира. Это позволяет легко получить доступ к показаниям ESP без зависимости от сторонней IoT-платформы.
2. Подготовка базы данных MySQL
После регистрации хостинг-аккаунта и настройки доменного имени вы можете войти в cPanel или аналогичную панель управления. После этого выполните следующие шаги для создания базы данных, имени пользователя, пароля и SQL-таблицы.
Создание базы данных и пользователя
Откройте вкладку «Advanced»:
1. Введите «database» в строке поиска и выберите «MySQL Database Wizard».
2. Введите желаемое имя базы данных. В моем случае имя базы данных – esp_data. Затем нажмите кнопку «Next Step»:
Примечание
Позже вам нужно будет использовать имя базы данных с префиксом, который вам дает хост (мой префикс базы данных на скриншоте выше размыт). Далее я буду ссылаться на него как example_esp_data.
3. Введите имя пользователя базы данных и задайте пароль. Вы должны сохранить все эти данные, потому что они понадобятся позже для установления соединения с базой данных через ваш PHP-код.
Вот и все! Ваша новая база данных и пользователь были успешно созданы. Теперь сохраните все свои данные, потому что они понадобятся позже:
Имя базы данных: example_esp_data
Имя пользователя: example_esp_board
Пароль: ваш пароль
Создание SQL-таблицы
После создания базы данных и пользователя вернитесь на панель управления cPanel и найдите «phpMyAdmin».
В левой боковой панели выберите имя вашей базы данных example_esp_data и откройте вкладку «SQL».
Важно: убедитесь, что вы открыли базу данных example_esp_data. Затем нажмите вкладку SQL. Если вы не выполните эти шаги точно и запустите SQL-запрос, вы можете создать таблицу в неправильной базе данных.
Скопируйте SQL-запрос из следующего фрагмента:
CREATE TABLE SensorData (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
sensor VARCHAR(30) NOT NULL,
location VARCHAR(30) NOT NULL,
value1 VARCHAR(10),
value2 VARCHAR(10),
value3 VARCHAR(10),
reading_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
Вставьте его в поле SQL-запроса (выделено красным прямоугольником) и нажмите кнопку «Go» для создания таблицы:
После этого вы должны увидеть вашу новую таблицу SensorData в базе данных example_esp_data, как показано на рисунке ниже:
3. PHP-скрипт HTTP POST – прием и вставка данных в базу данных MySQL
В этом разделе мы создадим PHP-скрипт, который отвечает за прием входящих запросов от ESP32 или ESP8266 и вставку данных в базу данных MySQL.
Если вы используете хостинг-провайдера с cPanel, вы можете найти «File Manager»:
Затем выберите опцию public_html и нажмите кнопку «+ File» для создания нового файла .php.
Примечание
Если вы следуете этому руководству и не знакомы с PHP или MySQL, я рекомендую создать именно эти файлы. В противном случае вам нужно будет изменить скетч ESP, предоставленный с другими URL-путями.
Создайте новый файл в /public_html с таким точным именем и расширением: esp-post-data.php
Отредактируйте вновь созданный файл (esp-post-data.php) и скопируйте следующий фрагмент:
<!--
Rui Santos
Complete project details at https://RandomNerdTutorials.com/cloud-weather-station-esp32-esp8266/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
-->
<?php
include_once('esp-database.php');
// Keep this API Key value to be compatible with the ESP code provided in the project page. If you change this value, the ESP sketch needs to match
$api_key_value = "tPmAT5Ab3j7F9";
$api_key= $sensor = $location = $value1 = $value2 = $value3 = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$api_key = test_input($_POST["api_key"]);
if($api_key == $api_key_value) {
$sensor = test_input($_POST["sensor"]);
$location = test_input($_POST["location"]);
$value1 = test_input($_POST["value1"]);
$value2 = test_input($_POST["value2"]);
$value3 = test_input($_POST["value3"]);
$result = insertReading($sensor, $location, $value1, $value2, $value3);
echo $result;
}
else {
echo "Wrong API Key provided.";
}
}
else {
echo "No data posted with HTTP POST.";
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
4. PHP-скрипт для функций базы данных
Создайте новый файл в /public_html, который отвечает за вставку и доступ к данным в вашей базе данных. Назовите файл: esp-database.php
Скопируйте этот PHP-скрипт:
<!--
Rui Santos
Complete project details at https://RandomNerdTutorials.com/cloud-weather-station-esp32-esp8266/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
-->
<?php
$servername = "localhost";
// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";
function insertReading($sensor, $location, $value1, $value2, $value3) {
global $servername, $username, $password, $dbname;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "INSERT INTO SensorData (sensor, location, value1, value2, value3)
VALUES ('" . $sensor . "', '" . $location . "', '" . $value1 . "', '" . $value2 . "', '" . $value3 . "')";
if ($conn->query($sql) === TRUE) {
return "New record created successfully";
}
else {
return "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
}
function getAllReadings($limit) {
global $servername, $username, $password, $dbname;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT id, sensor, location, value1, value2, value3, reading_time FROM SensorData order by reading_time desc limit " . $limit;
if ($result = $conn->query($sql)) {
return $result;
}
else {
return false;
}
$conn->close();
}
function getLastReadings() {
global $servername, $username, $password, $dbname;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT id, sensor, location, value1, value2, value3, reading_time FROM SensorData order by reading_time desc limit 1" ;
if ($result = $conn->query($sql)) {
return $result->fetch_assoc();
}
else {
return false;
}
$conn->close();
}
function minReading($limit, $value) {
global $servername, $username, $password, $dbname;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT MIN(" . $value . ") AS min_amount FROM (SELECT " . $value . " FROM SensorData order by reading_time desc limit " . $limit . ") AS min";
if ($result = $conn->query($sql)) {
return $result->fetch_assoc();
}
else {
return false;
}
$conn->close();
}
function maxReading($limit, $value) {
global $servername, $username, $password, $dbname;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT MAX(" . $value . ") AS max_amount FROM (SELECT " . $value . " FROM SensorData order by reading_time desc limit " . $limit . ") AS max";
if ($result = $conn->query($sql)) {
return $result->fetch_assoc();
}
else {
return false;
}
$conn->close();
}
function avgReading($limit, $value) {
global $servername, $username, $password, $dbname;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT AVG(" . $value . ") AS avg_amount FROM (SELECT " . $value . " FROM SensorData order by reading_time desc limit " . $limit . ") AS avg";
if ($result = $conn->query($sql)) {
return $result->fetch_assoc();
}
else {
return false;
}
$conn->close();
}
?>
Перед сохранением файла вам нужно изменить переменные $dbname, $username и $password, указав свои уникальные данные:
// Your Database name
$dbname = "example_esp_data";
// Your Database user
$username = "example_esp_board";
// Your Database user password
$password = "YOUR_USER_PASSWORD";
После добавления имени базы данных, имени пользователя и пароля сохраните файл и продолжайте с этим руководством. Если вы попробуете обратиться к вашему доменному имени по следующему URL-пути, вы увидите следующее:
https://example.com/esp-post-data.php
5. PHP-скрипт – отображение показаний базы данных на шкалах и в таблице
Вам также нужно добавить CSS-файл для стилизации вашей панели мониторинга, назовите его: esp-style.css:
Скопируйте этот CSS в ваш файл и сохраните его:
/**
Rui Santos
Complete project details at https://RandomNerdTutorials.com/cloud-weather-station-esp32-esp8266/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
**/
body {
width: 60%;
margin: auto;
text-align: center;
font-family: Arial;
top: 50%;
left: 50%;
}
@media screen and (max-width: 800px) {
body {
width: 100%;
}
}
table {
margin-left: auto;
margin-right: auto;
}
div {
margin-left: auto;
margin-right: auto;
}
h2 { font-size: 2.5rem; }
.header {
padding: 1rem;
margin: 0 0 2rem 0;
background: #f2f2f2;
}
h1 {
font-size: 2rem;
font-family: Arial, sans-serif;
text-align: center;
text-transform: uppercase;
}
.content {
display: flex;
}
@media screen and (max-width: 500px) /* Mobile */ {
.content {
flex-direction: column;
}
}
.mask {
position: relative;
overflow: hidden;
display: block;
width: 12.5rem;
height: 6.25rem;
margin: 1.25rem;
}
.semi-circle {
position: relative;
display: block;
width: 12.5rem;
height: 6.25rem;
background: linear-gradient(to right, #3498db 0%, #05b027 33%, #f1c40f 70%, #c0392b 100%);
border-radius: 50% 50% 50% 50% / 100% 100% 0% 0%;
}
.semi-circle::before {
content: "";
position: absolute;
bottom: 0;
left: 50%;
z-index: 2;
display: block;
width: 8.75rem;
height: 4.375rem;
margin-left: -4.375rem;
background: #fff;
border-radius: 50% 50% 50% 50% / 100% 100% 0% 0%;
}
.semi-circle--mask {
position: absolute;
top: 0;
left: 0;
width: 12.5rem;
height: 12.5rem;
background: transparent;
transform: rotate(120deg) translate3d(0, 0, 0);
transform-origin: center center;
backface-visibility: hidden;
transition: all 0.3s ease-in-out;
}
.semi-circle--mask::before {
content: "";
position: absolute;
top: 0;
left: 0%;
z-index: 2;
display: block;
width: 12.625rem;
height: 6.375rem;
margin: -1px 0 0 -1px;
background: #f2f2f2;
border-radius: 50% 50% 50% 50% / 100% 100% 0% 0%;
}
.gauge--2 .semi-circle { background: #3498db; }
.gauge--2 .semi-circle--mask { transform: rotate(20deg) translate3d(0, 0, 0); }
#tableReadings { border-collapse: collapse; }
#tableReadings td, #tableReadings th {
border: 1px solid #ddd;
padding: 10px;
}
#tableReadings tr:nth-child(even){ background-color: #f2f2f2; }
#tableReadings tr:hover { background-color: #ddd; }
#tableReadings th {
padding: 10px;
background-color: #2f4468;
color: white;
}
Наконец, создайте еще один PHP-файл в директории /public_html, который будет отображать все содержимое базы данных на веб-странице. Назовите новый файл: esp-weather-station.php
Отредактируйте вновь созданный файл (esp-weather-station.php) и скопируйте следующий код:
<!--
Rui Santos
Complete project details at https://RandomNerdTutorials.com/cloud-weather-station-esp32-esp8266/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
-->
<?php
include_once('esp-database.php');
if (isset($_GET["readingsCount"])){
$data = $_GET["readingsCount"];
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
$readings_count = $_GET["readingsCount"];
}
// default readings count set to 20
else {
$readings_count = 20;
}
$last_reading = getLastReadings();
$last_reading_temp = $last_reading["value1"];
$last_reading_humi = $last_reading["value2"];
$last_reading_time = $last_reading["reading_time"];
// Uncomment to set timezone to - 1 hour (you can change 1 to any number)
//$last_reading_time = date("Y-m-d H:i:s", strtotime("$last_reading_time - 1 hours"));
// Uncomment to set timezone to + 7 hours (you can change 7 to any number)
//$last_reading_time = date("Y-m-d H:i:s", strtotime("$last_reading_time + 7 hours"));
$min_temp = minReading($readings_count, 'value1');
$max_temp = maxReading($readings_count, 'value1');
$avg_temp = avgReading($readings_count, 'value1');
$min_humi = minReading($readings_count, 'value2');
$max_humi = maxReading($readings_count, 'value2');
$avg_humi = avgReading($readings_count, 'value2');
?>
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="esp-style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<header class="header">
<h1>ESP Weather Station</h1>
<form method="get">
<input type="number" name="readingsCount" min="1" placeholder="Number of readings (<?php echo $readings_count; ?>)">
<input type="submit" value="UPDATE">
</form>
</header>
<body>
<p>Last reading: <?php echo $last_reading_time; ?></p>
<section class="content">
<div class="box gauge--1">
<h3>TEMPERATURE</h3>
<div class="mask">
<div class="semi-circle"></div>
<div class="semi-circle--mask"></div>
</div>
<p style="font-size: 30px;" id="temp">--</p>
<table cellspacing="5" cellpadding="5">
<tr>
<th colspan="3">Temperature <?php echo $readings_count; ?> readings</th>
</tr>
<tr>
<td>Min</td>
<td>Max</td>
<td>Average</td>
</tr>
<tr>
<td><?php echo $min_temp['min_amount']; ?> °C</td>
<td><?php echo $max_temp['max_amount']; ?> °C</td>
<td><?php echo round($avg_temp['avg_amount'], 2); ?> °C</td>
</tr>
</table>
</div>
<div class="box gauge--2">
<h3>HUMIDITY</h3>
<div class="mask">
<div class="semi-circle"></div>
<div class="semi-circle--mask"></div>
</div>
<p style="font-size: 30px;" id="humi">--</p>
<table cellspacing="5" cellpadding="5">
<tr>
<th colspan="3">Humidity <?php echo $readings_count; ?> readings</th>
</tr>
<tr>
<td>Min</td>
<td>Max</td>
<td>Average</td>
</tr>
<tr>
<td><?php echo $min_humi['min_amount']; ?> %</td>
<td><?php echo $max_humi['max_amount']; ?> %</td>
<td><?php echo round($avg_humi['avg_amount'], 2); ?> %</td>
</tr>
</table>
</div>
</section>
<?php
echo '<h2> View Latest ' . $readings_count . ' Readings</h2>
<table cellspacing="5" cellpadding="5" id="tableReadings">
<tr>
<th>ID</th>
<th>Sensor</th>
<th>Location</th>
<th>Value 1</th>
<th>Value 2</th>
<th>Value 3</th>
<th>Timestamp</th>
</tr>';
$result = getAllReadings($readings_count);
if ($result) {
while ($row = $result->fetch_assoc()) {
$row_id = $row["id"];
$row_sensor = $row["sensor"];
$row_location = $row["location"];
$row_value1 = $row["value1"];
$row_value2 = $row["value2"];
$row_value3 = $row["value3"];
$row_reading_time = $row["reading_time"];
// Uncomment to set timezone to - 1 hour (you can change 1 to any number)
//$row_reading_time = date("Y-m-d H:i:s", strtotime("$row_reading_time - 1 hours"));
// Uncomment to set timezone to + 7 hours (you can change 7 to any number)
//$row_reading_time = date("Y-m-d H:i:s", strtotime("$row_reading_time + 7 hours"));
echo '<tr>
<td>' . $row_id . '</td>
<td>' . $row_sensor . '</td>
<td>' . $row_location . '</td>
<td>' . $row_value1 . '</td>
<td>' . $row_value2 . '</td>
<td>' . $row_value3 . '</td>
<td>' . $row_reading_time . '</td>
</tr>';
}
echo '</table>';
$result->free();
}
?>
<script>
var value1 = <?php echo $last_reading_temp; ?>;
var value2 = <?php echo $last_reading_humi; ?>;
setTemperature(value1);
setHumidity(value2);
function setTemperature(curVal){
//set range for Temperature in Celsius -5 Celsius to 38 Celsius
var minTemp = -5.0;
var maxTemp = 38.0;
//set range for Temperature in Fahrenheit 23 Fahrenheit to 100 Fahrenheit
//var minTemp = 23;
//var maxTemp = 100;
var newVal = scaleValue(curVal, [minTemp, maxTemp], [0, 180]);
$('.gauge--1 .semi-circle--mask').attr({
style: '-webkit-transform: rotate(' + newVal + 'deg);' +
'-moz-transform: rotate(' + newVal + 'deg);' +
'transform: rotate(' + newVal + 'deg);'
});
$("#temp").text(curVal + ' ºC');
}
function setHumidity(curVal){
//set range for Humidity percentage 0 % to 100 %
var minHumi = 0;
var maxHumi = 100;
var newVal = scaleValue(curVal, [minHumi, maxHumi], [0, 180]);
$('.gauge--2 .semi-circle--mask').attr({
style: '-webkit-transform: rotate(' + newVal + 'deg);' +
'-moz-transform: rotate(' + newVal + 'deg);' +
'transform: rotate(' + newVal + 'deg);'
});
$("#humi").text(curVal + ' %');
}
function scaleValue(value, from, to) {
var scale = (to[1] - to[0]) / (from[1] - from[0]);
var capped = Math.min(from[1], Math.max(from[0], value)) - from[0];
return ~~(capped * scale + to[0]);
}
</script>
</body>
</html>
Если вы попробуете обратиться к вашему доменному имени по следующему URL-пути, вы увидите следующее:
https://example.com/esp-weather-station.php
Вот и все! Если вы видите эту веб-страницу с пустыми значениями в вашем браузере, значит все готово. В следующем разделе вы узнаете, как вставить данные с вашего ESP32 или ESP8266 в базу данных.
6. Настройка ESP32 или ESP8266
Этот проект совместим как с платами ESP32, так и с ESP8266. Вам нужно просто собрать простую схему и загрузить предоставленный скетч для вставки температуры, влажности, давления и других данных в базу данных каждые 10 минут. Скетч немного отличается для каждой платы.
Необходимые компоненты
Для этого примера мы будем получать показания с датчика BME280. Вот список компонентов, необходимых для сборки схемы этого проекта:
Плата ESP32 (читайте Лучшие платы ESP32)
Альтернатива – плата ESP8266 (читайте Лучшие платы ESP8266)
Вы можете использовать ссылки выше или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!
Схемы подключения
Модуль датчика BME280, который мы используем, обменивается данными по протоколу I2C, поэтому его нужно подключить к выводам I2C ESP32 или ESP8266.
Подключение BME280 к ESP32
Выводы I2C ESP32:
GPIO 22: SCL (SCK)
GPIO 21: SDA (SDI)
Соберите схему, как показано на следующей диаграмме (Руководство по ESP32 с BME280 и Веб-сервер ESP32 BME280).
Рекомендуемое чтение: Справочник по выводам ESP32
Подключение BME280 к ESP8266
Выводы I2C ESP8266:
GPIO 5 (D1): SCL (SCK)
GPIO 4 (D2): SDA (SDI)
Соберите схему, как показано на следующей диаграмме, если вы используете плату ESP8266 (читайте Руководство по ESP8266 с BME280).
Рекомендуемое чтение: Справочник по выводам ESP8266
Установка библиотек
Мы будем программировать ESP32/ESP8266 с помощью Arduino IDE, поэтому у вас должно быть установлено дополнение ESP в вашей Arduino IDE.
Следуйте одному из следующих руководств в зависимости от используемой платы:
Код для ESP32
Следуйте этому разделу, если вы используете ESP32. Для ESP8266 нажмите здесь.
После установки необходимых дополнений платы скопируйте следующий код в вашу Arduino IDE, но пока не загружайте его. Вам нужно внести некоторые изменения, чтобы он работал для вас.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// REPLACE with your Domain name and URL path or IP address with path
const char* serverName = "https://example.com/esp-post-data.php";
// Keep this API Key value to be compatible with the PHP code provided in the project page.
// If you change the apiKeyValue value, the PHP file /post-esp-data.php also needs to have the same key
String apiKeyValue = "tPmAT5Ab3j7F9";
String sensorName = "BME280";
String sensorLocation = "Office";
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
// (you can also pass in a Wire library object like &Wire2)
bool status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring or change I2C address!");
while (1);
}
}
void loop() {
//Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
WiFiClientSecure *client = new WiFiClientSecure;
client->setInsecure(); //don't use SSL certificate
HTTPClient https;
// Your Domain name with URL path or IP address with path
https.begin(*client, serverName);
// Specify content-type header
https.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Prepare your HTTP POST request data
String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
+ "&location=" + sensorLocation + "&value1=" + String(bme.readTemperature())
+ "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
Serial.print("httpRequestData: ");
Serial.println(httpRequestData);
// You can comment the httpRequestData variable above
// then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
//String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BME280&location=Office&value1=24.75&value2=49.54&value3=1005.14";
// Send HTTP POST request
int httpResponseCode = https.POST(httpRequestData);
// If you need an HTTP request with a content type: text/plain
//https.addHeader("Content-Type", "text/plain");
//int httpResponseCode = https.POST("Hello, World!");
// If you need an HTTP request with a content type: application/json, use the following:
//https.addHeader("Content-Type", "application/json");
//int httpResponseCode = https.POST("{\"value1\":\"19\",\"value2\":\"67\",\"value3\":\"78\"}");
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
https.end();
}
else {
Serial.println("WiFi Disconnected");
}
//Send an HTTP POST request every 30 seconds
delay(30000);
}
Настройка сетевых учетных данных
Вам нужно изменить следующие строки, указав ваши сетевые учетные данные: SSID и пароль. В коде есть комментарии, указывающие, где нужно внести изменения.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Настройка serverName
Вам также нужно указать ваше доменное имя, чтобы ESP публиковал показания на ваш собственный сервер.
const char* serverName = "https://example.com/esp-post-data.php";
Теперь вы можете загрузить код на вашу плату.
Примечание
Большинство серверов требуют выполнения HTTPS-запросов. Код выше выполняет HTTPS-запросы для соответствия требованиям большинства современных облачных серверов.
Ваш сервер не поддерживает HTTPS? Используйте этот код вместо этого.
Как работает код
Этот проект уже достаточно объемный, поэтому мы не будем подробно описывать работу кода, но вот краткое изложение:
Импорт всех библиотек для работы;
Настройка переменных, которые вы можете изменить (apiKeyValue, sensorName, sensorLocation);
apiKeyValue – это просто случайная строка, которую вы можете изменить. Она используется в целях безопасности, чтобы только тот, кто знает ваш API-ключ, мог публиковать данные в вашу базу данных;
Инициализация последовательного соединения для целей отладки;
Установление Wi-Fi соединения с вашим роутером;
Инициализация BME280 для получения показаний;
Инициализация защищенного WiFi-клиента.
Затем в функции loop() выполняется HTTP POST запрос каждые 10 минут с последними показаниями BME280:
// Your Domain name with URL path or IP address with path
http.begin(serverName);
// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Prepare your HTTP POST request data
String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName + "&location=" + sensorLocation + "&value1=" + String(bme.readTemperature()) + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
int httpResponseCode = http.POST(httpRequestData);
Вы можете закомментировать переменную httpRequestData выше, которая объединяет все показания BME280, и использовать переменную httpRequestData ниже для тестовых целей:
String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BME280&location=Office&value1=24.75&value2=49.54&value3=1005.14";
Узнайте больше о HTTPS-запросах с ESP32: ESP32 HTTPS Requests (Arduino IDE).
Код для ESP8266
Следуйте этому разделу, если вы используете ESP8266. Для ESP32 смотрите раздел выше.
После установки необходимых дополнений платы и библиотек скопируйте следующий код в вашу Arduino IDE, но пока не загружайте его. Вам нужно внести некоторые изменения, чтобы он работал для вас.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// REPLACE with your Domain name and URL path or IP address with path
const char* serverName = "https://example.com/esp-post-data.php";
// Keep this API Key value to be compatible with the PHP code provided in the project page.
// If you change the apiKeyValue value, the PHP file /post-esp-data.php also needs to have the same key
String apiKeyValue = "tPmAT5Ab3j7F9";
String sensorName = "BME280";
String sensorLocation = "Office";
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
// (you can also pass in a Wire library object like &Wire2)
bool status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring or change I2C address!");
while (1);
}
}
void loop() {
//Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
// Ignore SSL certificate validation
client->setInsecure();
//create an HTTPClient instance
HTTPClient https;
// Your Domain name with URL path or IP address with path
https.begin(*client, serverName);
// Specify content-type header
https.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Prepare your HTTP POST request data
String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
+ "&location=" + sensorLocation + "&value1=" + String(bme.readTemperature())
+ "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
Serial.print("httpRequestData: ");
Serial.println(httpRequestData);
// You can comment the httpRequestData variable above
// then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
//String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BME280&location=Office&value1=24.75&value2=49.54&value3=1005.14";
// Send HTTP POST request
int httpResponseCode = https.POST(httpRequestData);
// If you need an HTTP request with a content type: text/plain
//http.addHeader("Content-Type", "text/plain");
//int httpResponseCode = https.POST("Hello, World!");
// If you need an HTTP request with a content type: application/json, use the following:
//http.addHeader("Content-Type", "application/json");
//int httpResponseCode = https.POST("{\"value1\":\"19\",\"value2\":\"67\",\"value3\":\"78\"}");
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
https.end();
}
else {
Serial.println("WiFi Disconnected");
}
//Send an HTTP POST request every 30 seconds
delay(30000);
}
Настройка сетевых учетных данных (ESP8266)
Вам нужно изменить следующие строки, указав ваши сетевые учетные данные: SSID и пароль. В коде есть комментарии, указывающие, где нужно внести изменения.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Настройка serverName (ESP8266)
Вам также нужно указать ваше доменное имя, чтобы ESP публиковал показания на ваш собственный сервер.
const char* serverName = "https://example.com/esp-post-data.php";
Теперь вы можете загрузить код на вашу плату.
Примечание
Большинство серверов требуют выполнения HTTPS-запросов. Код выше выполняет HTTPS-запросы для соответствия требованиям большинства современных облачных серверов.
Ваш сервер не поддерживает HTTPS? Используйте этот код вместо этого.
Узнайте больше о HTTPS-запросах с ESP8266: ESP8266 NodeMCU HTTPS Requests (Arduino IDE).
Демонстрация
После выполнения всех шагов дайте вашей плате ESP собрать некоторые показания и опубликовать их на вашем сервере.
Если все правильно, вот что вы должны увидеть в мониторе последовательного порта Arduino IDE:
Если вы откроете ваше доменное имя по следующему URL-пути:
https://example.com/esp-weather-station.php
Вы должны увидеть последние 20 показаний, сохраненных в вашей базе данных. Есть две шкалы, которые показывают последние показания температуры и влажности, а также временную метку.
Обновите веб-страницу, чтобы увидеть последние показания:
Есть поле, в которое вы можете ввести количество показаний для визуализации, а также количество показаний для статистики: минимум, максимум и среднее. По умолчанию установлено значение 20. Например, если вы введете 30 и нажмете кнопку обновления, вы увидите, что ваша веб-страница обновится и пересчитает все значения.
Веб-страница также адаптивна для мобильных устройств, поэтому вы можете использовать любое устройство для доступа к ней:
Вы также можете перейти в phpMyAdmin для управления данными, хранящимися в таблице SensorData. Вы можете удалять, редактировать данные и т.д.
Заключение
В этом руководстве вы узнали, как публиковать данные датчиков в базу данных на вашем собственном серверном домене, к которому вы можете получить доступ из любой точки мира. Для этого необходимо иметь свой собственный сервер и доменное имя (альтернативно, вы можете использовать LAMP-сервер на Raspberry Pi для локального доступа).
Я рекомендую вам изменить внешний вид веб-страницы, добавить больше функций (например, уведомления по электронной почте), публиковать данные с различных датчиков, использовать несколько плат ESP и многое другое.
Вам также может быть интересно прочитать:
Visualize Your Sensor Readings from Anywhere in the World (ESP32/ESP8266 + MySQL + PHP) using Charts
Узнайте больше о ESP32 и ESP8266 с помощью наших ресурсов:
Спасибо за чтение.
Источник: DIY Cloud Weather Station with ESP32/ESP8266 (MySQL Database and PHP)