Своими рукамипрактическая инструкция

Форточка сама открывается: собираем вентиляцию теплицы на ESP32

Редакция Фермозавра·15 апреля 2026 г.·6 мин чтения

Солнце вышло — в теплице стало жарче. Соберём привод форточки, научим его реагировать на температуру и посмотрим, как автоматика ведёт себя при медленном нагреве.

Форточка сама открывается: собираем вентиляцию теплицы на ESP32

Утром форточка закрыта, солнце поднимается, а вы заняты на другом конце участка. Хочется, чтобы теплица проветривалась по температуре. Начнём с простого опыта: датчик DHT22, ESP32 и небольшой позиционный сервопривод. На столе будет видно, как изменение показаний превращается в движение.

Это лабораторная сборка для знакомства с автоматикой. Перед переносом на настоящую форточку подбирают питание, тягу и защиту от отказов. Проценты в программе задают положение привода; реальное положение створки проверяют отдельно. Начнём со снятой тяги, чтобы спокойно разобраться с направлением и ходом.

Что положить на стол

  • ESP32 DevKit на классическом ESP32; номера выводов нужно сверить со своей платой.
  • DHT22 и библиотека DHT sensor library от Adafruit. SHT31 не является программной заменой: ему нужны другая библиотека и подключение.
  • Позиционный RC-сервопривод, подходящий по усилию, ходу, питанию и уровню управляющего сигнала. Модель выбирают по механике, а не только по массе створки.
  • Отдельное питание сервопривода, рассчитанное в том числе на пуск и заклинивание, защита цепи питания, клеммы и провода соответствующего сечения.
  • Тяга, механические ограничители, возможность ручного освобождения створки и защищённый корпус электроники.

Пример рассчитан на позиционный RC-сервопривод. Для линейного привода на 12 В понадобится другой узел: драйвер направления, концевики и ограничитель времени движения. Выберите тип механики до покупки деталей — от него зависит и схема управления.

Подключаем датчик и привод

ESP32 3V3 → DHT22 VCC
ESP32 GND → DHT22 GND
ESP32 GPIO4 → DHT22 DATA
Подтяжка DATA → 3V3, по документации конкретного датчика/модуля
ESP32 GPIO18 → управляющий вход совместимого сервопривода
Отдельный источник питания → питание сервопривода
GND источника сервопривода → ESP32 GND
Переключатель «Открыть» → между GPIO25 и GND
Кнопка «Подтвердить восстановление» → между GPIO27 и GND

Плату ESP32 на стенде можно питать от USB. Не подавайте питание сервопривода на её вывод 3V3 и не соединяйте положительные выходы независимых источников. Если вход сервопривода не совместим с логикой 3,3 В, нужен согласователь уровня. Для DHT22 не подтягивайте DATA к 5 В.

Первое включение сделайте со снятой тягой. Посмотрите, куда поворачивается вал при запуске: библиотека может выдать начальный импульс ещё до первой команды. Затем подберите диапазон импульсов и крайние углы для своего привода.

Почему форточка не должна дёргаться на каждом измерении

Для первого опыта заданы такие точки: при 23 °C и ниже — закрыто, от 23 до 30 °C открытие растёт от 0 до 100%, при 30 °C — полностью открыто. У 35 °C есть отдельная приоритетная проверка. Так удобно проследить работу алгоритма; рабочие температуры потом выбирают под культуру и режим теплицы.

Попробуйте медленно менять температуру. Программа сравнивает её с показанием, при котором последний раз меняла цель. Накопился 1 °C — пора передвинуть привод. Так маленькие шаги складываются в заметное изменение, а лёгкие колебания возле одной температуры оставляют вал в покое.

При ошибке датчика контроллер запоминает неисправность и задаёт открытие на 100%. Проверьте этот переход на столе. Для настоящей теплицы аварийное положение выбирают с учётом мороза и ветра; вместе с ним предусматривают независимую защиту и возможность освободить створку вручную.

После запуска или ошибки дождитесь допустимого показания и нажмите подтверждение. Это ваш сигнал контроллеру: причину проверили, можно продолжать. Переключатель ручного открытия позволяет отдельно испытать полный ход. Температурный алгоритм работает одинаково днём и ночью.

Загружаем скетч

Для воспроизводимой сборки: Arduino-ESP32 3.3.12, ESP32Servo 3.2.1, DHT sensor library 1.4.7 и Adafruit Unified Sensor 1.1.15. Выберите плату ESP32 Dev Module. Перед подключением механики настройте CLOSED_ANGLE, OPEN_ANGLE, диапазон импульсов и FAULT_PERCENT под свой стенд.

#include <Arduino.h>
#include <DHT.h>
#include <ESP32Servo.h>
#include <math.h>

constexpr int DHT_PIN = 4, SERVO_PIN = 18;
constexpr int MANUAL_OPEN_PIN = 25, FAULT_RESET_PIN = 27;
constexpr int CLOSED_ANGLE = 20, OPEN_ANGLE = 120;
constexpr int FAULT_PERCENT = 100; // Выбрать по анализу отказов конкретной теплицы.
constexpr float T_CLOSED = 23.0f, T_OPEN = 30.0f;
constexpr float T_EMERGENCY = 35.0f, HYST = 1.0f;
constexpr uint32_t SAMPLE_MS = 10000, STEP_MS = 40;
DHT dht(DHT_PIN, DHT22);
Servo vent;
int commanded = FAULT_PERCENT, target = FAULT_PERCENT;
float acceptedTemp = NAN;
bool fault = true, valid = false, haveSample = false;
float temperature = NAN;
uint32_t sampledAt = 0, movedAt = 0;

