Перевод статьи Build a Smart Cooker Whistle Counter Using ESP32 — Circuit Digest.

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

В этом руководстве мы собираем счётчик свистков на ESP32. Устройство слушает всплески звука и само считает свистки, пока вы занимаетесь своими делами. Оно подключается к облачной панели, где задаётся нужное число свистков, включается и выключается прослушивание, а по достижении цели прилетает мгновенное уведомление в мессенджер.

Как это работает#

Блок-схема работы программы счётчика свистков

Логика работы программы

Основной датчик — электретный микрофонный модуль MAX4466. Он ловит звуковые волны от скороварки и превращает их в меняющееся аналоговое напряжение; встроенный операционный усилитель усиливает и обрабатывает сигнал, смещённый относительно опорной точки 1,65 В. Готовый аналоговый сигнал подаётся на вход АЦП ESP32.

ESP32 читает звук своим 12-битным АЦП, который переводит напряжение в значения от 0 до 4095. Ослабление АЦП выставлено в ADC_11db — это позволяет безопасно измерять размах до 3,3 В без ограничения сигнала.

Чтобы корректно измерить уровень шума, ESP32 слушает микрофон окнами по 50 мс. В каждом окне он запоминает максимум и минимум напряжения и считает размах:

ΔV = Vmax − Vmin

Затем размах переводится в понятный уровень звука в децибелах:

дБ = 41,52 × log₁₀(ΔV) + 64,02

Калибровка MAX4466#

Калибровать модуль обязательно, иначе он будет показывать завышенные или заниженные значения. Загрузите прошивку и подстроечным резистором на плате выставьте уровень фонового шума в 30 дБ.

Что понадобится#

№КомпонентМодельКол-во
1МикроконтроллерESP32 Dev Kit1
2Микрофонный усилительMAX44661

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

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

Схема счётчика свистков

Вывод микрофонного модуляESP32
OUTGPIO 34
GNDGND
VCC3,3 В

Настройка облачной панели#

Проект использует облако CircuitDigest — там живёт панель управления и оттуда же уходит уведомление в WhatsApp.

Шаг 1. Регистрация. Зарегистрируйтесь или войдите в CircuitDigest Cloud.

Шаг 2. Новое устройство. На вкладке Dashboard выберите слева раздел устройств, нажмите Add New Device и дайте проекту имя — например, «Cooker Whistle Monitoring and Alerting System».

Добавление нового устройства в панели

Создаём устройство

Шаг 3–4. Переменные. В разделе Variables выберите созданное устройство и добавьте четыре переменные с направлением bidirectional:

ПеременнаяКлючНазначение
NO OF WHISTLEanalog-input-1целевое число свистков
SETanalog-input-2включение и выключение прослушивания
WHISTLE COUNTanalog-input-3текущий счёт
LIVE DBanalog-input-4уровень звука в реальном времени
Список переменных в облачной панели

Четыре переменные проекта

Шаг 5. Виджеты. В разделе Dashboard нажмите Add Widget, выберите SliderWidget, укажите устройство, имя и переменную. Повторите для остальных трёх виджетов.

Добавление виджета на панель

Собираем панель из виджетов

Шаг 6. Уведомления. На вкладке Home найдите раздел уведомлений WhatsApp, привяжите номер телефона и подтвердите его кодом из СМС.

Настройка отправки уведомлений

Привязка номера для уведомлений

Как работает программа#

При включении ESP32 настраивает GPIO34 как аналоговый вход, выставляет ослабление АЦП в ADC_11db, поднимает Wi-Fi и подключается к облаку.

В основном цикле параллельно идут две задачи. Первая — опрос микрофона: ESP32 непрерывно сэмплирует MAX4466 окнами по 20 мс, считает размах и переводит его в децибелы. Вторая — приём команд с панели через фоновые колбэки CDcloud.loop(): ползунок (analog-input-1) обновляет целевое число свистков, переключатель (analog-input-2) включает и выключает прослушивание.

Когда прослушивание активно и уровень звука превышает WHISTLE_ON_DB (60 дБ) не меньше MIN_WHISTLE_MS (300 мс), а затем падает ниже WHISTLE_OFF_DB (50 дБ), свисток засчитывается: счётчик увеличивается, новое значение уходит в облако, и включается пауза, защищающая от повторного срабатывания на эхо. Как только счёт достигает цели, уходит POST-запрос с уведомлением, прослушивание выключается, а переключатель на панели возвращается в положение OFF.

Разбор кода#

Код написан в Arduino IDE.

