Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Надежный кухонный таймер на Arduino с LCD-дисплеем

Компоненты и материалы

Компонент Количество
Arduino UNO 1
Adafruit Standard LCD 16x2 (белый на синем) 1
Тактильные кнопки 12 мм (SparkFun) 4
Резисторы 10 кОм 4
Резисторы 220 Ом (в списке 221 Ом) 2
Однооборотный потенциометр 100 кОм 1
Пьезо-зуммер 1
Плата для прототипирования и перемычки 1

О проекте

Собственный кухонный таймер — отличный проект для изучения работы с кнопками, дисплеем и управлением временем. Устройство имеет четыре режима работы:

Принцип работы

Каждая кнопка подключена через подтягивающий резистор 10 кОм к GND. При нажатии контакт замыкается на +5V. Опрос кнопок осуществляется в loop() с детектированием фронтов (изменения состояния). Для кнопки Reset реализовано определение длинного нажатия (счетчик циклов).

Управление режимами — switch(currentMode). Блок «Time management» считает оставшееся время через now() (библиотека TimeLib) и переключает в RINGING. Блок «LCD management» обновляет дисплей согласно режиму.

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

Используйте любую плату для прототипирования. Зуммер можно разместить под проводами (см. фото/видео). На схеме показаны подключения LCD (пины 12,11,5,4,3,2), кнопок (пины 6,7,8,9), зуммера (пин 10) и потенциометра контраста.

Код (Arduino Kitchen Timer v1.0)

Требуются библиотеки: LiquidCrystal.h (стандартная) и TimeLib.h (Paul Stoffregen, установить через Library Manager или ZIP).

/**************************************************
 * Arduino Kitchen Timer v1.0 - 27.01.2016
 * By Angelo Fiorillo (Rome, IT)
 * Лицензия: GNU GPL v3+
 **************************************************/
#include <LiquidCrystal.h>
#include <TimeLib.h> // Фикс ошибки «'now' was not declared»

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int buzzerPin = 10;
const int resetButtonPin = 6;      // S4
const int startStopButtonPin = 7;  // S3
const int downButtonPin = 8;       // S2
const int upButtonPin = 9;         // S1

// Настройки таймера
int setupHours = 0, setupMinutes = 0, setupSeconds = 0;
time_t setupTime = 0;
int currentHours = 0, currentMinutes = 0, currentSeconds = 0;
time_t currentTime = 0, startTime = 0, elapsedTime = 0;

// Состояния кнопок
int resetButtonState = LOW, startStopButtonState = LOW;
int upButtonState = LOW, downButtonState = LOW;
int resetButtonPrevState = LOW, startStopButtonPrevState = LOW;
int upButtonPrevState = LOW, downButtonPrevState = LOW;

bool resetButtonPressed = false, resetButtonLongPressed = false;
bool startStopButtonPressed = false, upButtonPressed = false, downButtonPressed = false;

// Режимы
const int MODE_IDLE = 0;
const int MODE_SETUP = 1;
const int MODE_RUNNING = 2;
const int MODE_RINGING = 3;
int currentMode = MODE_IDLE;

int dataSelection = 0; // 0=часы, 1=минуты, 2=секунды (в SETUP)
long resetButtonLongPressCounter = 0;

void setup() {
  lcd.begin(16, 2);
  pinMode(resetButtonPin, INPUT);
  pinMode(startStopButtonPin, INPUT);
  pinMode(upButtonPin, INPUT);
  pinMode(downButtonPin, INPUT);
  pinMode(buzzerPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // Сброс флагов нажатий
  startStopButtonPressed = false;
  upButtonPressed = false;
  downButtonPressed = false;

  /* --- Кнопка Reset (S4) с длинным нажатием --- */
  resetButtonPressed = false;
  resetButtonLongPressed = false;
  resetButtonState = digitalRead(resetButtonPin);
  if (resetButtonState != resetButtonPrevState) {
    resetButtonPressed = (resetButtonState == HIGH);
    resetButtonPrevState = resetButtonState;
  } else {
    if (resetButtonState == HIGH) {
      resetButtonLongPressCounter++;
      if (resetButtonLongPressCounter == 100) { // порог длинного нажатия
        resetButtonPressed = false;
        resetButtonLongPressed = true;
        resetButtonLongPressCounter = 0;
      }
    } else {
      resetButtonLongPressCounter = 0;
      resetButtonPressed = false;
      resetButtonLongPressed = false;
    }
  }

  /* --- Кнопка Start/Stop (S3) --- */
  startStopButtonState = digitalRead(startStopButtonPin);
  if (startStopButtonState != startStopButtonPrevState) {
    startStopButtonPressed = (startStopButtonState == HIGH);
    startStopButtonPrevState = startStopButtonState;
  }

  /* --- Кнопка Down (S2) --- */
  downButtonState = digitalRead(downButtonPin);
  if (downButtonState != downButtonPrevState) {
    downButtonPressed = (downButtonState == HIGH);
    downButtonPrevState = downButtonState;
  }

  /* --- Кнопка Up (S1) --- */
  upButtonState = digitalRead(upButtonPin);
  if (upButtonState != upButtonPrevState) {
    upButtonPressed = (upButtonState == HIGH);
    upButtonPrevState = upButtonState;
  }

  /* --- МАШИНА СОСТОЯНИЙ --- */
  switch (currentMode) {
    case MODE_IDLE:
      if (resetButtonPressed) Reset();
      if (resetButtonLongPressed) currentMode = MODE_SETUP;
      if (startStopButtonPressed) {
        currentMode = (currentMode == MODE_IDLE) ? MODE_RUNNING : MODE_IDLE;
        if (currentMode == MODE_RUNNING) startTime = now(); // СТАРТ
      }
      break;

    case MODE_SETUP:
      if (resetButtonPressed) { // Выход из настройки
        setupTime = setupSeconds + 60L * setupMinutes + 3600L * setupHours;
        currentHours = setupHours; currentMinutes = setupMinutes; currentSeconds = setupSeconds;
        dataSelection = 0; currentMode = MODE_IDLE;
      }
      if (startStopButtonPressed) { // Выбор поля
        dataSelection++; if (dataSelection == 3) dataSelection = 0;
      }
      if (downButtonPressed) { // Уменьшение
        switch (dataSelection) {
          case 0: setupHours--; if (setupHours == -1) setupHours = 99; break;
          case 1: setupMinutes--; if (setupMinutes == -1) setupMinutes = 59; break;
          case 2: setupSeconds--; if (setupSeconds == -1) setupSeconds = 59; break;
        }
      }
      if (upButtonPressed) { // Увеличение
        switch (dataSelection) {
          case 0: setupHours++; if (setupHours == 100) setupHours = 0; break;
          case 1: setupMinutes++; if (setupMinutes == 60) setupMinutes = 0; break;
          case 2: setupSeconds++; if (setupSeconds == 60) setupSeconds = 0; break;
        }
      }
      break;

    case MODE_RUNNING:
      if (startStopButtonPressed) currentMode = MODE_IDLE; // Стоп
      if (resetButtonPressed) { Reset(); currentMode = MODE_IDLE; } // Сброс
      break;

    case MODE_RINGING:
      if (resetButtonPressed || startStopButtonPressed || downButtonPressed || upButtonPressed)
        currentMode = MODE_IDLE; // Любая кнопка гасит звонок
      break;
  }

  /* --- РАСЧЕТ ВРЕМЕНИ --- */
  switch (currentMode) {
    case MODE_IDLE: case MODE_SETUP: break; // ничего не делаем
    case MODE_RUNNING:
      currentTime = setupTime - (now() - startTime);
      if (currentTime <= 0) currentMode = MODE_RINGING;
      break;
    case MODE_RINGING:
      analogWrite(buzzerPin, 20); delay(20);
      analogWrite(buzzerPin, 0); delay(40); // Пик-пик
      break;
  }

  /* --- УПРАВЛЕНИЕ LCD --- */
  lcd.setCursor(0, 0);
  switch (currentMode) {
    case MODE_IDLE:
      lcd.print("Timer ready ");
      lcd.setCursor(0, 1);
      lcd.print(currentHours); lcd.print(" ");
      lcd.print(currentMinutes); lcd.print(" ");
      lcd.print(currentSeconds); lcd.print(" ");
      break;
    case MODE_SETUP:
      lcd.print("Setup mode: ");
      switch (dataSelection) {
        case 0: lcd.print("HRS "); break;
        case 1: lcd.print("MINS"); break;
        case 2: lcd.print("SECS"); break;
      }
      lcd.setCursor(0, 1);
      lcd.print(setupHours); lcd.print(" ");
      lcd.print(setupMinutes); lcd.print(" ");
      lcd.print(setupSeconds); lcd.print(" ");
      break;
    case MODE_RUNNING:
      lcd.print("Counting down...");
      lcd.setCursor(0, 1);
      if (hour(currentTime) < 10) lcd.print("0");
      lcd.print(hour(currentTime)); lcd.print(":");
      if (minute(currentTime) < 10) lcd.print("0");
      lcd.print(minute(currentTime)); lcd.print(":");
      if (second(currentTime) < 10) lcd.print("0");
      lcd.print(second(currentTime));
      break;
    case MODE_RINGING:
      lcd.print(" RING-RING! ");
      lcd.setCursor(0, 1); lcd.print(" ");
      break;
  }
  delay(10);
}

void Reset() {
  currentMode = MODE_IDLE;
  currentHours = setupHours; currentMinutes = setupMinutes; currentSeconds = setupSeconds;
}

Советы по сборке

Производственный процесс

  1. Умный датчик полива «Thirst Alert» на Arduino — DIY сигнализация засухи для растений
  2. Создание осциллографа на Arduino Nano с дисплеем Nokia 5110 (20 кГц): простое DIY-руководство
  3. Умные шторы: автоматическое управление светом на Arduino с солнечной энергией
  4. Итальянские словесные часы на Arduino Nano, NeoPixel, LCD и RTC
  5. Сборка надежного таймера обратного отсчета на Arduino с 7-сегментным дисплеем SparkFun
  6. Надежный счетчик кВт·ч на Sigfox с Arduino MKR Fox 1200
  7. Bluetooth-монитор температуры на Arduino Nano с NTC-термистором
  8. Бесконтактный жестовый замок: APDS-9960 + Arduino для безопасного доступа
  9. Гальванически разделённый аналоговый вход для Arduino на LM331 и оптопаре 4N25
  10. Точный тест времени реакции на Arduino UNO