AI脑洞板
完整教案
自学课件
第 37 课 · 共 37/51 课

番茄时钟和闹钟——时间怎样被测量和提醒 时间怎样被测量和提醒

课时
待定
器材
ESP32-S3 触摸屏板 + USB 线
前置知识
无
配套代码
见项目 demo 目录

开始之前:小明第三次来

你好,我是吴老师。

小明又来了。 前两次他带来的是"老忘带书"和"背单词老忘"。

这次他的麻烦,听起来跟前两个不太一样:

请你扮演一个四年级的小学生,名字叫小明。

你有一个麻烦:一坐下来写作业就想玩,一玩就停不下来,
作业老是拖到很晚。妈妈盯着的时候你能坐住,她一走你又开始玩了。
(别的你也不知道 —— 你就是个普通小学生,没想过怎么解决。)

规则:
1. 你说话要像一个真的四年级学生:句子短,想到什么说什么
2. 一次只说一点,别一口气把情况全说完了 —— 等对方问你
3. 对方问你什么,你就老实回答什么
4. 你不知道"该做什么工具",你只知道自己有这个麻烦

现在开始:先打个招呼,然后说说你的麻烦。
说完就停下来,等对方提问。

把这段发给电脑上的 AI。从现在起,它就是小明。

一、⚠️ 这个麻烦,比前两个难

前两个麻烦,问几轮就能问清楚。这个不一样。

💡 因为小明说的"我一玩就停不下来"不是原因,是结果。

你要找的是:他为什么停不下来?

而且有意思的是 —— 小明自己多半知道原因,只是不会主动说。

二、像侦探一样问他

这几问最值钱:

该问想挖出什么
"你一般能坐住多久?"是十秒就烦,还是二十分钟才烦?答案完全不一样
"走神的时候,你一般在想什么?"是想玩?还是这题不会做?这是两件事
⭐ "妈妈在的时候,有什么不一样?"他真的需要"被盯着",还是需要别的?
"你写完作业之后,会干什么?"如果他"写完也没得玩",那拖着就是划算的
❌ 别问为什么
"你是不是要个定时器?"你把答案塞给他了 —— 他会说"对对对",做出来才发现没用
"你要什么功能?"他要是知道,就不用找你了

⭐ 第三问最关键。

追下去往往会发现:小明需要的不是"有人盯他",是**"有个东西告诉他'你正在做对的事'"**。

妈妈在的时候他坐得住 —— 因为有人在看着他、认可他。 她一走,这个"看着"就没了。

三、你到底问出了什么

要回答从小明的话里
他真正的麻烦不是"没有闹钟",是看不到自己在进步,所以坐不住
什么时候用每次开始写作业的那一刻
怎么算做成了能连续坐住 20 分钟,而且自己知道自己坐住了

⭐ 看出来了吗?

如果直接做个"倒计时 25 分钟",他还是会中途摸鱼 —— 因为时间在走,他看不见。

💡 这一条会直接落到技术点上:得让进度看得见。 记住它,第五节要用。

本课一句话:计时器不是"数秒数",而是"用现在时刻减去开始时刻"。 板子没有一个"感觉到时间"的器官,它只是拿一个会走的数,和另一个会走的数做减法。

四、先让板子当"番茄钟"

先别听我讲,让板子演示一遍。

请使用课程的 esp32s3-touchboard-hardware-dev Skill,
烧录本课配套程序 assets/codes/demo01_tomato_clock:
板子屏幕显示一个番茄钟,按一下"开始",进入 25 分钟专注倒计时;
到点板子"叮"一声提醒你休息;再按一次进入 5 分钟休息。
屏幕会显示还剩多少分钟、今天专注了多久。
烧录前把中文字库复制好(见 README)。烧录后告诉我:
按"开始"以后,屏幕上的数字是怎么变化的?

几秒后,屏幕上出现一个番茄钟:一个大大的圈,里面写着"25:00"(还剩 25 分钟)。下方有个"开始"按钮。你点一下,数字开始倒着走:24:59、24:58……走到 00:00,板子"叮"一声,然后屏幕变成"该休息了 ✨ 5:00"。

五、拆开看:计时器到底在"数"什么?

现在关键的来了。很多人以为计时器是"一秒一秒地数",其实不是。

板子是这么算的(伪代码,不用背):

还剩多少时间 = 目标时长 - (现在时刻 - 开始时刻)

举个例子:你按"开始"的那一瞬间,板子记下一个数 开始时刻 = 10000(这个数代表"从开机到现在过了多少毫秒")。

过了一秒,现在时刻变成了 11000。那么:

还剩 = 25分钟 - (11000 - 10000)
     = 25分钟 - 1秒
     = 24分59秒

看到没?板子从来没有"数秒",它一直做的是"减法":用 当前时刻 减去 开始时刻,得到"过去了多久",再用 目标时长 减去它,得到"还剩多少"。

⚠️ 给比喻划边界:说计时器像"沙漏",但沙漏真的在漏沙子;板子的"沙漏"是个假沙漏——它会算"过去了多少",但沙子是"现在时刻 - 开始时刻"这个减法算出来的,不是真的在漏。正因为它不是真漏,所以它不会错、不会停、也不会莫名变快——除非主控卡住了。

六、⭐ "现在几点了"这个数,从哪来?

上面那个"当前时刻",是 millis() 这个函数给的——它从板子开机那一刻开始,每秒加一千,是个一直往前走的大型计数器。这个靠主控自己数,不依赖任何外部时钟。

但是!它有一个致命弱点:它只记"开机到现在过去了多久",它不知道"现在到底是上午 9 点还是晚上 9 点"。也就是说,它的"现在"是从 0 开始的相对时间,不是"日历上几点几分"。

那要显示"现在几点"怎么办?两种办法:

办法怎么拿"现在几点"优点缺点
主控自己数(millis)从开机开始数,能算"过去了多久"简单、不需要网不知道"几月几号几点",断电清零
联网对时(NTP)问一个网络时钟服务器"现在几点?"知道真实日期时间需要联网,断电要重问

本板没有独立的电池时钟芯片(RTC)。所以它没有"永远准确的时间"——要么靠主控数(断电就清零),要么联网问一次(断电再连网重新问)。这是本板的一个真实边界,也是真实设备几乎都用来联网对时的原因。

七、到点提醒:"叮"一声是怎么发生的?

计时器到 00:00,板子怎么知道该"叮"了?

其实就是一个条件判断:

每一帧(比如每 20 毫秒):
    现在时刻 = millis()
    还剩 = 目标时长 - (现在时刻 - 开始时刻)

    如果 还剩 <= 0:       ← 到点了!
        播放"叮"的一声
        切换到"该休息了"画面

"到点了"不是板子"感觉"到的,是它一遍遍判断"还剩是不是 ≤ 0"判断出来的。 就像你盯着时钟看它走到 12 点,板子盯着"还剩"这个数,一看它归零就触发提醒。

提醒的方式也很讲究。板子有三个"输出"可以用来提醒你:声音(第 11 课,喇叭)、灯(第 1 课,RGB)、屏幕(画面)。你可以选一种、也可以三种一起来——能让你"看见/听见"就行。

八、从"计时器"到"番茄钟":再加两个规则

光会倒计时还不够。番茄钟真正聪明的地方,是两个规则:

  1. 专注段 / 休息段交替:25 分钟专注 → 5 分钟休息 → 25 分钟专注 → …… 循环。
  2. 记录:今天专注了几个番茄。每次完成一个专注段,计数 +1。

这个"记录"就是状态——和背单词课的"掌握度"、电子宠物的"饥饿度"一样,是一个会被时间或操作改变的数。

规则(一段番茄):
    专注 25 分钟:
        完成 → "叮" → 记录 +1 个番茄 → 进入休息 5 分钟
        休息到点 → "叮" → 回到专注 25 分钟

你看,番茄钟就是个状态机:专注 / 休息 / 记录,三个状态换来换去。你在第 30 课(贪吃蛇)已经见过状态机了。

⭐ 别忘了你采访出来的那句话:他真正缺的是"看得见的进步"。

所以光有数字是不够的("还剩 12 分钟"他看不出来走了多少)—— 演示里那个一圈一圈填满的大圆,才是真正解决他问题的东西。

技术要求是"能算出还剩多少",产品需求是"让他看得见"。两件事。

九、⭐ 交付给小明

装好之后,回头告诉他你做了什么:

我做好了一个工具。它长这样:
____(把屏幕上的样子说给他听)
每次你开始写作业就点上,那个圈会慢慢填满。
你觉得能帮上你吗?

认真听他怎么说:

小明:嗯……可是圈填满之前,我还是会偷偷玩一下。 小明:还有,我怎么知道我今天做了几个?

⭐ 第一句说明:一个工具解决不了所有问题。 它能让他"更愿意坐住",但按不按下开始键,还是他自己的事。 这不是失败 —— 好的工具是帮人变好一点,不是替人活着。

第二句正好指向第八节那个"记录"(记忆番茄数)—— 但注意: 它只存在内存里,一断电就没了。想让它记住,得存 TF 卡(第 14 课)。

十、分析:这个番茄钟用了哪些技术?

同样不让 AI 深挖代码,你要能说清"零件表":

