Простой секундомер на ESP32 и LCD-дисплее.

В данной статье описывается процесс создания простого, но точного секундомера, построенного на базе микроконтроллера ESP32 и жидкокристаллического (LCD) дисплея с интерфейсом I²C. Секундомер управляется кнопками "Старт", "Стоп" и "Сброс", предоставляя базовый функционал для измерения временных интервалов. Использование ESP32, благодаря его вычислительной мощности и встроенным функциям, позволяет реализовать точное измерение времени, а применение I²C LCD упрощает схему подключения и уменьшает количество используемых выводов микроконтроллера. Этот проект может быть полезен в качестве основы для более сложных систем хронометража или как учебный пример работы с ESP32, LCD-дисплеями и обработкой событий от кнопок.

Описание проекта секундомер на ESP32 и LCD-дисплее.

Описание проекта секундомер на ESP32 и LCD-дисплее.

Представленный проект секундомера на ESP32 использует LCD-дисплей с I²C интерфейсом для отображения времени. Функциональность секундомера включает в себя три основные операции: запуск/возобновление отсчета времени, остановку (паузу) и сброс.

  • Старт/Возобновление: Нажатие кнопки "Старт" инициирует отсчет времени или возобновляет его, если секундомер был ранее остановлен.
  • Стоп/Пауза: Нажатие кнопки "Стоп" приостанавливает отсчет времени.
  • Сброс: Повторное нажатие кнопки "Стоп" в режиме паузы приводит к сбросу секундомера в исходное состояние (00:00:000).

Для точного отсчета времени используется функция millis() из среды Arduino. Эта функция возвращает количество миллисекунд, прошедших с момента запуска программы на ESP32. Несмотря на то, что ESP32 позволяет выводить до четырех знаков после запятой (десятитысячные доли секунды), в данном проекте для удобства отображения на LCD ограничимся тремя знаками (миллисекундами).

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

Для сборки секундомера потребуются следующие компоненты:

Наименование компонента Количество Примечание
1 Плата ESP32 1 Любая модель ESP32 с достаточным количеством выводов.
2 16x2 I²C LCD-дисплей 1 Дисплей с интерфейсом I²C для упрощения подключения.
3 Тактовая кнопка 2 Для кнопок "Старт" и "Стоп/Сброс".
4 Соединительные провода 10
5 Макетная плата (Breadboard) 1 Для удобного прототипирования без пайки.

Схема подключения и аппаратная часть.

Схема подключения компонентов секундомера представлена ниже.

Схема подключения компонентов секундомера представлена ниже.


  • Подключение кнопок:
    • Кнопка "Старт" подключается к цифровому выводу 18 ESP32.
    • Кнопка "Стоп/Сброс" подключается к цифровому выводу 19 ESP32.
    • Важно: Используются внутренние подтягивающие резисторы микроконтроллера (INPUT_PULLUP), поэтому при нажатии кнопки на выводе будет LOW.
  • Подключение LCD-дисплея (I²C):
    • SDA дисплея подключается к выводу SDA ESP32 (обычно GPIO21).
    • SCL дисплея подключается к выводу SCL ESP32 (обычно GPIO22).
    • VCC дисплея подключается к источнику питания 5V.
    • GND дисплея подключается к общему проводу (GND) ESP32.

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

Дополнение: I2C интерфейс. I2C (Inter-Integrated Circuit) — это последовательная шина данных, используемая для связи между микроконтроллерами и периферийными устройствами. Она требует всего два провода (SDA для данных и SCL для тактового сигнала), что значительно упрощает подключение по сравнению с параллельными интерфейсами. Адрес устройства I2C (в данном случае 0x27) указывается в коде и должен соответствовать адресу, установленному на LCD-модуле (обычно настраивается перемычками на плате модуля).

Программный код (с комментариями):

/*
*  Простой секундомер на ESP32 и LCD-дисплее.
* https://arduino-tex.ru/news/205/prostoi-sekundomer-na-esp32-i-lcd-displee.html
*/
#include <Wire.h>               // Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  // Библиотека для работы с I2C LCD
// Инициализация LCD-дисплея по адресу 0x27 (16 столбцов, 2 строки).
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Пины кнопок
const int startButtonPin = 18;
const int stopButtonPin = 19;
// Состояния таймера
enum TimerState { IDLE,
                  RUNNING,
                  PAUSED };
