CHAPTER 11 / FIELD GUIDE

项目一:桌面调光器

把旋钮、按键、LED 和屏幕连成产品。

建议用时 60–90 分钟先预测,再实验,再解释

先定义用户看见的行为

旋钮决定亮度百分比;按键切换输出开关;OLED 显示 000–100 和亮度条,左上角实心方块表示输出已启用。关闭时保留旋钮读数,但 LED 熄灭。

模块引脚 / 协议更新节奏
LEDGPIO4,经 330 Ω 到 LED / GNDPWM 硬件持续运行
按键GPIO5 到 GND,内部上拉主循环采样 + 30 ms 消抖
旋钮中点 GPIO1,两端 3V3/GND约每 10 ms 加循环耗时
OLEDSDA8 / 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 特性和实际驱动电流都影响主观亮度。产品界面需要说明数值代表什么。

本章验收

本章一手资料

卡住时可以直接向我提问:附上章节号、工程名、接线和第一条错误日志。