Arduino Kitchen Timer
组件和用品
| × | 1 | ||||
| × | 1 | ||||
| × | 4 | ||||
| × | 4 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
关于这个项目
起初,上帝创造了天地。还有人类。人类创造了数字厨房定时器,就像这个一样。
人类说,酷但有点惨淡。让我们做得更好!
上帝说,我听到了你的呼唤,让 Arduinos 出现吧:地球上到处都是 Arduinos,那很好。
人类用一个 Arduino 创造了一个更好的厨房定时器,就像这个。
上帝看到了新的厨房计时器并说:我看到了你的新厨房计时器,它看起来糟糕 ,但似乎太好玩 ! 那很好 . :-)
你需要什么
既然您知道这一切的来源,让我们深入探讨一下。
我使用的所有组件都来自 Arduino 入门套件 ,包括您在图片和视频中看到的小面包板。随意将项目纳入更大的项目 ,如果你愿意。
您还需要一个电源:在玩耍时,PC 的 USB 端口和电缆就足够了。
你需要做什么
首先:请从入门套件或您喜欢的组件箱中收集所有需要的组件;如果你没有,不要惊慌。 有很多 在网上。您可以在下面找到组件列表。
而且,你也需要代码。它在它的盒子里,又在下面。
工作原理
基本上,就像任何其他类似设备一样,您可以在您附近的任何商店花一美元购买。但是这个 是你的 .这将向您展示如何 那些小玩意儿确实有用。
这里的关键字是:当前模式 .计时器本身一次只能以四种模式中的一种运行:
- IDLE - 计时器正在等待您的输入,显示当前设置的时间量;这也是上电或复位后的初始模式。
- SETUP - 您可以通过长按 S4 进入此模式(在代码中这也称为“重置按钮”);在这里,通过使用 S3(“开始停止按钮”),您可以选择要更改的值,以便设置稍后倒计时的经过时间;最后,分别使用 S2(“向下按钮”)和 S1(“向上按钮”),您可以减少或增加所选值(小时、分钟或秒)。
- RUNNING - 您可以通过按 S3 进入此模式,而离开则需要 S3 或 S4(这将引导您进入空闲模式)。
- RINGING - 当所需时间过去后,此模式会自动激活;你可以按任意开关离开(即让小男孩停止响铃)。
代码
首先,我们需要包含 合适的库:
#include
#include
如果您还没有它们,则需要下载并安装它们:
- 保罗 Stoffregen's 时间 图书馆 (请下载ZIP 从绿色的“克隆或下载”按钮)
- Arduino LiquidCrystal 库
接下来,让我们初始化 那个漂亮的液晶模组:
液晶液晶(12, 11, 5, 4, 3, 2);
请随意随意打乱引脚以获得良好的布线布局:不要跟着我这样做,因为我做了一个糟糕的布线计划! :D 例如,您可以反转上述语句中的后四个引脚,以避免在下面的示意图中看到黄色电线交叉(显然,您必须相应地调整按钮引脚常数,见下文)。玩,玩得开心!在复制/粘贴之后,Arduinos 的生活就开始了!
接下来的 51 行代码包含静态变量声明和初始化。请随意浏览它们,它们清晰的名称和一些零散的评论将引导您了解整个事情。
setup() 函数执行您已经在任何 Arduino 草图中看到无数次的通常的初步步骤。唯一值得注意的是第一个语句,它将设置初始 LCD 显示光标的位置。因为,是的:这个模块要求你沿着它的行和列设置一个位置,然后“打印”一些东西,它会从那个位置开始出现。
现在让我们转到 loop() 函数。
首先,让我们发现开关状态。为了实现这一点,下面的代码块用于几乎 他们每个人:
/*
* 开始/停止按钮管理
*/
startStopButtonPressed =false;
startStopButtonState =digitalRead(startStopButtonPin);
if(startStopButtonState !=startStopButtonPrevState)
{
startStopButtonPressed =startStopButtonState ==HIGH;
startStopButtonPrevState =startStopButtonState;
}
针对相关引脚发出 digitalRead 并将结果与先前读取的值进行比较:如果发生变化,则存储新值以供将来参考,如果按下按钮,则 bool "xxxButtonPressed" 静态变量设置为 true。
查看下面的电路图,您会注意到每个输入引脚都被一个 10k 电阻器强制为低电平,除非按下相应的开关并且引脚本身直接连接到 +5V。一个相当经典的场景,嗯?
以前,我说“几乎 每个按钮”,因为有一个按钮的作用与其他按钮不同:S4。它的代码块能够检测到上述长按以进入设置模式。
接下来是模式管理块切换:每个案例查看按钮状态触发器(“xxxButtonPressed”)并将流程重定向到正确的新状态,或执行正确的操作。
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();
}
}
中断;
前面的代码片段显示了 IDLE 模式的管理方式,并且一目了然。另一个例子显示了在振铃时按下任何按钮如何停止它:
case MODE_RINGING:
if(resetButtonPressed || startStopButtonPressed || downButtonPressed || upButtonPressed)
{
currentMode =MODE_IDLE;
}
break;
看起来很容易,不是吗? :-) 是的。
下一个块 - “时间管理” - 执行实际时差计算,触发响铃模式并实际响铃 该做的时候发出嗡嗡声。
最后一个模块——“LCD 管理”——通过在适当的位置打印适当的字符串来管理每种模式的 LCD 显示。
就是这样。
总结并行动!
既然这只小狗对你来说已经没有更多的秘密了,让我们看看它的实际行动吧。感谢收看,祝您玩得开心!
代码
- ArduinoSketch
ArduinoSketchArduino
/**************************************************** **** * Arduino Kitchen Timer v1.0 - 2016/01/27 * 作者:Angelo Fiorillo(意大利罗马) * 本作品在 GNU General 下分发 * Public License version 3 或更高版本 (GPL3+) * 请包括此信用请注意是否要*重新使用此草图的任何部分。尊重我的工作*,就像我会尊重你的一样。 * 请随时与我联系:[email protected] * ************************************* ***********/#include#include // FIX 2018-08-12 这修复了«'now' 未在此范围内声明» errorLiquidCrystal lcd( 12, 11, 5, 4, 3, 2);const int buzzerPin =10;const int resetButtonPin =6;const int startStopButtonPin =7;const int downButtonPin =8;const int upButtonPin =9;int setupHours =0; // 当开始时倒计时多少小时int setupMinutes =0; // 当开始时倒计时多少分钟int setupSeconds =0; // starttime_t setupTime =0;int currentHours =0;int currentMinutes =0;int currentSeconds =0;time_t currentTime =0;time_t startTime =0;time_t elapsedTime =0;int resetButtonState =LOW;long时倒计时多少秒resetButtonLongPressCounter =0;int startStopButtonState =LOW;int upButtonState =LOW;int downButtonState =LOW;int resetButtonPrevState =LOW;int startStopButtonPrevState =LOW;int upButtonPrevState =LOW;int downButtonPrevState =LOW;bool resetButtonPressed =false;bool resetButtonLongPressed =false;bool startStopButtonPressed =false;bool upButtonPressed =false;bool 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; // 0=idle 1=setup 2=running 3=ringing // Power up --> idle // Reset --> idle // Start/Stop --> start or stop counter // Up / Down --> NOP // 复位(长按)--> 进入设置 // 开始/停止 --> 数据选择 // 向上 --> 增加当前数据值 // 向下 --> 减少当前数据值 // 复位 --> 退出设置(空闲)int dataSelection =0; // 当前选择的数据进行编辑(设置模式,随开始/停止而变化) // 0=小时 (00-99) 1=分钟 (00-59) 2=秒 (00-59)void setup() { //把你的设置代码放在这里,运行一次:lcd.begin(16, 2); pinMode(resetButtonPin, INPUT); pinMode(startStopButtonPin, INPUT); pinMode(upButtonPin, INPUT); pinMode(downButtonPin, INPUT); pinMode(蜂鸣器Pin,输出); Serial.begin(9600);}void loop() { // 把你的主要代码放在这里,重复运行:startStopButtonPressed =false; upButtonPressed =假; downButtonPressed =false; /* * 重置按钮管理 */ 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; } } /* * 开始/停止按钮管理*/ startStopButtonPressed =false; startStopButtonState =digitalRead(startStopButtonPin); if(startStopButtonState !=startStopButtonPrevState) { startStopButtonPressed =startStopButtonState ==HIGH; startStopButtonPrevState =startStopButtonState; } /* * 向下按钮管理 */ downButtonPressed =false; downButtonState =digitalRead(downButtonPin); if(downButtonState !=downButtonPrevState) { downButtonPressed =downButtonState ==HIGH; downButtonPrevState =downButtonState; } /* * 向上按钮管理 */ upButtonPressed =false; 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) { // 启动计时器!开始时间 =现在(); } } 休息; case MODE_SETUP:if(resetButtonPressed) { // 退出设置模式 setupTime =setupSeconds + (60 * setupMinutes) + (3600 * setupHours); currentHours =setupHours; currentMinutes =setupMinutes; currentSeconds =setupSeconds;数据选择 =0; currentMode =MODE_IDLE; } if(startStopButtonPressed) { // 选择下一个数据调整dataSelection++; if(dataSelection ==3) { dataSelection =0; } } if(downButtonPressed) { switch(dataSelection) { case 0:// hours setupHours--; if(setupHours ==-1) { setupHours =99; } 休息; case 1:// 分钟 setupMinutes--; if(setupMinutes ==-1) { setupMinutes =59; } 休息; case 2:// 秒 setupSeconds--; if(setupSeconds ==-1) { setupSeconds =59; } 休息; } } if(upButtonPressed) { switch(dataSelection) { case 0:// hours setupHours++; if(setupHours ==100) { setupHours =0; } 休息; case 1:// 分钟 setupMinutes++; if(setupMinutes ==60) { setupMinutes =0; } 休息; case 2:// 秒 setupSeconds++; if(setupSeconds ==60) { setupSeconds =0; } 休息; } } 休息; case MODE_RUNNING:if(startStopButtonPressed) { currentMode =MODE_IDLE; } if(resetButtonPressed) { 重置(); currentMode =MODE_IDLE; } 休息; case MODE_RINGING:if(resetButtonPressed || startStopButtonPressed || downButtonPressed || upButtonPressed) { currentMode =MODE_IDLE; } 休息; } /* * 时间管理 */ switch(currentMode) { case MODE_IDLE:case MODE_SETUP:// NOP break; case MODE_RUNNING:currentTime =setupTime - (now() - startTime); if(currentTime <=0) { currentMode =MODE_RINGING; } 休息;案例MODE_RINGING:模拟写入(蜂鸣器Pin,20);延迟(20);模拟写入(蜂鸣器Pin,0);延迟(40);休息; } /* * LCD管理*/ //lcd.clear(); lcd.setCursor(0, 0); switch(currentMode) { case MODE_IDLE:lcd.print("定时器就绪"); lcd.setCursor(0, 1); lcd.print(currentHours);液晶打印(“”); lcd.print(currentMinutes);液晶打印(“”); lcd.print(currentSeconds);液晶打印(“”);休息; case MODE_SETUP:lcd.print("设置模式:"); switch(dataSelection) { case 0:lcd.print("HRS ");休息;情况一:lcd.print("MINS");休息;情况 2:lcd.print("SECS");休息; } lcd.setCursor(0, 1); lcd.print(setupHours);液晶打印(“”); lcd.print(setupMinutes);液晶打印(“”); lcd.print(setupSeconds);液晶打印(“”);休息; case MODE_RUNNING:lcd.print("倒计时..."); lcd.setCursor(0, 1); if(hour(currentTime) <10) lcd.print("0");液晶显示(小时(当前时间)); lcd.print(":"); if(minute(currentTime) <10) lcd.print("0");液晶显示(分钟(当前时间)); lcd.print(":"); if(second(currentTime) <10) lcd.print("0"); lcd.print(second(currentTime));休息; case MODE_RINGING:lcd.print("RING-RING!"); lcd.setCursor(0, 1);液晶打印(“”);休息; } delay(10);}void Reset(){ currentMode =MODE_IDLE; currentHours =setupHours; currentMinutes =setupMinutes; currentSeconds =setupSeconds;}
示意图
您可以使用任何通用面包板,包括入门套件,它比此处描述的要小(蜂鸣器可以放置在黄线下方,请参阅视频和照片)。制造工艺