驴友花雕 发表于 2025-5-29 18:19:17

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

本帖最后由 驴友花雕 于 2025-6-7 06:51 编辑





驴友花雕 发表于 2025-5-29 18:26:18

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

该 Arduino 项目提供了一个用户友好、高度可定制的厨房计时器,具有所有基本功能。


驴友花雕 发表于 2025-5-29 18:28:33

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

## 步骤1:描述

厨房计时器是一种简单、用户友好的设备,可以倒计时设定的时间,并在烹饪或烘焙任务完成时通过声音或视觉信号提醒用户。

大多数商用厨房计时器的设置和操作都相对复杂,因为人们更加关注许多不必要的选项和功能,而忽略了操作的简单性,而这对于具有此用途的计时器来说是一个基本特征。

在这个项目中,我将向您展示一种非常简单的方法来制作厨房计时器,它操作极其简单,但几乎具有现代商用计时器的所有功能。



驴友花雕 发表于 2025-5-29 18:31:25

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

## 第 2 步:零件

要制造该设备,您只需要几个组件:

- Arduino Nano微控制器板

- TM1637 - 4 位,7 段显示

-10K电位器

- 三个按钮

- 和蜂鸣器



驴友花雕 发表于 2025-5-29 18:33:05

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

## 步骤3:功能和能力

首先,我将解释如何操作该设备及其功能和性能。为了简单起见,时间设置使用一个简单的电位器,分为三个范围:0 至 60 分钟、0 至 30 分钟和 0 至 10 分钟。绿色按钮启动倒计时,黄色按钮可随时重置设备,红色按钮可选择所需的范围。

当设备打开时,屏幕上会出现时间,该时间由电位器的位置决定。

开机默认范围为 60 分钟。现在,使用电位器简单快速地设置所需时间,例如 7 分钟,然后按下启动按钮。计时器开始倒计时,显示屏中间的两个点开始闪烁。如果在此过程中的任何时候按下重置按钮,时间将恢复到原始设置状态。蜂鸣器会发出间歇性提示音,显示屏上的数字(在本例中为四个零)也会交替闪烁,表示设置时间已结束。这种情况会持续到我们按下重置按钮,之后设备即可再次运行。我们还来了解一下 RANGE 按钮的功能。

按下按钮后,屏幕上会显示设定范围两秒钟,然后显示该范围内的定时器值。使用此选项,我们可以更精确、更轻松地设置更短的时间间隔。正如您在说明中所见,此定时器的设置精度目前为 30 秒,因为对于厨房定时器来说,这已经足够了。







驴友花雕 发表于 2025-5-29 18:34:57

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

## 步骤4:代码说明

但是,根据需要,它可以是 10 秒、5 秒甚至 1 秒,并在代码中设置:

#define QUANTIZE_INTERVAL 30 //(1 到 60 秒)

至于代码,我试图使其尽可能灵活且易于修改,因此只需进行最少的更改,我们就可以创建一个自定义计时器来满足我们自己的要求。

简而言之,正如您所见,所有定时器参数都可以更改。例如,前面提到的 QUANTIZE_INTERVAL、POT_SMOOTHING、POT_READ_DELAY、报警频率以及开启/关闭时间、定时器范围的数量和持续时间,甚至显示屏的亮度。



驴友花雕 发表于 2025-5-29 18:36:59

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

## 步骤5:结论、原理图和代码

最后是简短的总结。总而言之,这个 Arduino 项目提供了一个用户友好、高度可定制的厨房定时器,具备所有必备功能,证明了有效的计时并不需要不必要的复杂性。







驴友花雕 发表于 2025-5-29 18:38:33

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

项目代码

//-----------------------------------------------------
// Kitchen Timer with TM1637 Display
// by: mircemk
// License: GNU GPl 3.0
// Created: April 2025
//-----------------------------------------------------


#include <TM1637Display.h>

