Энергосберегающая метеостанция-даталоггер на ESP8266 и BME280 с MicroPython

Этот проект показывает, как построить даталоггер, который публикует показания температуры, влажности и давления каждые 10 минут в таблицу Google Sheets с помощью ESP8266 12-E. Между считыванием показаний датчика ESP находится в режиме глубокого сна и потребляет всего 7 мкА. Плата ESP программируется с использованием MicroPython, а для интеграции проекта с Google Sheets мы используем сервис IFTTT Webhooks.

ESP12-E Low Power MicroPython Weather Station

Этот проект также совместим с ESP32. Вам нужно будет внести лишь несколько изменений в код (мы покажем вам, что нужно сделать).

В рамках этого проекта вы освоите следующие концепции:

  • Считывание температуры, влажности и давления с BME280 и ESP8266/ESP32 с помощью MicroPython;

  • Выполнение HTTP POST-запросов в MicroPython для отправки показаний датчика в сторонний сервис;

  • Использование сервисов IFTTT Webhooks для сохранения показаний датчика в таблице Google Sheets;

  • Перевод ESP8266/ESP32 в режим глубокого сна и пробуждение по таймеру;

  • Подробнее о глубоком сне в MicroPython:

Прошивка MicroPython

Для прохождения этого руководства вам необходимо прошить прошивку MicroPython на ваш ESP32 или ESP8266. Вам также нужна IDE для написания и загрузки кода на плату. Мы рекомендуем использовать Thonny IDE или uPyCraft IDE:

Создание аккаунта IFTTT

В этом проекте мы будем публиковать показания датчика в таблице Google Sheets. Для этого мы используем сервисы IFTTT Webhooks. Поэтому вам нужно создать бесплатную учётную запись на IFTTT.

Перейдите на официальный сайт ifttt.com, введите свой email и завершите регистрацию, чтобы начать работу.

IFTTT

Создание апплета

Далее вам нужно создать новый апплет (Applet). Выполните следующие шаги для создания нового апплета:

1) Перейдите в «My Applets» и создайте новый апплет, нажав кнопку «New Applet».

New Applet

2) Нажмите на слово «this», выделенное синим цветом — как показано на рисунке ниже.

If This

3) Найдите сервис «Webhooks» и выберите значок Webhooks.

Webhooks

4) Выберите триггер «Receive a web request» (Получить веб-запрос).

Receive a web request

5) Дайте имя событию. В данном случае мы используем «bme_280_readings», и мы рекомендуем использовать именно это имя события, как показано на рисунке ниже. После этого нажмите кнопку «Create trigger».

IFTTT Event Name

6) Нажмите на слово «that», чтобы продолжить.

Then That

7) Найдите сервис «Google Sheets» и выберите значок Google Sheets.

Google Sheets

8) Если вы ещё не подключили сервис Google Sheets, вам нужно нажать кнопку «Connect».

Connect Google Sheets

9) Выберите действие «Add a row to spreadsheet» (Добавить строку в таблицу).

Add a row to spreadsheet

10) Затем заполните поля действия. Дайте таблице имя и оставьте остальные поля по умолчанию. Наконец, нажмите кнопку «Create action».

Complete action fields IFTTT

11) Ваш апплет будет создан после нажатия кнопки «Finish».

Review and Finish

Тестирование апплета

Прежде чем продолжить проект, очень важно сначала протестировать ваш апплет. Выполните следующие шаги для тестирования апплета.

1) Перейдите на страницу сервиса Webhooks, и нажмите кнопку «Documentation».

Maker Webhooks

2) Появится страница, как показано на следующем рисунке. На странице отображается ваш уникальный API-ключ. Вы не должны делиться своим уникальным API-ключом с кем-либо.

Заполните секцию «To trigger an Event», как показано ниже — она выделена красными прямоугольниками. Затем нажмите кнопку «Test it».

Webhooks Documentation

Примечание

Сохраните ваш IFTTT API-ключ, потому что он понадобится вам далее в этом проекте.

3) Событие должно быть успешно запущено, и вы увидите зелёное сообщение «Event has been triggered», как показано ниже.

Event has been triggered

4) Перейдите на ваш Google Диск. Сервис IFTTT должен был создать папку «IFTTT» с папкой «MakerWebhooks/bme280» внутри. В этой папке вы найдёте таблицу Bme_280_readings.

IFTTT Webhooks BME280

5) Откройте таблицу. Вы должны увидеть значения, которые вы ввели ранее для тестирования апплета.

