Мониторинг окружающей среды на ESP32 и SCD40

После эксперимента с мониторингом СО2 на Arduino Nano и MQ-135 и крайне странными полученными данными были докуплены новые датчики — MH-Z19B модуль инфракрасного датчика CO2 и SCD40 модуль измерения CO2, температуры и влажности, но руки как-то все не доходили, пока не подвернулась лабораторная работа по дисциплине «Разработка микроконтроллерных устройств Интернета вещей» на базе ESP32 C3 Super Mini. Незамедлительно был закуплен контроллер и заброшен на полку до лучших времен, которые все же настали, а потом и появилось время зафиксировать результат.

И так, имеется:

  1. ESP32 C3 Super Mini — микроконтроллер с WiFi/BLE
  2. LCD1602C — текстовый дисплей 16×2 символов (I2C интерфейс)
  3. SCD40 — датчик CO₂, температуры и влажности (I2C интерфейс Sensirion)
  4. Макетная плата 830
  5. Модуль питания MB-102 (3.3V/5V)

Задача:

Разработать проект — схему подключения компонентов, разработать код с учетом новых компонентов и требований к мониторингу параметров через веб-интерфейс по WiFi, подготовить описание по монтажу и программированию контроллера. Необходимые данные — текущие измеряемые значения датчика, все доступные параметры компонентов — энергопотребление, токи, напряжения. Если базовый набор компонентов не позволяет выполнить все требования в части данных, то необходимо разработать два варианта проекта — из базового набора и с дополнительными компонентами.

Будем работать от самой простой реализации с постепенным усложнением функционала.

 

Базовый вариант:

Измерение CO₂, температуры, влажности от SCD40 и параметров которые возможно получить/измерить без дополнительных датчиков на ESP32 с отображением данных на LCD1602.

Этап 2:

Добавить веб-интерфейс с текущими показаниями.

Этап 3:

Добавить дополнительный модуль измерителя тока/напряжения для измерения:

  • Напряжение питания системы
  • Потребляемого тока
  • Мощности энергопотребления
  • Напряжения на каждом компоненте

Базовый вариант

Принципиальную схему и макетную плату готовим в Fritzing. Компоненты нашел тут SCD40LCD1602ESP32 C3 Super MiniMB-102 (YwRobot). Попутно нашел STL модели корпусов.

Принципиальная схема устройства
Макетная схема

Файл проекта Lab ESP32-SCD40-LCD1602 Sketch

Код получился следующим:

/*
* Проект: Монитор качества воздуха ESP32-C3
* Датчики: SCD40 (CO2, температура, влажность)
* Дисплей: LCD1602 I2C
*/

#include <Wire.h>
#include <LCDI2C_Multilingual_MCD.h>
#include <SparkFun_SCD4x_Arduino_Library.h>

// ===== НАСТРОЙКИ I2C =====
#define I2C_SDA 8 // GPIO8 - SDA
#define I2C_SCL 9 // GPIO9 - SCL
#define LCD_ADDR 0x27 // Адрес LCD

// ===== НАСТРОЙКИ ADC ДЛЯ ИЗМЕРЕНИЯ НАПРЯЖЕНИЯ =====
#define ADC_PIN 4 // GPIO4 - аналоговый вход
#define ADC_VREF 3.3 // Опорное напряжение АЦП
#define ADC_RESOLUTION 4095.0 // 12-бит АЦП

// ===== ОБЪЕКТЫ =====
LCDI2C_Russian lcd(LCD_ADDR, 16, 2); // LCD 16x2
SCD4x scd40; // Датчик SCD40

// ===== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ =====
float co2 = 0; // CO2 в ppm
float temperature = 0; // Температура в °C
float humidity = 0; // Влажность в %
float voltage = 0; // Напряжение питания
unsigned long lastUpdate = 0;
const unsigned long UPDATE_INTERVAL = 5000; // Обновление каждые 5 секунд

// ===== СИМВОЛЫ ДЛЯ LCD =====
byte degreeSymbol[8] = { // Символ градуса
   0b01100,
   0b10010,
   0b10010,
   0b01100,
   0b00000,
   0b00000,
   0b00000,
   0b00000
};

void setup() {
   Serial.begin(115200);
   delay(1000);
   Serial.println("=== ESP32-C3 Monitor - Запуск ===");

   // Инициализация I2C
   Wire.begin(I2C_SDA, I2C_SCL);
   Serial.println("I2C инициализирован");

   // Инициализация LCD
   lcd.init();
   lcd.backlight();
   lcd.createChar(0, degreeSymbol);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("ESP32-C3 Monitor");
   lcd.setCursor(0, 1);
   lcd.print("Starting...");
   Serial.println("LCD инициализирован");

   // Инициализация SCD40
   if(!scd40.begin()) {
      Serial.println("ОШИБКА: SCD40 не найден!");
      lcd.clear();
      lcd.print("SCD40: Error!");
      while(1) {
         delay(1000);
      }
    }

   // Запуск периодических измерений SCD40
   if(scd40.startPeriodicMeasurement()) {
      Serial.println("SCD40 инициализирован успешно");
   } else {
      Serial.println("ОШИБКА запуска измерений SCD40");
   }

   delay(1000);
   lcd.clear();
   lcd.print("System ready");
   Serial.println("Система готова к работе");
   delay(2000);
}

void loop() {

   // Обновление данных с датчиков
   if(millis() - lastUpdate >= UPDATE_INTERVAL) {
   lastUpdate = millis();
   updateSensors();
   updateDisplay();
   }
   delay(10);
}

// ===== ФУНКЦИЯ ОБНОВЛЕНИЯ ДАННЫХ С ДАТЧИКОВ =====
void updateSensors() {

   // Чтение данных SCD40
   if(scd40.readMeasurement()) {
   co2 = scd40.getCO2();
   temperature = scd40.getTemperature();
   humidity = scd40.getHumidity();
   Serial.println("--- Новые данные ---");
   Serial.print("CO2: "); Serial.print(co2); Serial.println(" ppm");
   Serial.print("Температура: "); Serial.print(temperature); Serial.println(" °C");
   Serial.print("Влажность: "); Serial.print(humidity); Serial.println(" %");
   } else {
      Serial.println("Нет новых данных от SCD40");
   }

   // Измерение напряжения питания
   int adcValue = analogRead(ADC_PIN);
   voltage = (adcValue / ADC_RESOLUTION) * ADC_VREF * 2.0; // Делитель 1:2
   Serial.print("Напряжение: "); Serial.print(voltage); Serial.println(" V");
}

// ===== ФУНКЦИЯ ОБНОВЛЕНИЯ ДИСПЛЕЯ =====
void updateDisplay() {
   lcd.clear();

   // Первая строка: CO2 и температура
   lcd.setCursor(0, 0);
   lcd.print("CO2:");
   lcd.print((int)co2);
   lcd.print("ppm ");
   lcd.print((int)temperature);
   lcd.write(0); // Символ градуса
   lcd.print("C");

   // Вторая строка: Влажность и напряжение
   lcd.setCursor(0, 1);
   lcd.print("RH:");
   lcd.print((int)humidity);
   lcd.print("% U:");
   lcd.print(voltage, 1);
   lcd.print("V");
}

Собранное устройство:

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *