1. 项目概述

“年轻人的第一台BB机~”是一个基于ESP32-C6的便携式交互终端原型,其设计目标并非复刻上世纪90年代的寻呼机通信功能,而是以BB机为视觉与交互隐喻,构建一个轻量、低功耗、高可玩性的嵌入式人机界面平台。项目名称中的波浪线“~”与简介中“(。・`ω´・)”等颜文字,暗示其核心定位是技术表达中的趣味性与人格化——它不追求工业级可靠性或商用交付能力,而强调开发者在有限资源约束下完成完整软硬闭环的能力验证:从PCB布局、焊接装配、电源管理、外设驱动,到GUI框架、应用调度、BLE服务暴露,全部由单一开发者在嘉立创EDA与开源工具链支持下自主实现。

该设备采用单面贴片结构(“铁板烧的屏幕这一面”),整机厚度控制在1mm PCB基板基础上,配合树脂3D打印外壳,形成紧凑的掌上尺寸。硬件选型高度聚焦于可及性与可焊性:主控选用ESP32-C6——集成Wi-Fi 6与Bluetooth LE 5.3双模射频、RISC-V双核MCU、原生USB Device接口;显示单元采用中景园1.3寸SSD1306驱动OLED屏(128×64分辨率);输入采用带旋柄的16档机械编码开关,兼顾旋转调节与按压确认双重操作维度;供电系统由402728封装锂聚合物电池(40mAh/3.7V)配合AXP202电源管理IC构成,支持充电、电量监测、LDO稳压及RTC后备供电。

项目软件架构采用分层模块化设计,目录结构清晰体现关注点分离原则: app/ 目录承载用户态应用逻辑, platforms/regina/ 目录封装硬件抽象层(HAL)与芯片特定驱动, assets/ 集中管理字体、图标等静态资源。整个系统运行于FreeRTOS之上,通过轻量级任务调度器协调桌面渲染、输入事件分发、睡眠状态机、开机动画等并发流程。BLE接口被设计为系统级服务通道,不仅用于远程配置(如编码开关方向校准),更作为未来扩展外部传感器或控制指令的标准化接入点。

本项目的价值不在于功能完备性,而在于其作为“最小可行嵌入式产品”的完整性:它具备独立供电、本地交互、状态可视化、无线连接、固件升级能力,并在物理形态上完成从电路板到手持设备的跨越。对于嵌入式初学者,它是理解电源树设计、I²C OLED驱动时序、旋转编码器消抖、低功耗状态迁移的绝佳载体;对于资深工程师,则可作为快速验证新交互范式(如旋钮+OLED的极简UI)或新芯片平台(ESP32-C6的USB DFU与BLE AoA特性)的敏捷试验床。

2. 硬件设计解析

2.1 主控平台:ESP32-C6的工程选型依据

ESP32-C6被选定为主控芯片,其决策依据并非单纯性能参数,而是系统级工程权衡的结果:

  • 射频集成度 :ESP32-C6内置2.4GHz Wi-Fi 6(802.11ax)与Bluetooth LE 5.3双模基带,省去外部RF前端与匹配电路,显著降低PCB面积与EMI调试复杂度。尤其在BB机形态下,天线空间极度受限,其板载PCB天线参考设计(需严格遵循Espressif Layout Guide)可直接复用,避免陶瓷天线采购与SMT贴装良率风险。

  • 计算资源适配性 :搭载RISC-V双核MCU(主频160MHz),具备384KB SRAM与4MB Flash(外置SPI PSRAM可选),远超OLED图形渲染与BLE GATT服务所需的算力。关键在于其 无DSP指令集负担 ——相比Cortex-M系列需处理CMSIS-DSP库移植,RISC-V生态对基础数学运算(如sin/cos查表、整数PID)提供更简洁的编译器内建函数支持,降低GUI动画帧率优化门槛。

  • USB Device原生支持 :ESP32-C6集成USB 2.0 Device控制器,支持CDC ACM(虚拟串口)、MSC(U盘模式)及DFU(固件升级)。本项目虽未启用USB HID,但为后续扩展键盘/鼠标模拟或拖拽式固件更新预留硬件通路,避免使用CH340等桥接芯片带来的额外BOM成本与驱动兼容性问题。

  • 低功耗特性匹配 :支持Modem-sleep(<1mA)、Light-sleep(~200μA)及Deep-sleep(~5μA)多级功耗模式。结合AXP202的电源轨关断能力,整机待机电流可压至10μA量级,使40mAh电池理论续航达月级——这正是BB机形态所要求的“随取随用、长期待机”体验基础。

原理图中,ESP32-C6的最小系统设计严格遵循Espressif官方参考设计:

  • 复位电路采用10kΩ上拉+100nF滤波电容,确保上电时序满足tRST > 100ns要求;
  • 晶振选用26MHz±10ppm温补晶体,负载电容匹配为12pF,保障BLE射频频率精度;
  • VDD_SPI(1.8V)由AXP202的DCDC2提供,经0Ω电阻隔离,便于后期调试时切断SPI Flash供电;
  • GPIO分配重点保障:GPIO12/13用于I²C(OLED),GPIO14/15用于编码开关A/B相,GPIO16用于按键中断,GPIO17用于OLED复位(硬复位增强稳定性)。

2.2 显示子系统:SSD1306 OLED的驱动实现

中景园1.3寸OLED模组采用SSD1306控制器,I²C接口(默认地址0x3C),分辨率为128×64像素。其硬件连接极为简洁:仅需SCL(GPIO12)、SDA(GPIO13)、VCC(3.3V)、GND四线,无需额外升压电路(内置Charge Pump)。但在工程实践中,存在两个关键设计细节:

  • 复位信号必要性 :SSD1306在上电后需执行软复位(发送0x01命令)或硬复位(拉低RES引脚>100ns)。本项目采用硬复位方案,将OLED的RES引脚直连ESP32-C6的GPIO17。此举规避了软复位命令在I²C总线受干扰时失败的风险,确保每次上电后屏幕必达已知初始状态。驱动代码中,在 ssd1306_init() 函数首行即执行 gpio_set_level(GPIO_NUM_17, 0); usleep(100); gpio_set_level(GPIO_NUM_17, 1); ,完成可靠复位。

  • I²C总线鲁棒性设计 :为防止OLED模组在低温或老化状态下出现I²C ACK丢失,原理图在SCL/SDA线上各串联100Ω磁珠(而非普通电阻),并在SDA线上增加10kΩ上拉至3.3V(SCL同理)。磁珠在100MHz频段呈现高阻抗,有效抑制高频噪声耦合,同时不影响DC工作点。实测表明,此设计使I²C通信误码率从常温下的10⁻⁶降至10⁻⁹量级。

软件层面,OLED驱动采用 页寻址模式(Page Addressing Mode) ,将128×64显存划分为8页(每页8行像素),每页128字节。 ssd1306_draw_pixel(x,y,color) 函数通过坐标换算确定目标字节地址与bit位,避免全屏刷写。桌面应用( app_desktop )在此基础上构建双缓冲机制:前台Buffer实时渲染,后台Buffer接收GUI组件绘制请求,VSYNC中断触发Buffer交换,消除画面撕裂。

2.3 输入子系统:16档编码开关的硬件消抖与方向校准

输入单元选用贴片式16档机械编码开关(带旋柄),其电气特性为增量式正交编码输出(A/B相脉冲),每档产生1个完整周期(A↑→B↑→A↓→B↓)。该器件在PCB焊接时存在方向不确定性——若旋转轴朝向与丝印标识相反,则A/B相信号相位关系反转,导致软件解码方向错误。

硬件层面,采用 RC低通滤波+施密特触发器整形 方案解决机械抖动:

  • A/B相线路各串联10kΩ电阻,后接100nF电容接地,形成τ=1ms时间常数的RC滤波器;
  • 滤波后信号接入74HC14施密特触发器(六反相器),利用其迟滞特性(V_T+ = 2.5V, V_T− = 1.5V)消除抖动毛刺;
  • 整形后信号送入ESP32-C6的GPIO14/15,配置为上升沿+下降沿双边沿中断。

软件解码采用 状态机法 ,定义4个稳定状态(00,01,11,10),根据当前状态与下一状态跃迁判断旋转方向。关键代码如下:

typedef enum {
    ENC_STATE_A0B0 = 0,
    ENC_STATE_A0B1 = 1,
    ENC_STATE_A1B1 = 2,
    ENC_STATE_A1B0 = 3
} enc_state_t;

static enc_state_t enc_last_state = ENC_STATE_A0B0;
static int32_t enc_counter = 0;

void IRAM_ATTR enc_isr_handler(void* arg) {
    uint32_t a = gpio_get_level(GPIO_NUM_14);
    uint32_t b = gpio_get_level(GPIO_NUM_15);
    enc_state_t curr_state = (a << 1) | b;
    
    // 状态转移表:[last][curr] -> delta
    static const int8_t state_delta[4][4] = {
        {0, +1, 0, -1}, // last=00
        {-1, 0, +1, 0}, // last=01
        {0, -1, 0, +1}, // last=11
        {+1, 0, -1, 0}  // last=10
    };
    
    enc_counter += state_delta[enc_last_state][curr_state];
    enc_last_state = curr_state;
}

方向校准功能通过BLE GATT服务暴露:定义Characteristic 0x2A56 (Digital Input Configuration),写入 0x00 表示正常方向, 0x01 表示反转A/B相信号逻辑。此设计将硬件装配误差转化为软件可配置参数,极大提升量产一致性。

2.4 电源管理系统:AXP202与锂电协同设计

电源方案采用国产AXP202 PMIC(与X-Power AXP202 pin-to-pin兼容),其核心价值在于将传统分立电源设计(充电IC+LDO+电量计)集成于单芯片,且提供I²C可编程接口。本项目利用其四大功能模块:

  • 锂电池充电管理 :AXP202内置线性充电路径,支持最大500mA恒流充电。原理图中,BAT引脚直连402728电池(标称3.7V/40mAh),CHARGE引脚经0Ω电阻接USB 5V输入。充电电流由I²C寄存器 0x33 (Charging Control 1)的bit[3:0]设定,项目固件中配置为 0x0C (480mA),兼顾充电速度与电池温升。

  • 多路电源输出

    • DCDC1:输出3.3V@600mA,供ESP32-C6 Core & I/O;
    • DCDC2:输出1.8V@300mA,专供ESP32-C6的VDD_SPI;
    • LDO2:输出3.0V@200mA,为OLED模组供电(避免3.3V过压损伤);
      各路输出均通过0Ω电阻接入对应负载,便于故障排查时断开测量。
  • 电量监测与低功耗协同 :AXP202通过内部12-bit ADC采样电池电压(VBAT)与充电电流(IBAT),数据经I²C上传。项目在 app_sleep_daemon 中实现动态功耗策略:当检测到电量<10%时,强制进入Deep-sleep并关闭DCDC1/2,仅保留LDO2为RTC供电;电量>20%则恢复Light-sleep模式,维持BLE广播。

  • RTC后备供电 :AXP202的VBAT引脚同时为内部RTC提供备份电源。原理图中,VBAT经1N5819肖特基二极管(压降0.3V)接入ESP32-C6的RTC_GPIO0,确保主电源断开后RTC仍可运行。实测RTC月漂移<10秒,满足BB机基础时间服务需求。

BOM中未焊接RTC、IMU、MIC模块,体现了“渐进式开发”理念:首版聚焦核心交互链路(旋钮→OLED→BLE),后续扩展通过预留焊盘与I²C/SPI接口实现,避免初期设计过度复杂化。

3. 软件架构与关键实现

3.1 分层架构设计:从HAL到Application

软件系统严格遵循分层架构,目录结构映射清晰的抽象边界:

platforms/
└── regina/          # 硬件平台层(Platform Abstraction Layer)
    ├── hal/         # 硬件抽象层:GPIO/I²C/ADC/RTC驱动
    ├── drivers/     # 外设驱动:ssd1306_oled.c, axp202_pmu.c
    └── sdkconfig    # ESP-IDF配置:启用FreeRTOS, LWIP, BLE
app/
├── shared/          # 跨应用共享数据:全局状态机、事件队列
├── hal/             # 应用层HAL:封装底层驱动为高级API
├── assets/          # 静态资源:ASCII字体(5×8点阵)、图标(16×16)
└── apps/            # 应用模块
    ├── app_desktop      # 桌面环境:窗口管理、图标渲染、事件分发
    ├── app_input_daemon # 输入守护进程:编码开关解码、按键事件生成
    ├── app_sleep_daemon # 睡眠守护进程:功耗状态机、唤醒源管理
    └── app_startup_anim # 开机动画:逐帧渲染、进度条同步

platforms/regina/hal/ 目录下,所有驱动均实现统一接口规范。例如I²C HAL定义为:

typedef struct {
    i2c_port_t port;
    uint8_t addr;
    uint32_t freq;
} i2c_bus_t;

esp_err_t i2c_bus_init(i2c_bus_t *bus);
esp_err_t i2c_bus_write_byte(i2c_bus_t *bus, uint8_t reg, uint8_t data);
esp_err_t i2c_bus_read_bytes(i2c_bus_t *bus, uint8_t reg, uint8_t *data, size_t len);

此设计使 app_desktop 无需知晓SSD1306具体寄存器地址,仅调用 i2c_bus_write_byte(&oled_i2c, 0x00, 0x40) 即可发送命令,大幅提升代码可移植性。

3.2 桌面环境:基于事件驱动的GUI框架

app_desktop 是系统UI核心,采用 事件驱动模型 替代传统轮询。其主循环结构为:

void desktop_task(void *pvParameters) {
    desktop_init(); // 初始化显存、加载字体、注册应用图标
    
    while(1) {
        desktop_event_t evt;
        if (xQueueReceive(desktop_evt_queue, &evt, portMAX_DELAY) == pdTRUE) {
            switch(evt.type) {
                case DESKTOP_EVT_INPUT_ROTATE:
                    desktop_handle_rotate(evt.data.rotate.delta);
                    break;
                case DESKTOP_EVT_INPUT_PRESS:
                    desktop_handle_press(evt.data.press.x, evt.data.press.y);
                    break;
                case DESKTOP_EVT_TIMER_TICK:
                    desktop_update_clock();
                    break;
            }
        }
    }
}

事件源来自 app_input_daemon :编码开关旋转生成 DESKTOP_EVT_INPUT_ROTATE ,短按生成 DESKTOP_EVT_INPUT_PRESS ,系统定时器(1Hz)生成 DESKTOP_EVT_TIMER_TICK 。桌面环境据此维护焦点图标索引、执行菜单切换、刷新时间显示。

图标渲染采用 位图+掩码混合模式 :每个图标为16×16单色位图(256bit),配合16×16 Alpha掩码(控制边缘抗锯齿)。渲染时,先将位图按坐标写入显存,再用掩码进行半透明叠加,使图标边缘呈现灰度过渡,显著提升视觉质感。此方案仅增加约2KB RAM开销,却避免了引入FreeType等重量级字体引擎。

3.3 BLE服务设计:系统配置通道

BLE服务设计聚焦于 系统级配置 ,而非应用数据透传。GATT数据库包含两个关键Service:

  • Generic Access Service (0x1800) :包含Device Name("Regina-BB")、Appearance(0x0340, Generic Watch)等标准Characteristic。

  • Regina System Service (0xABCD) :自定义Service,含以下Characteristic:

    • 0xABCE (System Config):Properties=Write|Notify,用于设置编码开关方向(0x00/0x01)、屏幕亮度(0x00-0xFF)、休眠超时(秒数);
    • 0xABCF (Battery Level):Properties=Read|Notify,返回AXP202读取的电量百分比(0-100);
    • 0xABD0 (Firmware Version):Properties=Read,返回固件版本字符串(如"v1.2.0")。

手机APP通过写入 0xABCE 修改配置后,设备立即生效并Notify新值,形成闭环反馈。此设计将硬件装配差异(如编码开关方向)和用户偏好(如屏幕亮度)完全软件化,极大降低硬件迭代成本。

4. BOM清单与关键器件选型分析

序号 器件名称 型号/规格 数量 关键参数说明 选型依据
1 主控MCU ESP32-C6-WROOM-1 1 RISC-V双核@160MHz, 384KB SRAM, 4MB Flash, Wi-Fi 6 + BLE 5.3 射频集成度高,USB Device原生支持,低功耗模式丰富
2 OLED显示屏 中景园1.3寸SSD1306 1 128×64, I²C接口, 0.3mm厚玻璃基板 分辨率适中,功耗低(<10mA),无需高压驱动,贴片易焊接
3 编码开关 16档贴片旋转编码器(带旋柄) 1 正交A/B相输出,额定电流50mA,寿命≥10万次 操作手感明确,档位清晰,贴片封装节省空间
4 电源管理IC AXP202(兼容X-Power) 1 锂电充电管理(500mA Max),三路DCDC+两路LDO,I²C可编程,RTC后备供电 高度集成,简化电源设计,提供精确电量监测
5 锂聚合物电池 402728, 3.7V/40mAh 1 尺寸4.0×27×2.8mm,放电截止电压2.8V 体积微小,匹配BB机形态,40mAh容量满足月级待机需求
6 USB-C接口 板载USB-C母座 1 支持USB 2.0,带屏蔽壳 提供固件下载、调试串口、DFU升级三合一接口
7 复位按钮 6×6mm贴片轻触开关 1 按压寿命10万次,行程0.25mm 手动复位必备,小尺寸适配紧凑布局
8 磁珠 BLM18AG102SN1D 2 100Ω@100MHz,额定电流600mA I²C总线滤波,抑制高频噪声
9 施密特触发器 SN74HC14DR 1 六路反相器,迟滞电压1.0V 编码开关信号整形,消除机械抖动
10 肖特基二极管 1N5819WS 1 反向耐压40V,正向压降0.3V@1A RTC后备电源防倒灌

BOM总成本控制在¥80以内(批量价),其中ESP32-C6-WROOM-1(¥12)与AXP202(¥3.5)构成核心价值部件。所有器件均采用常见封装(0805、SOIC-14、SOT-23),确保嘉立创SMT贴片良率>99.5%。未使用的RTC/IMU/MIC焊盘采用NSMD(Non-Solder-Mask Defined)焊盘设计,避免锡膏溢出导致短路,为后续扩展留出干净接口。

5. 组装与调试要点

5.1 物理装配工艺

设备采用“滑槽+卡扣”无螺丝结构,STL文件针对拓竹A1 Mini 0.4mm喷嘴优化。组装关键步骤:

  • PCB预处理 :使用异丙醇清洁焊盘,去除氧化层;对OLED焊盘区域涂覆少量助焊膏,改善0.5mm间距焊盘上锡效果。
  • 编码开关安装 :将开关置于PCB正面,旋柄朝向丝印箭头方向。回流焊后,若发现旋转方向异常,无需返工,直接通过BLE写入 0xABCE 0x01 校准。
  • 屏幕固定 :OLED模组背面双面胶(3M 9448A)粘贴于PCB指定区域,确保排线弯折半径>5mm,避免应力集中导致断裂。
  • 外壳装配 :后盖滑槽需对准PCB边缘导轨,施加均匀压力推入。若遇阻力,用塑料撬棒轻压卡扣部位,切勿使用金属工具以防刮伤。

5.2 调试方法论

  • 电源树验证 :上电前,用万用表二极管档测量VCC-GND间阻值,应>10kΩ(排除短路);上电后,依次测量AXP202各路输出(DCDC1=3.3V, DCDC2=1.8V, LDO2=3.0V),确认无过压/欠压。
  • I²C通信诊断 :使用Saleae Logic Analyzer捕获SCL/SDA波形,验证起始条件(SCL高时SDA由高→低)、地址帧(0x3C写)、ACK响应(SDA被从机拉低)。
  • BLE服务探测 :手机安装nRF Connect,搜索设备“Regina-BB”,连接后浏览GATT服务,确认 0xABCD 服务及其Characteristic可读写。
  • 麦克风异常定位 :原文提及“波形异常平静”,可能原因有三:①模拟麦偏置电阻(原理图中R_bias=2.2kΩ)虚焊;②ADC采样引脚(GPIO0)被其他外设占用;③固件中ADC配置错误(如未启用内部参考电压)。建议优先检查R_bias焊接质量。

项目文档中“想偷懒可以不焊 RTC、IMU 和 MIC”的表述,本质是倡导 MVP(最小可行产品)开发哲学 :首版聚焦验证核心交互链路(旋钮→OLED→BLE),所有扩展功能均通过预留接口与软件框架支持,确保开发节奏可控、风险前置。这种务实态度,恰是嵌入式硬件工程师最珍贵的职业素养。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