Энергосберегающая метеостанция-даталоггер на ESP8266 и BME280 с MicroPython
Этот проект показывает, как построить даталоггер, который публикует показания температуры, влажности и давления каждые 10 минут в таблицу Google Sheets с помощью ESP8266 12-E. Между считыванием показаний датчика ESP находится в режиме глубокого сна и потребляет всего 7 мкА. Плата ESP программируется с использованием MicroPython, а для интеграции проекта с Google Sheets мы используем сервис IFTTT Webhooks.
Этот проект также совместим с ESP32. Вам нужно будет внести лишь несколько изменений в код (мы покажем вам, что нужно сделать).
В рамках этого проекта вы освоите следующие концепции:
Считывание температуры, влажности и давления с BME280 и ESP8266/ESP32 с помощью MicroPython;
Выполнение HTTP POST-запросов в MicroPython для отправки показаний датчика в сторонний сервис;
Использование сервисов IFTTT Webhooks для сохранения показаний датчика в таблице Google Sheets;
Перевод ESP8266/ESP32 в режим глубокого сна и пробуждение по таймеру;
Подробнее о глубоком сне в MicroPython:
Прошивка MicroPython
Для прохождения этого руководства вам необходимо прошить прошивку MicroPython на ваш ESP32 или ESP8266. Вам также нужна IDE для написания и загрузки кода на плату. Мы рекомендуем использовать Thonny IDE или uPyCraft IDE:
Thonny IDE:
uPyCraft IDE:
Создание аккаунта IFTTT
В этом проекте мы будем публиковать показания датчика в таблице Google Sheets. Для этого мы используем сервисы IFTTT Webhooks. Поэтому вам нужно создать бесплатную учётную запись на IFTTT.
Перейдите на официальный сайт ifttt.com, введите свой email и завершите регистрацию, чтобы начать работу.
Создание апплета
Далее вам нужно создать новый апплет (Applet). Выполните следующие шаги для создания нового апплета:
1) Перейдите в «My Applets» и создайте новый апплет, нажав кнопку «New Applet».
2) Нажмите на слово «this», выделенное синим цветом — как показано на рисунке ниже.
3) Найдите сервис «Webhooks» и выберите значок Webhooks.
4) Выберите триггер «Receive a web request» (Получить веб-запрос).
5) Дайте имя событию. В данном случае мы используем «bme_280_readings», и мы рекомендуем использовать именно это имя события, как показано на рисунке ниже. После этого нажмите кнопку «Create trigger».
6) Нажмите на слово «that», чтобы продолжить.
7) Найдите сервис «Google Sheets» и выберите значок Google Sheets.
8) Если вы ещё не подключили сервис Google Sheets, вам нужно нажать кнопку «Connect».
9) Выберите действие «Add a row to spreadsheet» (Добавить строку в таблицу).
10) Затем заполните поля действия. Дайте таблице имя и оставьте остальные поля по умолчанию. Наконец, нажмите кнопку «Create action».
11) Ваш апплет будет создан после нажатия кнопки «Finish».
Тестирование апплета
Прежде чем продолжить проект, очень важно сначала протестировать ваш апплет. Выполните следующие шаги для тестирования апплета.
1) Перейдите на страницу сервиса Webhooks, и нажмите кнопку «Documentation».
2) Появится страница, как показано на следующем рисунке. На странице отображается ваш уникальный API-ключ. Вы не должны делиться своим уникальным API-ключом с кем-либо.
Заполните секцию «To trigger an Event», как показано ниже — она выделена красными прямоугольниками. Затем нажмите кнопку «Test it».
Примечание
Сохраните ваш IFTTT API-ключ, потому что он понадобится вам далее в этом проекте.
3) Событие должно быть успешно запущено, и вы увидите зелёное сообщение «Event has been triggered», как показано ниже.
4) Перейдите на ваш Google Диск. Сервис IFTTT должен был создать папку «IFTTT» с папкой «MakerWebhooks/bme280» внутри. В этой папке вы найдёте таблицу Bme_280_readings.
5) Откройте таблицу. Вы должны увидеть значения, которые вы ввели ранее для тестирования апплета.
Продолжайте читать это руководство, чтобы узнать, как интегрировать сервис IFTTT Google Sheets с вашим ESP8266 или ESP32.
Необходимые компоненты
Вот список компонентов, которые вам понадобятся для сборки схемы этого проекта:
ESP8266 12-E — читайте Лучшие платы разработки ESP8266 Wi-Fi
[Альтернатива] Плата ESP32 — читайте Сравнение плат разработки ESP32
[Опционально] Схема стабилизатора напряжения для LiPo и Li-ion аккумуляторов
Для этого проекта мы будем использовать ESP8266 12-E, потому что он потребляет меньше энергии в режиме глубокого сна (у него нет встроенного программатора). Вы также можете использовать ESP8266 NodeMCU Kit или плату разработки ESP32.
Загрузка кода на чип ESP8266 12-E
Для загрузки кода на ESP-12E необходимо установить последовательную связь между вашим ESP8266 и FTDI-программатором, как показано на схеме ниже.
RX – TX
TX – RX
VCC – VCC
VCC – EN
GND – GND
GND – GPIO15
GND – GPIO0
Если вы хотите узнать больше о выводах ESP12-E и о том, как их использовать, вы можете прочитать руководство ESP8266 Pinout Reference Guide.
Установка библиотеки BME280
Библиотека для чтения данных с датчика BME280 не является частью стандартной прошивки MicroPython. Поэтому вам нужно загрузить библиотеку на вашу плату ESP8266/ESP32.
В uPyCraft IDE создайте новый файл, нажав кнопку New File (1). Скопируйте код библиотеки BME280 в него. Код библиотеки BME280 можно найти по следующей ссылке:
Сохраните файл, нажав кнопку Save (2).
Назовите этот новый файл «BME280.py» и нажмите ok.
Нажмите кнопку Download and Run.
Примечание
Если у вас возникли проблемы с загрузкой нового скрипта на плату ESP, возможно, вам нужно перепрошить прошивку MicroPython: Прошивка MicroPython на ESP. Когда ESP находится в режиме глубокого сна, вы не можете загружать новые скрипты. Убедитесь, что вы сбросили плату, нажмите кнопку Stop в uPyCraft IDE сразу, чтобы перехватить её в активном состоянии, и тогда вы сможете получить доступ к сохранённым скриптам и загрузить новые.
Файл должен быть сохранён в папке устройства с именем «BME280.py», как показано на рисунке ниже.
Теперь вы можете использовать функционал библиотеки в своём коде, импортировав библиотеку.
Код
После загрузки файла BME280.py на ваш ESP8266 или ESP32, скопируйте следующий код в файл boot.py. Файл boot.py выполняется один раз при загрузке (это означает, что он выполняется каждый раз, когда ESP8266/ESP32 просыпается).
# Complete project details at https://RandomNerdTutorials.com
import machine
from machine import Pin, I2C
import BME280
import network
import urequests
from time import sleep
import esp
esp.osdebug(None)
import gc
gc.collect()
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
api_key = 'REPLACE_WITH_YOUR_IFTTT_API_KEY'
ms_sleep_time = 600000
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Connection successful')
print(station.ifconfig())
def deep_sleep(msecs) :
# configure RTC.ALARM0 to be able to wake the device
rtc = machine.RTC()
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
# set RTC.ALARM0 to fire after X milliseconds (waking the device)
rtc.alarm(rtc.ALARM0, msecs)
# put the device to sleep
machine.deepsleep()
# ESP8266 - Pin assignement
i2c = I2C(scl=Pin(5),sda=Pin(4), freq=10000)
# ESP32 - Pin assignement
#i2c = I2C(scl=Pin(22),sda=Pin(21), freq=10000)
try:
bme = BME280.BME280(i2c=i2c)
temp = bme.temperature
hum = bme.humidity
pres = bme.pressure
# uncomment for temperature in Fahrenheit
#temp = (bme.read_temperature()/100) * (9/5) + 32
#temp = str(round(temp, 2)) + 'F'
sensor_readings = {'value1':temp[:-1], 'value2':hum[:-1], 'value3':pres[:-3]}
print(sensor_readings)
request_headers = {'Content-Type': 'application/json'}
request = urequests.post(
'http://maker.ifttt.com/trigger/bme280/with/key/' + api_key,
json=sensor_readings,
headers=request_headers)
print(request.text)
request.close()
except OSError as e:
print('Failed to read/publish sensor readings.')
sleep(10)
#ESP8266
deep_sleep(ms_sleep_time)
#ESP32
#machine.deepsleep(ms_sleep_time)
Прежде чем загружать код на плату, вам нужно вставить свои учётные данные сети и уникальный API-ключ IFTTT. Продолжайте читать, чтобы узнать, как это сделать.
Как работает код
Давайте кратко рассмотрим код и разберёмся, как он работает.
Импорт библиотек
Вы начинаете с импорта необходимых модулей. Для взаимодействия с GPIO и чтения данных с датчика по протоколу I2C необходимо импортировать классы Pin и I2C из модуля machine. Вы также импортируете полный модуль machine, чтобы использовать функции, связанные с глубоким сном.
import machine
from machine import Pin, I2C
Вам нужно импортировать библиотеку BME280, которую вы ранее загрузили на плату.
import BME280
Для подключения к вашей сети необходимо импортировать модуль network.
import network
Вам нужна библиотека urequests. Эта библиотека позволяет выполнять HTTP-запросы. В этом примере мы будем делать запрос к сервисам IFTTT для публикации показаний датчика в таблицу Google Sheets.
import urequests
Наконец, импортируйте функцию sleep из модуля time, чтобы иметь возможность добавлять задержки в код.
from time import sleep
Настройка учётных данных сети
Вам нужно добавить свои SSID и пароль в следующие переменные:
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
Добавление API-ключа IFTTT
Вставьте свой уникальный API-ключ из сервиса Webhooks IFTTT в следующую строку:
api_key = 'REPLACE_WITH_YOUR_WEBHOOKS_IFTTT_API_KEY'
Настройка времени сна
В этом примере мы установили время сна на 10 минут (600000 миллисекунд). Это означает, что каждые 10 минут ESP просыпается, считывает показания и публикует их в таблице Google Sheets. Время сна задаётся в переменной ms_sleep_time в миллисекундах:
ms_sleep_time = 600000
Предупреждение
Если вы установите очень короткий период, вы можете превысить лимит запросов, установленный сервисами IFTTT.
Подключение к сети
Следующие строки подключают ESP8266/ESP32 к вашему роутеру и выводят IP-адрес ESP:
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Connection successful')
print(station.ifconfig())
Функция глубокого сна (ESP8266)
Затем создайте функцию deep_sleep(), которая принимает в качестве аргумента количество миллисекунд, на которые мы хотим перевести ESP8266 в режим глубокого сна.
def deep_sleep(msecs) :
# configure RTC.ALARM0 to be able to wake the device
rtc = machine.RTC()
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
# set RTC.ALARM0 to fire after X milliseconds (waking the device)
rtc.alarm(rtc.ALARM0, msecs)
# put the device to sleep
machine.deepsleep()
Примечание
Если вы используете ESP32, вам не нужно создавать/использовать эту функцию.
Чтение температуры, влажности и давления
Затем создайте экземпляр I2C с именем i2c. Он нужен для установления I2C-соединения с датчиком BME280. Передайте в качестве аргументов выводы SCL и SDA, а также частоту. Не беспокойтесь о частоте, значение 10000 Гц отлично подходит для этого датчика.
Выводы I2C по умолчанию для ESP8266 — это GPIO 5 (SCL) и GPIO 4 (SDA).
i2c = I2C(scl=Pin(5),sda=Pin(4), freq=10000)
Выводы I2C по умолчанию для ESP32 — это GPIO 22 (SCL) и GPIO 21 (SDA). Закомментируйте предыдущую строку и раскомментируйте следующую, если вы используете плату ESP32.
#i2c = I2C(scl=Pin(22),sda=Pin(21), freq=10000)
Затем используйте операторы try/except. В операторе try мы считываем данные с датчика и выполняем HTTP POST-запрос к сервисам IFTTT.
Температура сохраняется в переменной temp, влажность — в переменной hum, а давление — в переменной pres.
try:
bme = BME280.BME280(i2c=i2c)
temp = bme.temperature
hum = bme.humidity
pres = bme.pressure
Раскомментируйте следующие строки, если хотите получить температуру в градусах Фаренгейта.
# uncomment for temperature in Fahrenheit
#temp = (bme.read_temperature()/100) * (9/5) + 32
#temp = str(round(temp, 2)) + 'F'
Затем сохраните показания датчика в формате JSON в переменной sensor_readings. Это необходимо для выполнения HTTP POST-запроса в IFTTT.
sensor_readings = {'value1':temp[:-1], 'value2':hum[:-1], 'value3':pres[:-3]}
Библиотека BME280 возвращает показания с единицами измерения (C для температуры, % для влажности и hPa для давления). Чтобы упростить последующий анализ данных, мы удаляем единицы измерения, добавляя [:-1] для удаления последнего символа строки. [:-3] для давления удаляет последние три символа строки (hPa).
HTTP POST-запрос
Общий HTTP POST-запрос в MicroPython с использованием библиотеки urequests имеет следующий формат:
request = requests.post(<your_url>, json=<json_data>, headers=<headers>)
Первый параметр — это URL, по которому вы будете делать запрос. Как мы видели в апплете IFTTT, нам нужно использовать следующий URL (в котором api_key будет заменён на ваш собственный API-ключ):
http://maker.ifttt.com/trigger/bme_280_readings/with/key/your_api_key
Параметр JSON должен содержать данные в формате JSON. В нашем случае это переменная sensor_readings:
json=sensor_readings
Параметр headers содержит информацию о запросе. Для нашего запроса заголовки должны быть следующими:
request_headers = {'Content-Type': 'application/json'}
Наконец, мы выполняем запрос с помощью метода post() с информацией, которую мы определили ранее:
request = urequests.post(
'http://maker.ifttt.com/trigger/bme_280_readings/with/key/' + api_key,
json=sensor_readings,
headers=request_headers)
Наконец, выведите запрос и закройте соединение:
print(request.text)
request.close()
Если чтение данных с датчика или публикация показаний не удаётся, выполняется оператор except и мы выводим сообщение „Failed to read/publish sensor readings.“.
except OSError as e:
print('Failed to read/publish sensor readings.')
Операторы except в MicroPython предотвращают сбой вашей платы в случае возникновения ошибки.
Переход в режим сна
После выполнения HTTP POST-запроса мы переводим ESP8266/ESP32 в режим глубокого сна. Используйте следующую строку, если вы используете ESP8266:
deep_sleep(sleep_time_ms)
Закомментируйте предыдущую строку и раскомментируйте следующую, если вы используете ESP32:
#machine.deepsleep(ms_sleep_time)
Для использования глубокого сна с ESP32 с пробуждением по таймеру нужно просто вызвать метод deepsleep() и передать в качестве аргумента время сна в миллисекундах.
Сборка схемы
Датчик BME280, который мы используем, взаимодействует по протоколу I2C.
Следуйте одной из схем ниже в зависимости от платы, которую вы используете.
ESP8266 12-E
Важно
Вы должны подключить GPIO16 к выводу RST только после загрузки кода. Это соединение необходимо для того, чтобы ESP8266 мог самостоятельно просыпаться.
Примечание
Если вы используете ESP8266 12-E, мы рекомендуем использовать адаптер для использования с макетной платой, чтобы упростить подключение. Кроме того, вы можете сделать печатную плату дома, как мы. Мы использовали метод травления.
ESP8266 NodeMCU Kit
Если вы используете ESP8266 NodeMCU kit, вам также необходимо подключить вывод RST к GPIO 16 (D0) после загрузки кода.
ESP32
Если вы используете ESP32, вам просто нужно подключить схему, как показано на диаграмме:
Демонстрация
После загрузки необходимых файлов на вашу плату в следующем порядке:
BME280.py
boot.py
ESP8266/ESP32 начнёт публиковать показания датчика в таблицу Google Sheets.
Энергопотребление
Когда ESP8266 12-E находится в режиме глубокого сна, он потребляет около 7-8 мкА.
Когда ESP8266 просыпается и подключается к Wi-Fi, потребление тока может достигать 80 мА.
Если вы используете плату разработки ESP, вы получите более высокое потребление тока в режиме глубокого сна.
Питание ESP8266/ESP32 от аккумуляторов
Если вы собираете этот проект с чипом ESP8266 12-E, он потребляет очень мало энергии в режиме глубокого сна (примерно 7 мкА). Вы можете питать его от аккумуляторов, и они прослужат несколько месяцев (или даже лет, в зависимости от ёмкости).
Мы планируем создать часть 2 этого проекта с использованием схемы питания от аккумулятора. А пока вы можете прочитать это руководство по питанию ESP от LiPo и Li-ion аккумуляторов.
Итоги
С помощью этого проекта вы научились создавать даталоггер, который публикует показания датчика в таблицу Google Sheets. В ходе руководства вы узнали, как использовать BME280, выполнять HTTP POST-запросы и использовать глубокий сон с ESP8266/ESP32 на MicroPython.
Надеемся, этот проект был для вас интересным. Вам также могут понравиться:
[Электронная книга] Программирование на MicroPython с ESP32 и ESP8266
ESP32 веб-сервер с BME280 — мини-метеостанция (Arduino IDE)
ESP32 Публикация показаний датчика в Google Sheets (совместимо с ESP8266) (Arduino IDE)
Спасибо за чтение.