CHAPTER 11 / FIELD GUIDE
项目一:桌面调光器
把旋钮、按键、LED 和屏幕连成产品。
先定义用户看见的行为
旋钮决定亮度百分比;按键切换输出开关;OLED 显示 000–100 和亮度条,左上角实心方块表示输出已启用。关闭时保留旋钮读数,但 LED 熄灭。
| 模块 | 引脚 / 协议 | 更新节奏 |
|---|---|---|
| LED | GPIO4,经 330 Ω 到 LED / GND | PWM 硬件持续运行 |
| 按键 | GPIO5 到 GND,内部上拉 | 主循环采样 + 30 ms 消抖 |
| 旋钮 | 中点 GPIO1,两端 3V3/GND | 约每 10 ms 加循环耗时 |
| OLED | SDA8 / SCL9 | 约 200 ms 触发刷新 |
实验工程 · 07_dashboard
这是第一个综合成品。所有外设接线与前面单独实验一致。
打开 main.c · 查看公共驱动 lab.c · 下载全部工程
#include "lab.h"
#include "esp_log.h"
void app_main(void) {
button_init();
adc_init();
pwm_init();
oled_init();
bool enabled=true;
int value=adc_read_raw();
int64_t screen_at=0;
for(;; ) {
if(button_pressed()) {
enabled=!enabled;
ESP_LOGI("ui","enabled=%d",enabled);
}
value=(7*value+adc_read_raw())/8;
int percent=value*100/4095;
pwm_set(enabled?value*1023/4095:0);
if(now_ms()-screen_at>=200) {
screen_at=now_ms();
oled_clear();
oled_number(40,8,(unsigned)percent,3);
if(enabled)oled_rect(4,4,6,6);
oled_rect(4,46,percent*120/100,8);
oled_show();
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}分析它的限制
OLED 100 kHz 传输一帧的理论位传输时间已经接近 100 ms,实际还有协议开销。这段时间主循环不读按键,极短的点击可能漏掉。此项目适合慢速人机交互;第 12 章会用任务和队列隔离采样与显示。
验收矩阵
| 操作 | 预期 |
|---|---|
| 旋钮最小到最大 | 数字和亮度条整体递增,LED 随之变化 |
| 输出开启时按键 | 方块消失,LED 熄灭 |
| 关闭时旋转 | 数字仍更新,LED 保持熄灭 |
| 再次按键 | 恢复当前旋钮设定,而非旧的固定亮度 |
| 断电重启 | 按当前代码默认开启;下一章扩展可设计为默认关闭 |
独立修改任务
把上电默认状态改为关闭;增加一个“锁定读数”的状态;为每个状态写出操作表,再实现。先保留原工程,给修改版单独目录,便于比较。
停下来想一想
为什么屏幕显示 50% 时,不能承诺人眼看到的亮度正好是 100% 的一半?
查看推导与答案
显示的是控制量比例,视觉感受、LED 特性和实际驱动电流都影响主观亮度。产品界面需要说明数值代表什么。
本章验收
本章一手资料
卡住时可以直接向我提问:附上章节号、工程名、接线和第一条错误日志。