TimerState timerState = IDLE;  // Изначальное состояние - ожидание
unsigned long startTime = 0;    // Время старта/возобновления
unsigned long elapsedTime = 0;  // Прошедшее время
bool flag_pses = false;
void setup() {
  lcd.init();       // Инициализация LCD
  lcd.backlight();  // Включение подсветки
  lcd.clear();      // Очистка экрана
  lcd.setCursor(0, 0);
  lcd.print("Arduino-tex.ru");
  delay(1000);
  Serial.begin(115200);  // Инициализация Serial-порта (для отладки)
  // Настройка пинов кнопок как входы с подтяжкой
  pinMode(startButtonPin, INPUT_PULLUP);
  pinMode(stopButtonPin, INPUT_PULLUP);
}
void loop() {
  switch (timerState) {
    case IDLE:
      // Отображение "Press Start" и очистка второй строки
      if (!flag_pses) {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Press Start");
        lcd.setCursor(0, 1);
        lcd.print("                ");  // Очистка
        flag_pses = true;
      }
      // Ожидание нажатия кнопки "Старт"
      if (digitalRead(startButtonPin) == LOW) {
        delay(50);                                                 // Задержка для подавления дребезга контактов
        while (digitalRead(startButtonPin) == LOW) { delay(10); }  // Ожидание отпускания кнопки
        startTime = millis();  // Фиксация времени старта
        elapsedTime = 0;       // Сброс прошедшего времени
        timerState = RUNNING;  // Переход в состояние "Работает"
        lcd.clear();
      }
      break;
    case RUNNING:
      // Обновление прошедшего времени
      elapsedTime = millis() - startTime;
      displayTime(elapsedTime);  // Отображение времени
      // Остановка при нажатии кнопки "Стоп"
      if (digitalRead(stopButtonPin) == LOW) {
        delay(50);
        while (digitalRead(stopButtonPin) == LOW) { delay(10); }
        elapsedTime = millis() - startTime;  // Фиксация времени
        timerState = PAUSED;                 // Переход в состояние "Пауза"
      }
      break;
    case PAUSED:
      // Отображение времени в режиме паузы
      displayTime(elapsedTime);
      // Возобновление при нажатии "Старт"
      if (digitalRead(startButtonPin) == LOW) {
        delay(50);
        while (digitalRead(startButtonPin) == LOW) { delay(10); }
        startTime = millis() - elapsedTime;  // Корректировка времени старта
        timerState = RUNNING;
        lcd.clear();
      }
      // Сброс при нажатии "Стоп"
      else if (digitalRead(stopButtonPin) == LOW) {
        delay(50);
        while (digitalRead(stopButtonPin) == LOW) { delay(10); }
        timerState = IDLE;  // Возврат в состояние "Ожидание"
        flag_pses = false;
        lcd.clear();
      }
      break;
  }
}
// Функция отображения времени
void displayTime(unsigned long timeInMillis) {
  unsigned int minutes = timeInMillis / 60000;
  unsigned int seconds = (timeInMillis % 60000) / 1000;
  unsigned int milliseconds = timeInMillis % 1000;
  // Форматирование строки времени (MM:SS:MMM)
  char timeStr[10];
  sprintf(timeStr, "%02u:%02u:%03u", minutes, seconds, milliseconds);
  // Вывод времени на первую строку LCD
  lcd.setCursor(0, 0);
  lcd.print(timeStr);
  lcd.setCursor(0, 1);
  lcd.print("Arduino-tex.ru");
  // Вывод времени в Serial-порт (для отладки)
  Serial.println(timeStr);
}

Работа секундомера.

Программа работает в цикле, отслеживая состояние секундомера и реагируя на нажатия кнопок.

  1. Состояние IDLE (Ожидание): На LCD отображается сообщение "Press Start". Программа ожидает нажатия кнопки "Старт".
  2. Состояние RUNNING (Работает): После нажатия кнопки "Старт" программа фиксирует текущее время (с помощью millis()) и начинает отсчет прошедшего времени. Время отображается на LCD в формате MM:SS:MMM.
  3. Состояние PAUSED (Пауза): При нажатии кнопки "Стоп" отсчет времени приостанавливается, и текущее значение времени остается на дисплее.
  4. Возобновление и Сброс:
    • Нажатие кнопки "Старт" в состоянии PAUSED возобновляет отсчет времени. При этом корректируется начальное время (startTime), чтобы обеспечить непрерывный отсчет.
    • Нажатие кнопки "Стоп" в состоянии PAUSED сбрасывает секундомер в состояние IDLE.

Работа секундомера.

Дополнение: Подавление дребезга контактов. При нажатии и отпускании механических кнопок возникает так называемый "дребезг контактов" - кратковременные ложные срабатывания. Для борьбы с этим явлением в коде используется задержка (delay(50)) после обнаружения нажатия кнопки. Это позволяет игнорировать кратковременные изменения сигнала.

Заключение.

В этой статье был представлен подробный обзор создания простого и точного секундомера с использованием микроконтроллера ESP32, I²C LCD-дисплея и кнопок управления. Проект демонстрирует основные принципы работы с ESP32, подключения периферийных устройств по интерфейсу I²C, обработки событий от кнопок и реализации логики секундомера. Полученный секундомер обладает достаточной точностью для большинства бытовых задач и может быть легко модифицирован для добавления новых функций, таких как сохранение результатов, установка таймера обратного отсчета или управление внешними устройствами. Данный проект может послужить отправной точкой для разработки более сложных измерительных приборов на базе ESP32.

Полезные ссылки:


Понравился проект Простой секундомер на ESP32 и LCD-дисплее? Не забудь поделиться с друзьями в соц. сетях.

А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в Telegram.

Спасибо за внимание!

Технологии начинаются с простого!

Фотографии к статье

Файлы для скачивания

Код секундомера на ESP32 Код секундомера на ESP32.ino5 Kb 33 Скачать

Комментарии

Ваше Имя*


Разработка проектов