// Pin definitions
#define CLK 2
#define DIO 3
#define POT_PIN A0
#define START_BUTTON 4
#define RESET_BUTTON 5
#define BUZZER_PIN 6
#define RANGE_BUTTON 7

// Constants
#define QUANTIZE_INTERVAL 30   
#define POT_SMOOTHING 30      
#define POT_READ_DELAY 50      
#define ALARM_FREQ 500         
#define ALARM_ON_TIME 200      
#define ALARM_OFF_TIME 200      
#define COLON_ON_TIME 500      
#define COLON_OFF_TIME 500   
#define RANGE_DISPLAY_TIME 1000
#define BUTTON_DEBOUNCE_TIME 300

// Timer ranges in seconds
const int TIMER_RANGES[] = {600, 1800, 3600};// 10min, 30min, 60min
const int NUM_RANGES = 3;

// Display instance
TM1637Display display(CLK, DIO);

// Variables
unsigned long previousMillis = 0;
const long interval = 1000;   
bool timerRunning = false;
int remainingTime = 0;         
bool colonState = true;         
unsigned long lastBuzzTime = 0;
unsigned long lastColonToggle = 0;
bool alarmOn = false;
bool displayOn = true;         
int lastDisplayedTime = -1;   
unsigned long lastPotRead = 0;
unsigned long lastDisplayFlash = 0;
int currentRangeIndex = 2;      // Start with 60min range (index 2)
unsigned long rangeDisplayStartTime = 0;
bool showingRange = false;      
unsigned long lastRangeButtonPress = 0;

// State enumeration
enum TimerState {
IDLE,
SHOWING_RANGE,
RUNNING,
ALARMING
};

TimerState currentState = IDLE;

void setup() {
pinMode(START_BUTTON, INPUT_PULLUP);
pinMode(RESET_BUTTON, INPUT_PULLUP);
pinMode(RANGE_BUTTON, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);

display.setBrightness(0x0a);
updateDisplay(quantizeTime(readSmoothedPot()));
}

void loop() {
unsigned long currentMillis = millis();

switch(currentState) {
    case SHOWING_RANGE:
      // Stay in range display mode until time elapsed
      if (currentMillis - rangeDisplayStartTime >= RANGE_DISPLAY_TIME) {
      currentState = IDLE;
      lastDisplayedTime = -1;// Force pot reading update
      } else {
      // Keep showing range
      displayRange(TIMER_RANGES);
      return;// Skip all other processing while showing range
      }
      break;
      
    case IDLE:
      // Handle range button
      if (digitalRead(RANGE_BUTTON) == LOW) {
      if (currentMillis - lastRangeButtonPress >= BUTTON_DEBOUNCE_TIME) {
          currentRangeIndex = (currentRangeIndex + 1) % NUM_RANGES;
          rangeDisplayStartTime = currentMillis;
          lastRangeButtonPress = currentMillis;
          currentState = SHOWING_RANGE;
          displayRange(TIMER_RANGES);
          return;// Exit loop immediately after changing to range display
      }
      }
      
      // Handle potentiometer input
      if (currentMillis - lastPotRead > POT_READ_DELAY) {
      lastPotRead = currentMillis;
      int potTime = quantizeTime(readSmoothedPot());
      if (potTime != lastDisplayedTime) {
          colonState = true;
          updateDisplay(potTime);
          lastDisplayedTime = potTime;
      }
      }
      
      // Handle start button
      if (digitalRead(START_BUTTON) == LOW) {
      delay(50);
      if (digitalRead(START_BUTTON) == LOW) {
          remainingTime = quantizeTime(readSmoothedPot());
          currentState = RUNNING;
          previousMillis = currentMillis;
          lastDisplayedTime = -1;
          colonState = true;
          lastColonToggle = currentMillis;
      }
      }
      break;
      
    case RUNNING:
      // Handle colon blinking
      if (colonState && (currentMillis - lastColonToggle >= COLON_ON_TIME)) {
      colonState = false;
      lastColonToggle = currentMillis;
      updateDisplay(remainingTime);
      }
      else if (!colonState && (currentMillis - lastColonToggle >= COLON_OFF_TIME)) {
      colonState = true;
      lastColonToggle = currentMillis;
      updateDisplay(remainingTime);
      }
      
      // Update timer
      if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if (remainingTime > 0) {
          remainingTime--;
          updateDisplay(remainingTime);
      }
      if (remainingTime == 0) {
          currentState = ALARMING;
      }
      }
      
      // Check reset button
      if (digitalRead(RESET_BUTTON) == LOW) {
      delay(50);
      if (digitalRead(RESET_BUTTON) == LOW) {
          resetTimer();
      }
      }
      break;
      
    case ALARMING:
      handleAlarm();
      if (digitalRead(RESET_BUTTON) == LOW) {
      delay(50);
      if (digitalRead(RESET_BUTTON) == LOW) {
          resetTimer();
      }
      }
      break;
}
}

