【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
本帖最后由 驴友花雕 于 2025-6-7 06:51 编辑【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
该 Arduino 项目提供了一个用户友好、高度可定制的厨房计时器,具有所有基本功能。【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
## 步骤1:描述厨房计时器是一种简单、用户友好的设备,可以倒计时设定的时间,并在烹饪或烘焙任务完成时通过声音或视觉信号提醒用户。
大多数商用厨房计时器的设置和操作都相对复杂,因为人们更加关注许多不必要的选项和功能,而忽略了操作的简单性,而这对于具有此用途的计时器来说是一个基本特征。
在这个项目中,我将向您展示一种非常简单的方法来制作厨房计时器,它操作极其简单,但几乎具有现代商用计时器的所有功能。
【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
## 第 2 步:零件要制造该设备,您只需要几个组件:
- Arduino Nano微控制器板
- TM1637 - 4 位,7 段显示
-10K电位器
- 三个按钮
- 和蜂鸣器
【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
## 步骤3:功能和能力首先,我将解释如何操作该设备及其功能和性能。为了简单起见,时间设置使用一个简单的电位器,分为三个范围:0 至 60 分钟、0 至 30 分钟和 0 至 10 分钟。绿色按钮启动倒计时,黄色按钮可随时重置设备,红色按钮可选择所需的范围。
当设备打开时,屏幕上会出现时间,该时间由电位器的位置决定。
开机默认范围为 60 分钟。现在,使用电位器简单快速地设置所需时间,例如 7 分钟,然后按下启动按钮。计时器开始倒计时,显示屏中间的两个点开始闪烁。如果在此过程中的任何时候按下重置按钮,时间将恢复到原始设置状态。蜂鸣器会发出间歇性提示音,显示屏上的数字(在本例中为四个零)也会交替闪烁,表示设置时间已结束。这种情况会持续到我们按下重置按钮,之后设备即可再次运行。我们还来了解一下 RANGE 按钮的功能。
按下按钮后,屏幕上会显示设定范围两秒钟,然后显示该范围内的定时器值。使用此选项,我们可以更精确、更轻松地设置更短的时间间隔。正如您在说明中所见,此定时器的设置精度目前为 30 秒,因为对于厨房定时器来说,这已经足够了。
【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
## 步骤4:代码说明但是,根据需要,它可以是 10 秒、5 秒甚至 1 秒,并在代码中设置:
#define QUANTIZE_INTERVAL 30 //(1 到 60 秒)
至于代码,我试图使其尽可能灵活且易于修改,因此只需进行最少的更改,我们就可以创建一个自定义计时器来满足我们自己的要求。
简而言之,正如您所见,所有定时器参数都可以更改。例如,前面提到的 QUANTIZE_INTERVAL、POT_SMOOTHING、POT_READ_DELAY、报警频率以及开启/关闭时间、定时器范围的数量和持续时间,甚至显示屏的亮度。
【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
## 步骤5:结论、原理图和代码最后是简短的总结。总而言之,这个 Arduino 项目提供了一个用户友好、高度可定制的厨房定时器,具备所有必备功能,证明了有效的计时并不需要不必要的复杂性。
【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()));
}
【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
【Arduino 动手做】带TM1637显示屏的多功能厨房定时器
页:
[1]