30浏览
查看: 30|回复: 8

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

[复制链接]
Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。

Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

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

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

驴友花雕  中级技神
 楼主|

发表于 前天 18:26

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

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

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

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 18:28

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

## 步骤1:描述

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

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

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

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

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 18:31

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

## 第 2 步:零件

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

- Arduino Nano微控制器板

- TM1637 - 4 位,7 段显示

-10K电位器

- 三个按钮

- 和蜂鸣器

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

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 18:33

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

## 步骤3:功能和能力

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

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

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

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

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

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

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

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 18:34

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

## 步骤4:代码说明

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

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

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

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

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

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 18:36

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

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

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

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





回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 18:38

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

项目代码

  1. //-----------------------------------------------------
  2. // Kitchen Timer with TM1637 Display
  3. // by: mircemk
  4. // License: GNU GPl 3.0
  5. // Created: April 2025
  6. //-----------------------------------------------------
  7. #include <TM1637Display.h>
  8. // Pin definitions
  9. #define CLK 2
  10. #define DIO 3
  11. #define POT_PIN A0
  12. #define START_BUTTON 4
  13. #define RESET_BUTTON 5
  14. #define BUZZER_PIN 6
  15. #define RANGE_BUTTON 7
  16. // Constants
  17. #define QUANTIZE_INTERVAL 30   
  18. #define POT_SMOOTHING 30        
  19. #define POT_READ_DELAY 50      
  20. #define ALARM_FREQ 500         
  21. #define ALARM_ON_TIME 200      
  22. #define ALARM_OFF_TIME 200      
  23. #define COLON_ON_TIME 500      
  24. #define COLON_OFF_TIME 500     
  25. #define RANGE_DISPLAY_TIME 1000
  26. #define BUTTON_DEBOUNCE_TIME 300
  27. // Timer ranges in seconds
  28. const int TIMER_RANGES[] = {600, 1800, 3600};  // 10min, 30min, 60min
  29. const int NUM_RANGES = 3;
  30. // Display instance
  31. TM1637Display display(CLK, DIO);
  32. // Variables
  33. unsigned long previousMillis = 0;
  34. const long interval = 1000;     
  35. bool timerRunning = false;
  36. int remainingTime = 0;         
  37. bool colonState = true;         
  38. unsigned long lastBuzzTime = 0;
  39. unsigned long lastColonToggle = 0;  
  40. bool alarmOn = false;
  41. bool displayOn = true;         
  42. int lastDisplayedTime = -1;     
  43. unsigned long lastPotRead = 0;
  44. unsigned long lastDisplayFlash = 0;
  45. int currentRangeIndex = 2;      // Start with 60min range (index 2)
  46. unsigned long rangeDisplayStartTime = 0;
  47. bool showingRange = false;      
  48. unsigned long lastRangeButtonPress = 0;
  49. // State enumeration
  50. enum TimerState {
  51.   IDLE,
  52.   SHOWING_RANGE,
  53.   RUNNING,
  54.   ALARMING
  55. };
  56. TimerState currentState = IDLE;
  57. void setup() {
  58.   pinMode(START_BUTTON, INPUT_PULLUP);
  59.   pinMode(RESET_BUTTON, INPUT_PULLUP);
  60.   pinMode(RANGE_BUTTON, INPUT_PULLUP);
  61.   pinMode(BUZZER_PIN, OUTPUT);
  62.   display.setBrightness(0x0a);
  63.   updateDisplay(quantizeTime(readSmoothedPot()));
  64. }
  65. void loop() {
  66.   unsigned long currentMillis = millis();
  67.   
  68.   switch(currentState) {
  69.     case SHOWING_RANGE:
  70.       // Stay in range display mode until time elapsed
  71.       if (currentMillis - rangeDisplayStartTime >= RANGE_DISPLAY_TIME) {
  72.         currentState = IDLE;
  73.         lastDisplayedTime = -1;  // Force pot reading update
  74.       } else {
  75.         // Keep showing range
  76.         displayRange(TIMER_RANGES[currentRangeIndex]);
  77.         return;  // Skip all other processing while showing range
  78.       }
  79.       break;
  80.       
  81.     case IDLE:
  82.       // Handle range button
  83.       if (digitalRead(RANGE_BUTTON) == LOW) {
  84.         if (currentMillis - lastRangeButtonPress >= BUTTON_DEBOUNCE_TIME) {
  85.           currentRangeIndex = (currentRangeIndex + 1) % NUM_RANGES;
  86.           rangeDisplayStartTime = currentMillis;
  87.           lastRangeButtonPress = currentMillis;
  88.           currentState = SHOWING_RANGE;
  89.           displayRange(TIMER_RANGES[currentRangeIndex]);
  90.           return;  // Exit loop immediately after changing to range display
  91.         }
  92.       }
  93.       
  94.       // Handle potentiometer input
  95.       if (currentMillis - lastPotRead > POT_READ_DELAY) {
  96.         lastPotRead = currentMillis;
  97.         int potTime = quantizeTime(readSmoothedPot());
  98.         if (potTime != lastDisplayedTime) {
  99.           colonState = true;
  100.           updateDisplay(potTime);
  101.           lastDisplayedTime = potTime;
  102.         }
  103.       }
  104.       
  105.       // Handle start button
  106.       if (digitalRead(START_BUTTON) == LOW) {
  107.         delay(50);
  108.         if (digitalRead(START_BUTTON) == LOW) {
  109.           remainingTime = quantizeTime(readSmoothedPot());
  110.           currentState = RUNNING;
  111.           previousMillis = currentMillis;
  112.           lastDisplayedTime = -1;
  113.           colonState = true;
  114.           lastColonToggle = currentMillis;
  115.         }
  116.       }
  117.       break;
  118.       
  119.     case RUNNING:
  120.       // Handle colon blinking
  121.       if (colonState && (currentMillis - lastColonToggle >= COLON_ON_TIME)) {
  122.         colonState = false;
  123.         lastColonToggle = currentMillis;
  124.         updateDisplay(remainingTime);
  125.       }
  126.       else if (!colonState && (currentMillis - lastColonToggle >= COLON_OFF_TIME)) {
  127.         colonState = true;
  128.         lastColonToggle = currentMillis;
  129.         updateDisplay(remainingTime);
  130.       }
  131.       
  132.       // Update timer
  133.       if (currentMillis - previousMillis >= interval) {
  134.         previousMillis = currentMillis;
  135.         if (remainingTime > 0) {
  136.           remainingTime--;
  137.           updateDisplay(remainingTime);
  138.         }
  139.         if (remainingTime == 0) {
  140.           currentState = ALARMING;
  141.         }
  142.       }
  143.       
  144.       // Check reset button
  145.       if (digitalRead(RESET_BUTTON) == LOW) {
  146.         delay(50);
  147.         if (digitalRead(RESET_BUTTON) == LOW) {
  148.           resetTimer();
  149.         }
  150.       }
  151.       break;
  152.       
  153.     case ALARMING:
  154.       handleAlarm();
  155.       if (digitalRead(RESET_BUTTON) == LOW) {
  156.         delay(50);
  157.         if (digitalRead(RESET_BUTTON) == LOW) {
  158.           resetTimer();
  159.         }
  160.       }
  161.       break;
  162.   }
  163. }
  164. void displayRange(int rangeInSeconds) {
  165.   int minutes = rangeInSeconds / 60;
  166.   uint8_t segments[4];
  167.   
  168.   segments[0] = display.encodeDigit(minutes / 10);
  169.   segments[1] = display.encodeDigit(minutes % 10) | 0x80;  // Force colon on
  170.   segments[2] = display.encodeDigit(0);
  171.   segments[3] = display.encodeDigit(0);
  172.   
  173.   display.setSegments(segments);
  174. }
  175. int readSmoothedPot() {
  176.   long total = 0;
  177.   for (int i = 0; i < POT_SMOOTHING; i++) {
  178.     total += analogRead(POT_PIN);
  179.     delay(1);
  180.   }
  181.   int average = total / POT_SMOOTHING;
  182.   return map(average, 0, 1023, 0, TIMER_RANGES[currentRangeIndex]);
  183. }
  184. int quantizeTime(int seconds) {
  185.   int quantized = (seconds / QUANTIZE_INTERVAL) * QUANTIZE_INTERVAL;
  186.   return constrain(quantized, 0, TIMER_RANGES[currentRangeIndex]);
  187. }
  188. void updateDisplay(int timeInSeconds) {
  189.   if (currentState == ALARMING && !displayOn) {
  190.     display.clear();
  191.     return;
  192.   }
  193.   int minutes = timeInSeconds / 60;
  194.   int seconds = timeInSeconds % 60;
  195.   uint8_t segments[4];
  196.   
  197.   segments[0] = display.encodeDigit(minutes / 10);
  198.   segments[1] = display.encodeDigit(minutes % 10);
  199.   segments[2] = display.encodeDigit(seconds / 10);
  200.   segments[3] = display.encodeDigit(seconds % 10);
  201.   
  202.   if (colonState) {
  203.     segments[1] |= 0x80;
  204.   }
  205.   display.setSegments(segments);
  206.   lastDisplayedTime = timeInSeconds;
  207. }
  208. void handleAlarm() {
  209.   unsigned long currentMillis = millis();
  210.   
  211.   // Handle display flashing
  212.   if (currentMillis - lastDisplayFlash >= 500) {
  213.     lastDisplayFlash = currentMillis;
  214.     displayOn = !displayOn;
  215.     updateDisplay(0);
  216.   }
  217.   // Handle intermittent alarm sound
  218.   if (currentMillis - lastBuzzTime >= (alarmOn ? ALARM_ON_TIME : ALARM_OFF_TIME)) {
  219.     lastBuzzTime = currentMillis;
  220.     alarmOn = !alarmOn;
  221.    
  222.     if (alarmOn) {
  223.       tone(BUZZER_PIN, ALARM_FREQ);
  224.     } else {
  225.       noTone(BUZZER_PIN);
  226.     }
  227.   }
  228. }
  229. void resetTimer() {
  230.   currentState = IDLE;
  231.   timerRunning = false;
  232.   noTone(BUZZER_PIN);
  233.   alarmOn = false;
  234.   displayOn = true;
  235.   colonState = true;
  236.   lastDisplayedTime = -1;
  237.   updateDisplay(quantizeTime(readSmoothedPot()));
  238. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 前天 18:44

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

附录
【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显示屏的多功能厨房定时器图2

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

附件.zip

2.24 KB, 下载次数: 0

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail