你好,我是吴老师。
这份是给你自己读的——不用等我讲,你一段一段往下看,看到让你停下来的地方,就照着做一遍。看不懂的整段复制给 AI,加一句"请一次只解释一个概念,讲完问我一个小问题"。
读完之后,你应该能:说出 BOOT 按钮是输入、RGB 灯是输出,中间的主控在"处理";说清按下、松开和 0、1 是怎么对上的;认出身边的输入设备和输出设备;说出一个按钮能做出哪几种事件,以及它们靠什么区分;做出一个用按钮控制的自己的作品。
用时:约 60 分钟。准备:板子、数据线、已经接入板卡 Skill 的 WorkBuddy(第 1 课的 RGB 灯程序留着)。
一、今天的目标:按一下,灯换一种颜色
上一课,我们教会了 RGB 灯变颜色。可是一直自己变化的灯,还不算真正"听话"——它不知道你在旁边。
今天给它介绍一位小伙伴:板子上的 BOOT 按钮。按一下,灯换一种颜色;再按一下,再换。你会发现:人的动作可以进入电脑,电脑也能让灯回应。 这就是"输入"和"输出"。
先做两件事。第一件,让 AI 先查资料再动手:
我是小学生,正在学习触摸屏板。
请先读取 esp32s3-touchboard-hardware-dev Skill,确认:
1. BOOT 按钮实际连接哪个 GPIO;
2. 板载 RGB 灯的数据引脚和灯珠类型;
3. 现在电脑检测到哪些开发板和端口。
只检查,不写程序、不烧录。请用小学生能听懂的话告诉我。
如果 AI 直接猜答案,追问它依据的文件路径。
第二件,确认无误后让它写程序:
请新建一个教学程序,在屏幕上画三个按钮 A、B、C,点哪个就切换到哪种玩法(点一下切换一次):
【A 玩法】按住 BOOT 时亮红灯,松开就灭;
【B 玩法】按一下 BOOT 亮红灯并保持亮着,再按一下才灭;
【C 玩法】一开始常亮红灯,每按一下 BOOT 就换成一个随机颜色。
屏幕上要显示:当前是哪种玩法、BOOT 现在是按下还是松开、一共按了几次、一个和灯同色的小方块。
当前选中的按钮要高亮,让同学一眼看出在玩哪种。
灯光使用较低亮度。请用中文注释,保留上一课程序,不使用 WiFi。
编译和烧录前先运行 arduino-cli board list,确认目标端口后再操作。
烧录后三种玩法都玩一遍,边玩边观察:
| 玩法 | 你怎么操作 | 灯怎么反应 | 想一想 |
|---|---|---|---|
| A 按住亮灯 | 按住不放,再松开 | 松开后灯灭了吗? | |
| B 开关灯 | 按一下,等两秒,再按一下 | 松手之后灯还亮着吗? | |
| C 换随机颜色 | 连按五下 | 五次颜色都不一样吗? |
关键的一问:三种玩法的灯,都是同一颗灯;你做的动作也都是"按 BOOT"。那为什么效果完全不同?(先别急着回答,读到第四节你就明白了。)
屏幕上那三个按钮是可以点的——虽然我们还没学触摸屏(第 8 课才讲),但这里你只要会"用手指点一下方块"就够了,把它当成一个现成的黑盒用。
二、按钮只有两种状态:按下,和松开
先讲个比喻。按钮像一扇只有两种状态的小门:门关着、门开着。电路也有两种容易判断的状态——低电平 LOW 和 高电平 HIGH。
在这块板上,BOOT 通常是按下时 LOW、松开时 HIGH(一定以板卡资料和实测为准)。为了好记,我们约定:
| 按钮状态 | 电路电平 | 记号 |
|---|---|---|
| 松开(手没碰它) | HIGH | 1 |
| 按下(手指按住) | LOW | 0 |
这个 1 和 0 不是考试分数,就是给两种状态起的名字,方便电脑记。
ESP32-S3 不会"看见"你的手指。它只做一件事:读 GPIO0 上的电平。松开给它 1,按住给它 0。
这里有个很重要的地方,看一眼上面那张图:程序读到的不是"你按了几下",而是"此刻是 0 还是 1"。至于"你按了一下"这件事——它得靠程序自己前后对比才看出来。
完整链路是:
手指按下 → BOOT 电路变化 → GPIO0 读到 LOW(0) → ESP32-S3 判断 → RGB 灯收到新颜色 → 你看见灯变色。
电脑里面到处都是这种 0 和 1。至于 0 和 1 怎么变成文字、图片、声音,后面第 5 课会专门讲。今天只要记住:按下去是 0,松开是 1。
做一个实验:把"看不见的信号"画出来
说"0 和 1"很容易,可你根本看不见它——电平藏在电路里,不像灯那样会亮。那怎么证明它真的在变?
答案:让板子把读到的值画出来。 我们做一个"示波器"——就是科学家用来观察电压变化的仪器。屏幕上横着画一条时间轴,竖着画一条电平轴(也就是 X-Y 平面的表格):上面那条线代表 1,下面那条线代表 0,再让画面自己慢慢往左滚,像一个会走纸的记录仪。
请新建一个教学程序,把屏幕变成一台"示波器",专门用来看 BOOT 引脚上的信号。
屏幕型号是 ILI9341,240×320 竖屏,用 TFT_eSPI 库,中文字要用课程自带的 font_course.h。
在屏幕上半部分画一个坐标区:横轴是时间(越往右越接近现在),纵轴是电平(上面那条线代表 1、下面那条线代表 0)。
每隔 ___ 毫秒读一次 BOOT 引脚(BOOT 接在 GPIO0,按下是低电平 0,松开是高电平 1):
读到 1 就画在上面那条水平线上,读到 0 就画在下面那条水平线上;
从 1 变到 0、或者从 0 变到 1 的那一刻,用一条竖线把两段连起来,让它看起来像台阶。
让波形每次向左滚动 ___ 像素,最右边永远是最新的读数,就像示波器或者心电图那样。
横轴的时间刻度(0、-1s、-2s……)请固定不动——它是一把尺子,让同学可以量出"刚才按了大约几秒"。
波形线请用 ___ 颜色,画粗一点点,看得清楚。
屏幕下半部分再加一只秒表:按住 BOOT 时它在涨,松开后停住,这样秒表的读数和波形上那段低电平的宽度可以互相对照。
屏幕背景和文字颜色你自己搭配,但要保证在板子上看得清、不刺眼。
请使用中文注释。编译和烧录前先运行 arduino-cli board list,确认目标端口后再操作。
先别急着发给 AI——上面有 3 个空要你自己填。 填之前想一想:
- 多久读一次?读得太慢,快按一下就漏掉了;读得太快,一秒里画的点太多,屏幕装不下几秒。
- 每次滚多少像素?这决定了"屏幕上能看见过去几秒"。
- 波形用什么颜色?要和深色背景分开,一眼看得清。
想好了再点开:我们的参考数字
我们程序里用的是 每 50 毫秒读一次、每次滚 2 像素、波形用青色。
算一下:50 毫秒读一次、每次滚 2 像素,那么屏幕上 40 像素 = 1 秒,横轴有 200 像素,所以一眼能看见过去约 5 秒。
这同样不是标准答案。你可以试试改成"每 200 毫秒读一次"——按一下快键,波形上可能只剩一个细缝,甚至整下都漏掉了。做过这个对比,你就明白"采样快慢"意味着什么了。
烧录后照着做,把你的观察记下来:
| 你做的事 | 波形上发生了什么 | 秒表显示 |
|---|---|---|
| 什么都不按 | ||
| 按住不放 | ||
| 快按快放三下 | ||
| 按住大约 2 秒再松开 |
边做边想这四个问题(想到了可以问 AI 核对):
- 松手时线在上面还是下面?按住时呢?——你看到的这条线,就是"电平"。
- 按住的时间越长,下面那段线有什么变化?——线段的长度,就是时间。
- 从 1 变到 0 的那一瞬间,线是斜着过去的,还是竖着跳的?为什么?
- 慢慢按、快按快放,仔细看跳变的地方——线有时候会抖一下。想想这是为什么?(提示:真实按钮里的金属片,碰到一起时不会"啪"一下就稳,会像门碰到门框那样弹几下。)
重要提示:波形上画的是方方正正的台阶,不是平滑的曲线。因为主控看到的就只有"高"和"低"两种,中间没有别的值。这正是本课最该记住的一点:主控的世界里只有 0 和 1,没有"一半高"。
三、输入设备和输出设备
前面说 BOOT 是"输入"、RGB 灯是"输出",其实这两个词说的是一整类东西。
- 输入设备:把外界的消息送进板子。你按 BOOT,就是告诉板子"有人按我了"。
- 输出设备:把板子的结果表现出来。灯亮起来,就是板子在回应你。
世界上这样的设备很多,我们这块板子上就有好几个:
| 板上就有的 | 别的地方常见的 | |
|---|---|---|
| 输入设备 | BOOT 按钮、麦克风、触摸屏、光线传感器 | 键盘、鼠标、摄像头、温度计 |
| 输出设备 | RGB 灯、屏幕、喇叭 | 打印机、电机、振动马达 |
看出来了吗?键盘和按钮是一类东西,屏幕和灯是一类东西——它们只是"收消息"和"送消息"的方式不同。
让 AI 带你去身边找一找(这一节重点不在背名词,在于你自己能认出来):
请带我在身边找一找常用的「输入设备」和「输出设备」。
先只讲「输入设备」:举 5 个我家里或教室里天天见到的东西(例如按钮、话筒),
每说一个,先问我"它把什么消息送进机器",等我回答你再补充。
讲完输入,再讲「输出设备」,同样举 5 个(例如喇叭、屏幕)。
最后问我一个问题:有没有一样东西,既是输入又是输出?为什么?
一次只讲一个,不要列长表格,不要先讲电路和代码。
找完之后回到我们这块板子:BOOT 按钮是输入设备,RGB 灯是输出设备。以后学到触摸屏、麦克风、扬声器,你会发现它们也都是这两类里的成员。
四、一个按钮,能做出几种事件?
第一节那个 A/B/C 程序,三种玩法用的是同一个按钮、同一颗灯,为什么效果完全不同?
关键在于:板子读到的只是"此刻是 0 还是 1",至于这一下算什么意思,是程序自己判断出来的。 换个判断方式,同一根手指就能做出不同的事。
| 玩法 | 程序怎么"判断",效果就不同 |
|---|---|
| A 按住亮灯 | 不用记,直接看"此刻是 0 吗"——按住就是 0,所以亮;松开变 1,就灭 |
| B 开关灯 | 要记住"灯现在是亮还是灭",只在"刚变成 0"的那一刻把状态翻一下 |
| C 换随机颜色 | 同样只在"刚变成 0"那一刻做一次,只不过做的事是换个颜色 |
顺着这个思路再往下想一步:如果判断的不是"此刻是不是 0",而是**"两次按下之间隔了多久"**——是不是就能认出更多花样?
| 事件 | 怎么按 | 程序怎么判断 | 灯色 |
|---|---|---|---|
| 单击 | 快速按一下 | 松开后等一小会儿,没有第二下 | 绿 |
| 双击 | 连着快按两下 | 两下之间不超过 350 毫秒 | 蓝 |
| 长按 | 按住不放手 | 按住超过 800 毫秒 | 红 |
| 三击? | 连着快按三下 | 交给你想(见下面的挑战) |
注意看:板子从头到尾只做了两件事——按下、松开。 这些"事件"全都是程序用时间量出来的。
这就像你敲门:敲一下、敲两下、一直按着门铃不放——门里的人都听得懂,但靠的是节奏,不是力度。
让 AI 帮你做出这三种事件:
请新建一个教学程序:用板子上的一个 BOOT 按钮,做出单击、双击、长按三种事件。
单击=快速按一下(松开后等一小会儿,没有第二下,才算单击);
双击=连着快按两下(两下之间不超过 ___ 毫秒);
长按=按住不放手超过 ___ 毫秒。
屏幕上显示现在按下了还是松开了、刚刚识别到哪种事件、单击双击长按各发生了几次;
再画一个"按住进度条",按得越久条越长,快满时就是快要算长按了。
三个事件各用一种颜色点灯:单击时亮 ___ 颜色,双击时亮 ___ 颜色,长按时亮 ___ 颜色。
请做消抖,并使用中文注释。
编译和烧录前先运行 arduino-cli board list,确认目标端口后再操作。
先别急着发给 AI —— 上面有 5 个空要你自己填。 填之前先想两件事:
- 两个"毫秒"数填多少才合适?想想你平时双击鼠标有多快、按住多久才算"长按";
- 三种颜色你想怎么配?建议挑三种一眼能分开的颜色(比如红/绿/蓝),别选两个相近的,否则你自己都看不出刚才触发的是哪个。
想好了再点开:我们的参考数字
我们程序里用的是 350 毫秒(双击间隔)和 800 毫秒(长按门槛)。
这只是一个可用的选择,不是标准答案。填大了,双击会被当成两次单击;填小了,正常速度的双击反而认不出来。你可以先用参考值跑通,再故意改成 100 毫秒或 2000 毫秒试试——亲眼看它怎么"认错",比记住数字有用得多。
动手:三种事件各来一遍
烧录后,三种事件各做几遍,把观察填进去:
| 我做的动作 | 屏幕显示的事件 | 次数对上吗 |
|---|---|---|
| 快速按一下 | ||
| 连着快按两下 | ||
| 按住 2 秒 |
重点观察两件事:
- 单击是不是"慢半拍"才出现?(下一节就讲为什么)
- 双击的时候,屏幕上会不会先闪出一次"单击"?如果会,说明等待窗口设得太短了——这是个很好的问题,记下来问 AI。
五、单击为什么要等一下才出来?
你按了一下,松开手。这时候板子没法立刻知道你是不是还要按第二下。
所以它只能等一小会儿(比如 350 毫秒):
- 这段时间里 安安静静 → 那就是单击;
- 这段时间里 又来了一下 → 那是双击,单击就不出现了。
这个等待就像别人说话时先停一下,看你还说不说。
"等多久"这个数字是设计者定的规则。等得太短,你想双击,板子却认成"两次单击";等得太长,单击就会显得"慢半拍"。
让 AI 给你讲讲这个取舍:
我发现单击不是马上出现的,要等一下才显示。
请解释:为什么板子不能一松手就立刻知道这是单击?
它在等什么?如果把等待时间调短会怎样?
请用"等你说完话我才知道你是不是还要再说"这样的比喻讲一遍。
动手:把等待窗口调短试试
刚才你填的那个"双击间隔"毫秒数,就是等待窗口。现在故意把它改小,看会发生什么:
请把双击的等待时间改成 80 毫秒,其它都不要动。
烧录后告诉我该重点观察什么。
烧录后正常速度双击几次,然后填一下:
| 我把等待窗口改成 | 双击时屏幕上发生了什么 | 我猜是为什么 |
|---|---|---|
| 原来的值 | ||
| 80 毫秒 |
改小之后,你多半会看到双击被拆成了两次单击。再改大到 2000 毫秒试试——这回单击是不是慢得让人着急?
这就是设计里的取舍:等待窗口太大,反应迟钝;太小,双击认不出来。没有"最对"的数字,只有"更适合"的数字。
六、动手做
前面每一节你其实都已经动过手了(A/B/C 三种玩法、示波器、三种事件)。 这一节留给还没做过的新花样——都要用到今天学的东西,但换个玩法。
作品 1:猜颜色(彩虹定格机)
前面 C 玩法是"每按一下换一个随机颜色"。现在换成跑马灯:灯自己飞快地循环变色,你按一下把它定住——像玩"转盘抽奖":
请做一个"猜颜色"小游戏:
RGB 灯每 200 毫秒在红、绿、蓝、黄、紫之间循环,亮度较低。
按下 BOOT 时锁定当前颜色并停止闪烁;让屏幕显示当前锁定的颜色。
再次按下开始下一轮。每次按下只触发一次,必须消抖。
请先画出"输入—规则—输出"的流程,再编译烧录。
观察:屏幕显示的颜色和灯一致吗?连按两次会不会跳过一轮?(试试看,这个现象值得追问 AI。)
作品 2:会呼吸的、能调模式的灯
第一节的 B 玩法其实就是个开关灯。现在把它做得像家里真正的那盏灯:不是"啪"一下亮起来,而是像开灯时那样慢慢亮起来;而且不只是白灯,还能换几种光。
请在这个开关灯的基础上改,做一个"会呼吸的灯":
【开关】BOOT 按钮用来开灯、关灯(还是按一下开、再按一下关)。
【渐变】灯不要"啪"一下就亮/灭,要慢慢过渡:
开灯时亮度从 0 一点一点涨到最亮,关灯时从最亮慢慢降到 0,
每一格大约走 ___ 毫秒,让人看得出它在"呼吸"。
【模式】屏幕上画几个模式按钮,点一下切换:
至少要有一个 ___ 模式(颜色偏暖,像老式灯泡)
和一个 ___ 模式(三个通道差不多,就是白光)。
你想再加别的模式也行,自己起名字。
【提示】屏幕上显示:现在是什么模式、灯是开着还是关着、BOOT 按了几次。
【安全】亮度不要太高,别刺眼。
请解释:灯"是开还是关"这个状态记在哪里?为什么按住按钮不会反复切换?
编译和烧录前先运行 arduino-cli board list,确认目标端口后再操作。
这次有 4 个空。 填之前想一想:
- 每格多少毫秒?这决定了"呼吸"是快是慢——太快就像闪,太慢你会等得不耐烦。
- 两种模式叫什么、颜色怎么配?提示里给了线索(一个偏暖、一个发白),名字由你来取。
- 屏幕上的按钮点一下就能换模式——这部分我们还没学过触摸屏(第 8 课才讲),照抄"点一下就切换"的说法就行,当黑盒用。
想好了再点开:我们的参考
- 渐变:每 8 毫秒走一格(100 格走完约 0.8 秒),看起来就是一次呼吸
- 两种模式叫 暖暖光(红 40 / 绿 22 / 蓝 6,偏暖)和 白光(32/32/34,三色差不多)
- 我们还多加了一种 夜灯(8/5/2,同样是暖色但整体很暗),你也可以自己加一种
这不是标准答案。 你可以把 8 毫秒改成 3 毫秒试试——会变成"闪"而不是"呼吸";再改成 40 毫秒,就慢得像日出。
猜一下:程序"记住开还是关",是存在哪里的?(提示:不是存在纸上,也不是存在云端——就是上一课说的主控的内存里。)
挑战 1:反应力挑战
让灯等待一段随机时间后变绿。看到绿灯后,尽快按下 BOOT——看谁反应快:
请做一个反应力挑战:
开始后等待一段随机时间,RGB 灯变成 ___ 色(我用这个颜色表示"可以按了");
从灯变色开始计时,按下 BOOT 后停止计时;
把反应时间用毫秒显示在屏幕上,例如"用时 ___ 毫秒";
灯变色之前按下,显示"___",并等待下一轮。
请保留开始、等待、成功、抢跑这几个状态,使用消抖,只用屏幕显示结果。
这里也有空要填:选一种"可以按了"的颜色,想一句"抢跑"该说的话("抢跑""太早了""手快了"都行,你自己挑),还有开头那句提示文字写什么。
提醒:颜色要和红灯分得开——后面有个状态灯是红的,别撞色,不然你会分不清现在该等还是该按。
"毫秒"是千分之一秒——屏幕上的是电脑测量出来的时间,不是人眼估的。连做五次,记录最短和平均用时。先想一个问题:为什么要在"灯变色之前按下"算抢跑?这利用了今天学的哪个判断?
挑战 2:三击,能不能做?
我们做了单击、双击、长按。那三击呢?先别急着让 AI 写,先自己想两个问题:
- 如果板子要认出"三击",它得等到什么时候才能确定你按完了三下、不会有第四下?
- 这样一来,你按完第三下之后,屏幕上要等多久才出现"三击"?
想好了再去问 AI:
在刚才那个单击/双击/长按的程序上,请再加一个"三击"(连着快按三下)。
三击和双击的等待时间,我打算这样定:
等第二下的窗口还是 ___ 毫秒(保持不动),
但等第三下的窗口我给它 ___ 毫秒 —— 请按我这个数写。
先告诉我:加了它以后,单击的等待时间会不会变长?为什么?
请只改这一个功能,保留原来三种事件的判断,并解释你改动了哪些数字。
注意这里挖的空和前面不一样:前面是让你挑一个"更合适"的值,这次是让你故意定一个数,然后看后果。 你可以填一个很大的数(比如 1500),看看单击会变得多迟钝;也可以填个很小的数(比如 100),看看三击还认不认得出来。 怎么填都行——你从结果里发现了什么,才是这个挑战真正要的东西。
这个挑战的答案不重要,你发现"等待时间会被拉长"这件事才重要。
七、自检小测
先自己想,再点开对答案。
1. 为什么说 BOOT 是输入、RGB 灯是输出?
输入把外界消息送进板子(按钮把手指动作变成电平);输出把结果表现出来(灯把程序结果变成光)。中间 ESP32-S3 做"处理"。
2. 按下去的时候,程序读到的是 0 还是 1?
本板上按下是 LOW,按约定记成 0;松开是 HIGH,记成 1。(以本板资料和实测为准,因为不同板子可能接法不同。)
3. 为什么程序要记住"上一次"按钮状态?
为了区分"刚按下"和"一直按着"。只有上一次是松开、这次变按下,才算一次新按下;一直按着就不重复处理,否则按住一秒灯会疯狂换色。
4. 板子只有"按下/松开"两个动作,为什么能认出双击?
因为程序记住了时间。它比较两下之间的间隔:够短就当成双击。单击、双击、长按的差别不在"按得多用力",而在"按的节奏",节奏是靠计时量出来的。
5. 为什么单击不是一松手就出现?
因为板子还不知道你会不会接着按第二下,必须等一小会儿(等待窗口)。窗口内没有第二下,才确认是单击。所以"等多久"这个规则,直接决定了单击的反应快慢。
6. 开关灯作品里,"现在是开还是关"记在哪里?
记在主控的内存里(一个会变化的变量)。程序按一下就把这个状态翻一次面,再决定输出什么。
7. 下面这几个,哪些是输入设备、哪些是输出设备?—— 键盘、喇叭、摄像头、屏幕、温度计
输入(把消息送进机器):键盘、摄像头、温度计; 输出(把结果表现出来):喇叭、屏幕。
记不住就想想:"是我在告诉机器,还是机器在告诉我?"
八、还想玩点什么
一个按钮 + 一颗灯,可以玩出不少花样:
| 方向 | 可以描述给 AI 的效果 | 值得继续想 |
|---|---|---|
| 彩虹定格机 | 灯不停变色,按一下定住,屏幕显示颜色名 | 锁定的是哪一刻的哪种颜色? |
| 单键小夜灯 | 一下开、一下关,带屏幕状态显示 | 程序怎么"记住"开关状态? |
| 反应力大赛 | 随机变绿后计时,比谁按得快 | 随机时间真的"随机"吗?怎么验证? |
| 摩斯电码 | 按的时间长短不同,灯亮长短不同 | 多长算"长"?这个标准谁定? |
| 密码门铃 | 按固定节奏(快-快-慢)灯才亮 | 板子怎么知道节奏对不对? |
| 三击彩蛋 | 连按三下触发一个隐藏灯色 | 等待窗口要给多长? |
| 揪出按钮的"抖动" | 做 A/B 两版对比:A 读到 0 就执行、B 只在刚按下时执行一次 | 为什么按住不放时 A 会疯狂重复、B 只做一次? |
想做"屏幕上有按钮、能点能滑"的同学,把想法记下来——那是触摸屏的事,会在后面课程专门学。
下一课,我们把主角从一颗小灯换成一块大屏幕:让整块屏幕亮出一种颜色。到时候你会发现,同样叫"变红",屏幕和灯干的事可完全不一样。