int targetFor(float t) {
  if (t <= T_CLOSED) return 0;
  if (t >= T_OPEN) return 100;
  return int((t - T_CLOSED) * 100.0f / (T_OPEN - T_CLOSED) + 0.5f);
}
int angleFor(int percent) {
  return CLOSED_ANGLE + (OPEN_ANGLE - CLOSED_ANGLE) * percent / 100;
}
void acceptReading(float t, float h) {
  haveSample = true;
  valid = isfinite(t) && isfinite(h) && t >= -40 && t <= 80 && h >= 0 && h <= 100;
  if (!valid) {
    fault = true;
    acceptedTemp = NAN;
    Serial.println("FAULT: sensor; inspect and press RESET button");
    return;
  }
  temperature = t;
  // fault остаётся установленным до ручного подтверждения.
}
void decide(bool manualOpen, bool resetPressed) {
  if (resetPressed && haveSample && valid) {
    fault = false;
    acceptedTemp = NAN;
  }
  if (manualOpen) { target = 100; acceptedTemp = NAN; return; }
  if (fault) { target = FAULT_PERCENT; return; }
  if (temperature >= T_EMERGENCY) {
    target = 100; acceptedTemp = temperature; return;
  }
  // Сравниваем с температурой последнего принятого решения, а не прошлого опроса.
  if (!isfinite(acceptedTemp) || fabsf(temperature - acceptedTemp) >= HYST ||
      temperature <= T_CLOSED || temperature >= T_OPEN) {
    target = targetFor(temperature);
    acceptedTemp = temperature;
  }
}
void moveOneStep(uint32_t now) {
  if (uint32_t(now - movedAt) < STEP_MS || commanded == target) return;
  movedAt = now;
  if (commanded < target) commanded = min(commanded + 2, target);
  else commanded = max(commanded - 2, target);
  vent.write(angleFor(commanded));
}
void setup() {
  Serial.begin(115200);
  pinMode(MANUAL_OPEN_PIN, INPUT_PULLUP);
  pinMode(FAULT_RESET_PIN, INPUT_PULLUP);
  dht.begin();
  vent.setPeriodHertz(50);
  vent.attach(SERVO_PIN, 500, 2400);
  if (!vent.attached()) {
    Serial.println("FAULT: servo attach failed; manual intervention required");
    while (true) delay(1000);
  }
  vent.write(angleFor(commanded)); // Первая команда действительно отправляется.
  movedAt = millis();
}
void loop() {
  const uint32_t now = millis();
  if (!haveSample || uint32_t(now - sampledAt) >= SAMPLE_MS) {
    sampledAt = now;
    acceptReading(dht.readTemperature(), dht.readHumidity());
    Serial.printf("T=%.1f valid=%d fault=%d\n", temperature, valid, fault);
  }
  static bool previousReset = false;
  bool reset = digitalRead(FAULT_RESET_PIN) == LOW;
  decide(digitalRead(MANUAL_OPEN_PIN) == LOW, reset && !previousReset);
  previousReset = reset;
  moveOneStep(now);
}

Датчик читается раз в десять секунд. Пока вы наблюдаете за приводом, откройте последовательный порт: туда выводятся ошибки. Плавное движение организовано по таймеру, поэтому программа продолжает выполнять остальные действия между изменениями команды.

Первые опыты с форточкой

  1. Без тяги проверить запуск, направление движения и крайние положения. Убедиться, что сброс питания не вызывает недопустимого перемещения.
  2. Подать последовательность температур с небольшим шагом вверх и вниз. Проверить достижение полного открытия и закрытия, а также подавление малых колебаний.
  3. Отключить датчик: ошибка должна зафиксироваться. После восстановления показаний движение по температуре должно возобновиться только после подтверждения.
  4. Проверить переключатель ручного открытия и возврат к автоматическому режиму.
  5. С подключённой механикой проверить ток, нагрев, ограничители и возможность ручного освобождения створки. Программа без обратной связи не обнаруживает заклинивание.
  6. Проверить сценарии холода, жары, ветра и пропадания питания. Для хозяйства предусмотреть независимую защиту и оповещение, соответствующие последствиям отказа.

Когда поведение на столе стало понятным, подключите механику и повторите опыты. Особенно интересно проверить медленный нагрев: форточка должна постепенно доходить до нужного положения, а не ждать резкого скачка. Запишите, где появляются люфт, нагрузка и задержка, — эти наблюдения помогут довести конструкцию.

Что попробовать дальше

Интерфейс управления приводом описан в документации ESP32Servo, чтение DHT22 — в библиотеке Adafruit DHT, настройка кнопок — в документации GPIO Arduino-ESP32.

Измерение температуры и влажности в теплице поможет выбрать место датчика и увидеть, как меняются условия после проветривания.

Полив с учётом прогноза погоды — следующий проект, если захочется связать наблюдения за теплицей с другими задачами.

💬 Комментарии

Чтобы оставить комментарий, войдите или зарегистрируйтесь

Загрузка комментариев...

Похожие статьи