Test Applet

Продолжайте читать это руководство, чтобы узнать, как интегрировать сервис IFTTT Google Sheets с вашим ESP8266 или ESP32.

Необходимые компоненты

Вот список компонентов, которые вам понадобятся для сборки схемы этого проекта:

Для этого проекта мы будем использовать ESP8266 12-E, потому что он потребляет меньше энергии в режиме глубокого сна (у него нет встроенного программатора). Вы также можете использовать ESP8266 NodeMCU Kit или плату разработки ESP32.

Загрузка кода на чип ESP8266 12-E

Для загрузки кода на ESP-12E необходимо установить последовательную связь между вашим ESP8266 и FTDI-программатором, как показано на схеме ниже.

ESP8266 ESP12-E FTDI uploading code
  • 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 можно найти по следующей ссылке:

https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/WiFi/HTTP_Client_IFTTT_BME280/BME280.py

Сохраните файл, нажав кнопку Save (2).

Create BME280 file

Назовите этот новый файл «BME280.py» и нажмите ok.

BME280.py filename

Нажмите кнопку Download and Run.

Download and Run

Примечание

Если у вас возникли проблемы с загрузкой нового скрипта на плату ESP, возможно, вам нужно перепрошить прошивку MicroPython: Прошивка MicroPython на ESP. Когда ESP находится в режиме глубокого сна, вы не можете загружать новые скрипты. Убедитесь, что вы сбросили плату, нажмите кнопку Stop в uPyCraft IDE сразу, чтобы перехватить её в активном состоянии, и тогда вы сможете получить доступ к сохранённым скриптам и загрузить новые.

Файл должен быть сохранён в папке устройства с именем «BME280.py», как показано на рисунке ниже.

BME280 success

Теперь вы можете использовать функционал библиотеки в своём коде, импортировав библиотеку.

Код

После загрузки файла 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.

BME280 sensor module

Следуйте одной из схем ниже в зависимости от платы, которую вы используете.

ESP8266 12-E

ESP8266 12-E BME280 schematic

Важно

Вы должны подключить GPIO16 к выводу RST только после загрузки кода. Это соединение необходимо для того, чтобы ESP8266 мог самостоятельно просыпаться.

Примечание

Если вы используете ESP8266 12-E, мы рекомендуем использовать адаптер для использования с макетной платой, чтобы упростить подключение. Кроме того, вы можете сделать печатную плату дома, как мы. Мы использовали метод травления.

ESP8266 12-E PCB adapter

ESP8266 NodeMCU Kit

Если вы используете ESP8266 NodeMCU kit, вам также необходимо подключить вывод RST к GPIO 16 (D0) после загрузки кода.

ESP8266 NodeMCU BME280 schematic

ESP32

Если вы используете ESP32, вам просто нужно подключить схему, как показано на диаграмме:

ESP32 BME280 schematic

Демонстрация

После загрузки необходимых файлов на вашу плату в следующем порядке:

  1. BME280.py

  2. boot.py

ESP8266/ESP32 начнёт публиковать показания датчика в таблицу Google Sheets.

Spreadsheet ESP8266 BME280

Энергопотребление

Когда ESP8266 12-E находится в режиме глубокого сна, он потребляет около 7-8 мкА.

ESP12-E low power deep sleep

Когда ESP8266 просыпается и подключается к Wi-Fi, потребление тока может достигать 80 мА.

ESP12-E normal mode

Если вы используете плату разработки ESP, вы получите более высокое потребление тока в режиме глубокого сна.

Питание ESP8266/ESP32 от аккумуляторов

Если вы собираете этот проект с чипом ESP8266 12-E, он потребляет очень мало энергии в режиме глубокого сна (примерно 7 мкА). Вы можете питать его от аккумуляторов, и они прослужат несколько месяцев (или даже лет, в зависимости от ёмкости).

Мы планируем создать часть 2 этого проекта с использованием схемы питания от аккумулятора. А пока вы можете прочитать это руководство по питанию ESP от LiPo и Li-ion аккумуляторов.

ESP8266 LiPo Li-ion Batteries circuit

Итоги

С помощью этого проекта вы научились создавать даталоггер, который публикует показания датчика в таблицу Google Sheets. В ходе руководства вы узнали, как использовать BME280, выполнять HTTP POST-запросы и использовать глубокий сон с ESP8266/ESP32 на MicroPython.

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

Спасибо за чтение.