技术 / 概念在这里干什么你之前在哪学过
millis() 计时"现在时刻 - 开始时刻",核心计时第 2/6 课
倒计时"目标时长 - (现在 - 开始)"本课新增
条件判断(到点)还剩 <= 0 就触发提醒第 2 课(if)
NTP 对时联网问"现在几点",显示真实时间第 19 课
状态机专注 / 休息 / 记录 三种状态切换第 30 课(贪吃蛇)
声音 / 灯到点"叮"提醒(输出)第 11 课 / 第 1 课
背景音乐可选休息时可放轻音乐第 16 课

⚠️ 重要边界:millis() 计时不受断电影响吗? 会受影响!millis() 从开机开始数,断电就清零重来。所以"今天专注了几个番茄"如果只存在内存里,断电就没了——这和背单词课的问题一模一样。想让"今天专注了几个"断电不忘,也要存进 TF 卡(第 14 课)。

⚠️ 另一个边界:要"现在几点",就不能只靠 millis()。millis() 只知道"开机到现在多久",不知道"日期几点"。要显示日历时间,得联网 NTP 对时——这正是第 19 课讲的"板子出门问云端"。

一句话总结:番茄钟 = 用 millis() 做减法计时 + 用条件判断"到点" + 用状态机管理专注/休息/记录 + 用声音/灯/屏幕提醒。"计时"本质是"现在 - 开始"的减法,"到点"本质是"还剩 ≤ 0"的判断。

十一、改一个条件,看它怎么变

我想改该动哪部分我预测会发生什么
专注改成 50 分钟专注时长那个数倒计时变长,提醒变晚
休息改成 10 分钟休息时长那个数休息变长
到点用"闪灯"提醒提醒方式不响了,改闪 RGB 灯
加上"记录今天做了几个番茄"状态记录屏幕显示计数
改成"到点放首歌"提醒 + 声音到点放音乐

先预测,再验证。 你会发现:改的都是"数据"(时长、提醒方式、要不要记录)和"规则"(几分钟一换、怎么提醒),而"计时"这件事本身(减法和判断到点)一点没变。

十二、如果它没按你想的来

现象先查什么
数字不走millis() 用对了吗?是不是没用"当前时刻-开始时刻"?
到点不"叮"声音链路对吗?音量够吗?(第 11 课)
到点不提醒还剩<=0 的判断写对了吗?有没有在每帧都检查?
"现在几点"不准靠 millis() 只能知相对时间;要日历时间得联网 NTP 对时
断电后"今天专注了几个"没了存了内存——要持久得存 TF 卡

记住:millis() 是"过去了多久",不是"现在几点";它们不是一回事。

十三、下课前,把"计时和提醒"讲给我听

先别看 AI 的回答,自己说一遍:

  1. ⭐ 小明说的"我一玩就停不下来",是原因还是结果?真正的原因是什么?
  2. 计时器真的是"一秒一秒数"吗?板子到底在做什么减法?
  3. millis() 给出的是"现在几点"还是"开机到现在多久"?它有什么局限?
  4. "到点了"是板子"感觉"到的,还是"判断"出来的?怎么判断?
  5. 本板有没有 RTC 时钟芯片?要显示"现在几点"该怎么办?
  6. 番茄钟的"专注/休息/记录"是什么?算不算状态机?
  7. "今天专注了几"为什么断电就没了?想记住该怎么存?

今天请留下三样东西:你调过的专注/休息时长、你设计的提醒方式(声音/灯/屏幕选一个)、以及一句"毫秒计时和日历时间"的区别。

十四、最后留给你:把"时间"变成你的伙伴

这一课你可能觉得"就一个计时器,有啥特别"。但想深一点:

理解"时间"这个资源,是工程师和普通人的分水岭。

你学到的本质能用来做什么
millis() 计时用减法测"过去了多久"动画、游戏、延迟、节拍
到点判断还剩<=0 触发提醒、闹钟、超时处理
状态机几个状态换来换去任何有开始/过程/结束的程序
NTP 对时联网问"现在几点"显示瞬间时间、定时任务

这些不只是"做个番茄钟",它们是所有"和时间打交道"的程序共同的底子——你后面做闹钟、倒计时、定时提醒、甚至智能家居,都用得上。

第七章「学习助手」到这里就完了。 回头看:34 课用数据组织一天、35 课用提示词让 AI 说话、36 课用数据+规则背单词、37 课用计时+状态管时间——我们一共让板子做了四件"帮你"的事。下一章(休闲娱乐)我们要反过来,让板子陪你看、听、玩。


教师备课备注(不作为课堂口播)