void displayRange(int rangeInSeconds) {
int minutes = rangeInSeconds / 60;
uint8_t segments;

segments = display.encodeDigit(minutes / 10);
segments = display.encodeDigit(minutes % 10) | 0x80;// Force colon on
segments = display.encodeDigit(0);
segments = display.encodeDigit(0);

display.setSegments(segments);
}

int readSmoothedPot() {
long total = 0;
for (int i = 0; i < POT_SMOOTHING; i++) {
    total += analogRead(POT_PIN);
    delay(1);
}
int average = total / POT_SMOOTHING;
return map(average, 0, 1023, 0, TIMER_RANGES);
}

int quantizeTime(int seconds) {
int quantized = (seconds / QUANTIZE_INTERVAL) * QUANTIZE_INTERVAL;
return constrain(quantized, 0, TIMER_RANGES);
}

void updateDisplay(int timeInSeconds) {
if (currentState == ALARMING && !displayOn) {
    display.clear();
    return;
}

int minutes = timeInSeconds / 60;
int seconds = timeInSeconds % 60;

uint8_t segments;

segments = display.encodeDigit(minutes / 10);
segments = display.encodeDigit(minutes % 10);
segments = display.encodeDigit(seconds / 10);
segments = display.encodeDigit(seconds % 10);

if (colonState) {
    segments |= 0x80;
}

display.setSegments(segments);
lastDisplayedTime = timeInSeconds;
}

void handleAlarm() {
unsigned long currentMillis = millis();

// Handle display flashing
if (currentMillis - lastDisplayFlash >= 500) {
    lastDisplayFlash = currentMillis;
    displayOn = !displayOn;
    updateDisplay(0);
}

// Handle intermittent alarm sound
if (currentMillis - lastBuzzTime >= (alarmOn ? ALARM_ON_TIME : ALARM_OFF_TIME)) {
    lastBuzzTime = currentMillis;
    alarmOn = !alarmOn;
   
    if (alarmOn) {
      tone(BUZZER_PIN, ALARM_FREQ);
    } else {
      noTone(BUZZER_PIN);
    }
}
}

void resetTimer() {
currentState = IDLE;
timerRunning = false;
noTone(BUZZER_PIN);
alarmOn = false;
displayOn = true;
colonState = true;
lastDisplayedTime = -1;
updateDisplay(quantizeTime(readSmoothedPot()));
}

驴友花雕 发表于 2025-5-29 18:44:21

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器

本帖最后由 驴友花雕 于 2025-6-7 06:52 编辑

附录
【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
项目链接:https://www.hackster.io/mircemk/ ... 1637-display-2ea539
项目作者:马其顿米尔塞姆克

视频教程(9分钟):https://www.youtube.com/watch?v=Ml7XeU9oe6c
项目代码:https://content.instructables.co ... FC8SENLMAXYF50W.ino





驴友花雕 发表于 7 天前

【Arduino 动手做】带TM1637显示屏的多功能厨房定时器






页: [1]
查看完整版本: 【Arduino 动手做】带TM1637显示屏的多功能厨房定时器