pinMode(AUDIO_PIN, INPUT);
analogSetAttenuation(ADC_11db);
CDcloud.subscribe(KEY_TARGET_SET, onTargetSlider);
CDcloud.subscribe(KEY_LISTEN_SW, onListenSwitch);
if (!CDcloud.begin(WIFI_SSID, WIFI_PASS, DEVICE_ID, CONNECTION_KEY, API_KEY)) { ESP.restart(); }
publishWithRetry(KEY_LISTEN_SW, 0.0f);

При старте GPIO34 настраивается как аналоговый вход, ослабление АЦП выставляется в 11 дБ. Затем программа подписывается на облачные ключи ползунка (KEY_TARGET_SET) и переключателя (KEY_LISTEN_SW), а CDcloud.begin() поднимает Wi-Fi и соединение с облаком.

float readDBLevel() {
  // сэмплируем MAX4466 окном 20 мс и находим размах сигнала
  float voltage = (peakToPeak * V_REF) / ADC_RESOLUTION;
  float rawDb = (41.52 * log10(voltage)) + 64.02;
  return (rawDb < 30.0 || !lastReadingValid) ? 30.0 : rawDb;
}

Выход MAX4466 сэмплируется окнами по 20 мс, размах переводится в напряжение и дальше в децибелы по логарифмической формуле. Значения ниже 30 дБ подрезаются, чтобы нормализовать фоновый шум. Раз в секунду текущий уровень публикуется в облако для отображения на панели.

CDcloud.loop(); // обработчики обновляют targetWhistles и переключают isListening

void onTargetSlider(float v) { targetWhistles = (int)v; }
void onListenSwitch(float v) { isListening = (bool)v; whistleCount = 0; }

if (WiFi.status() != WL_CONNECTED) ESP.restart();

Фоновый обработчик CDcloud.loop() непрерывно разбирает входящие пакеты телеметрии. Движение ползунка вызывает onTargetSlider() и обновляет цель, а переключатель — onListenSwitch(), который заодно обнуляет счётчик при включении. Если Wi-Fi отвалился, устройство просто перезагружается и восстанавливает связь само.

if (isListening && !inWhistle && db > WHISTLE_ON_DB && now > cooldownUntilMs) {
  inWhistle = true; whistleStartMs = now;
} else if (inWhistle && db < WHISTLE_OFF_DB) {
  inWhistle = false;
  if ((now - whistleStartMs) >= MIN_WHISTLE_MS) {
    whistleCount++;
    cooldownUntilMs = now + WHISTLE_COOLDOWN_MS; // WHISTLE_COOLDOWN_MS = 10000UL
    CDcloud.publish(KEY_LIVE_COUNT, (float)whistleCount);
  }
}

Вот сама детекция. Когда прослушивание включено, превышение WHISTLE_ON_DB отмечает возможное начало свистка. Если сигнал продержался выше порога не меньше 300 мс и затем упал ниже WHISTLE_OFF_DB, свисток считается состоявшимся: счётчик растёт, значение уходит в облако, и на 10 секунд выставляется блокировка — она не даёт затухающему свистку и эху насчитать лишнего.

Обратите внимание на приём: два разных порога на включение и выключение — это гистерезис. Без него сигнал, болтающийся возле единственного порога, дал бы десяток ложных срабатываний.

if (whistleCount >= targetWhistles) {
  sendWhatsAppAlert(whistleCount); // HTTP POST на www.circuitdigest.cloud:443
  isListening = false;
  CDcloud.publish(KEY_LISTEN_SW, 0.0f); // возвращаем переключатель в OFF
}

Когда счёт достиг цели, устройство отправляет JSON с итоговым числом свистков и уходит из режима прослушивания, чтобы случайный шум не породил дубль уведомления.

Результат#

Работа счётчика свистков на кухне

Испытания на настоящей скороварке

Счётчик проверили на обычной скороварке на кухне. На панели ползунком задаётся нужное число свистков (от 1 до 20) и включается прослушивание. Устройство непрерывно измеряет уровень звука, считает свистки и обновляет счёт на панели. Как только заданный предел достигнут, оно отправляет уведомление на телефон и прекращает слушать.

Что может пойти не так#

ПроблемаРешение
Как откалибровать MAX4466Поверните подстроечный резистор на обратной стороне модуля против часовой стрелки, чтобы увеличить усиление, или по часовой, чтобы уменьшить
ESP32 не подключается к Wi-FiПроверьте правильность имени сети и пароля в коде
В тихой комнате показывает около 80 дБ даже после подстройкиЗамените модуль MAX4466 на новый и откалибруйте заново
Свисток не детектируетсяУменьшите значения WHISTLE_ON_DB и WHISTLE_OFF_DB в коде, чтобы поднять чувствительность

Полный исходный код с логикой сэмплирования MAX4466, интеграцией с облаком и функцией отправки уведомления выложен в репозитории проекта — ссылка есть в оригинальной статье.