Микроконтроллер ESP32 — это мощный инструмент для создания умных устройств. В этой статье мы разберем практический проект на его основе: регулятор мощности с визуальным интерфейсом. Устройство позволяет плавно управлять напряжением на нагрузке (например, яркостью светодиодной ленты, скоростью двигателя, температурой паяльника) с помощью двух кнопок и отображать текущую мощность на OLED-экране.

Для чего это нужно?

  • Образовательная цель: Изучение основ ШИМ, работы с периферией ESP32 (кнопки, дисплей) и создания простого пользовательского интерфейса.

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

1. Аппаратная часть (Что нам понадобится)

  1. Плата ESP32 (любая, например, ESP32 DevKit V1).

  2. OLED-дисплей на чипе SSD1306 с интерфейсом I2C.

  3. N-канальный MOSFET-транзистор (например, IRFZ44N, IRLZ44N, 2N7000 или более мощный, в зависимости от нагрузки). Он выступает в роли электронного ключа.

  4. Две тактовые кнопки.

  5. Нагрузка для теста (например, 12В светодиодная лента + отдельный блок питания 12В).

  6. Соединительные провода и макетная плата.

  7. Резисторы: 10кОм (2 шт. для подтяжки кнопок) и, опционально, резистор на 100-470 Ом между пином ESP32 и затвором MOSFET для защиты от выбросов напряжения.

Схема подключения:

ESP32:
GPIO32 (MOSFET_PIN)  -> Затвор (G) MOSFET через резистор ~100-200 Ом
GPIO21 (SDA)         -> SDA дисплея
GPIO22 (SCL)         -> SCL дисплея
GPIO26 (BTN_UP)      -> Один контакт кнопки UP. Второй контакт -> +3.3V. Параллельно кнопке: резистор 10кОм к GND (подтяжка вниз).
GPIO27 (BTN_DOWN)    -> Аналогично кнопке DOWN.
3.3V                 -> VCC дисплея и кнопок
GND                  -> Общая земля (дисплей, кнопки, исток MOSFET, минус нагрузки)

MOSFET взят 2n7000:
Сток (D) MOSFET      -> Минус нагрузки (например, светодиодной ленты).
Плюс нагрузки        -> Плюс внешнего блока питания (например, +12V).
Минус блока питания  -> Общая земля (GND).

ВАЖНО по безопасности:

  • Если вы управляете нагрузкой с напряжением выше 5В (например, 12В, 24В, 220В), необходима гальваническая развязка (оптореле, симистор с оптодрайвером). Представленная схема с MOSFET подходит только для управления низковольтной нагрузкой, где цепь управления (ESP32) и цепь нагрузки имеют общую землю.

  • принципиальная схема ШИМ контроллера с экраном. (1 кнопка на схеме условно лишняя, на всякий случай для других проектов. (пин14))
  • Мощный MOSFET может сильно нагреваться. При больших токах используйте радиатор.

  • пример собранного устройства. Работоспособность проверена.

2. Детальный разбор программного кода (скетча)

Программа состоит из нескольких логических блоков.

2.1. Настройка и инициализация (блок setup())

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Подключаем библиотеки: Wire для работы с I2C, Adafruit_GFX и Adafruit_SSD1306 для управления дисплеем.

#define MOSFET_PIN 32
#define BTN_UP 26
#define BTN_DOWN 27

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

Adafruit_SSD1306 display(128, 64, &Wire, -1);
int pwmValue = 127; // Стартовое значение ШИМ (50%)

Создаем объект дисплея и переменную для хранения значения ШИМ (от 0 до 255).

void setup() {
  Serial.begin(115200);
  pinMode(MOSFET_PIN, OUTPUT);
  pinMode(BTN_UP, INPUT);
  pinMode(BTN_DOWN, INPUT);

Начинаем последовательный порт для отладки. Настраиваем пины: MOSFET — выход, кнопки — входы.

  ledcAttach(MOSFET_PIN, 5000, 8);
  ledcWrite(MOSFET_PIN, pwmValue);

Ключевой момент: Вместо стандартного analogWrite() ESP32 использует более гибкий LEDC (LED Control) для ШИМ.

  • ledcAttach(PIN, FREQUENCY, BIT_RESOLUTION) — привязывает пин к каналу ШИМ с частотой 5 кГц и разрядностью 8 бит (256 значений).

  • ledcWrite(PIN, VALUE) — устанавливает скважность ШИМ.

  Wire.begin(21, 22);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  // ... настройка текста
  Serial.println("Система запущена");
}

Инициализируем шину I2C на пинах 21 (SDA) и 22 (SCL), запускаем дисплей с адресом 0x3C и очищаем его.

2.2. Основной цикл (блок loop())

Цикл постоянно выполняет три задачи: опрос кнопок, обновление дисплея и небольшая задержка.

Опрос кнопок:

if (digitalRead(BTN_UP) == HIGH) {
    pwmValue = pwmValue + 10;
    if (pwmValue > 255) pwmValue = 255;
    ledcWrite(MOSFET_PIN, pwmValue);
    delay(200); // Простой антидребезг
}

При нажатии кнопки UP значение ШИМ увеличивается на 10. Функция delay(200) выполняет две роли: антидребезг (фильтрация механических колебаний контактов) и регулировка скорости изменения.

ВАЖНО: В реальных проектах для обработки кнопок лучше использовать библиотеки (Bounce2) или техники с отслеживанием времени (millis()), чтобы не блокировать работу системы.

Обновление дисплея:

display.clearDisplay();
display.setCursor(0,0);
display.print("MOSFET PWM Test");
// ... вывод значения и процентов
display.display();

Весь вывод на дисплей происходит в буфер. Команда display.display() отправляет содержимое буфера на экран.

Полный код