课程定位

  • ⭐ 2026-09-24 改版:本课加了「产品经理」范式(连同 34 / 36 / 46 / 47)。 结构:小明来求助 → 采访 → 挖真需求 → 做 → 交付 → 听反馈。
    • 本课的真需求反差:他说的"我一玩就停不下来"是结果不是原因; 追到根上常常是"看不到自己在进步"(妈妈在时坐得住,因为有人在认可他)。
    • ⚠️ 这一条必须回接技术点:正因为他"看不见",所以光有倒计时数字不够, 要有演示里那个一圈圈填满的大圆。采访与技术这条线断了就白改。
    • 交付时小明说"圈填满之前我还是会偷偷玩一下" —— 这是有意设计的: 要让老师点破"好工具是帮人变好一点,不是替人活着", 避免学生把"工具没根治问题"当成失败。
  • 第七章「学习助手」收尾课,也是时间类软件的核心课。技术落点:millis() 做减法计时、条件判断"到点"、状态机管理专注/休息、NTP 对时、用声音/灯/屏幕提醒。
  • 核心认知:计时不是"数秒数",而是"当前时刻 - 开始时刻"。millis() 给的是"开机到现在多久"(相对时间),不是"现在几点"(日历时间)——这是本课最重要的区分。
  • 与第 14 课、第 36 课呼应:内存 vs TF 卡("今天专注了几"断电就没了)。与第 19 课呼应:要日历时间必须联网 NTP 对时。
  • 时间边界(真难点):本板无独立 RTC 电池时钟芯片,时间只能主控计时(断电清零)或联网对时(断电重对)。这决定"现在几点"不可靠、要联网。

本课新增的核心知识点

  1. 计时本质:还剩 = 目标 - (现在 - 开始),减法不是数数。
  2. millis() 的局限:相对时间(开机到现在),不是日历时间;断电清零。
  3. 到点条件判断:还剩 <= 0 就触发提醒——不是"感觉"到的,是"判断"出来的。
  4. 状态机:专注 / 休息 / 记录 三种状态切换(复用第 30 课贪吃蛇的状态机思想)。
  5. NTP 对时:要显示日历时间须联网问"现在几点"(第 19 课)。
  6. 提醒方式:声音(喇叭)/ 灯(RGB)/ 屏幕三种输出,可组合。

必须避免的错误

  • 不要说"板子感觉到时间到了"——它是条件判断出来的。
  • 不要把 millis() 和"现在几点"混为一谈。millis() 是相对时长,不是日历时间;要日历时间须 NTP。
  • 不要说"本板时间很准"。无 RTC,断电需重新对时,时间可能不准——这是真实边界,要让学生知道。
  • 不要引入外部时钟模块(DS3231 等)——本板没有,且讲"无 RTC 的对时方案"是重点。

执行约束

  • FQBN:esp32:esp32:esp32s3:FlashSize=16M,PartitionScheme=app3M_fat9M_16MB,CDCOnBoot=cdc,PSRAM=opi
  • 依赖:TFT_eSPI、FT6336;若要响铃用 ES8311/I2S(第 11 课);ESP32Time/time.h;font/ChineseFont16.h。
  • 屏幕排线、触摸引脚同 34 课;功放 GPIO1 低有效;音量注意保护听力,先从小声开始。
  • dmeo01(计时版)不需要联网;demo02(NTP 对时版)需要 WiFi + 能上外网。
  • 中文显示:drawUtf8() + font/ChineseFont16.h;本课不需要云 API 密钥。

课堂执行要点

  • 顺序建议:demo01(现象:番茄钟倒计时 + 到点叮)→ 计时本质拆解 → millis() vs 日历时间 → 到点判断 → 状态机 → 改一个条件 → 下课前复述。若想讲"现在几点"再上 demo02(NTP 对时)。
  • 灵魂追问 ①:"计时器真的在数秒吗?它在做哪个减法?"——引出"现在还目标 - (现在-开始)"。
  • 灵魂追问 ②:"板子知道现在几点吗?"——引出 millis() 相对时间 vs NTP 日历时间 + 无 RTC 的边界。
  • 观察表先预测后实测。
  • 到点提醒先小声演示,注意保护听力。

待办与遗留

  • demo01_tomato_clock(计时版)、demo02(NTP 对时版,可选)源码已写(含中文字库),尚未实板验证。吴老师实板验收重点:① 倒计时是否准确;② 到点"叮"(声音链路 + 音量);③ 状态机(专注/休息切换)是否正确;④ 声音提醒是否保护听力(从小声)。
  • 若设计"今天专注了几存 TF 卡",需接第 14 课 TF 卡,作为拓展(本课主 demo 先用内存版,点破边界)。
  • NTP 对时(demo02)待实板联网验证;若教室无网,用主控 millis 相对计时也可完成主线。

第 37 课 · 番茄钟

第 37 课 · 番茄钟

点「开始」进入 25 分钟专注倒计时,到点屏幕和 RGB 灯一起提醒我休息,再进入 5 分钟休息。

37计时状态机millis
第 37 课 · 联网对时时钟

第 37 课 · 联网对时时钟

连上 WiFi 后向网络时间服务器问一句「现在几点」,屏幕就显示真实的日期、星期和秒表。

37NTP联网时间