立创开源基于STM32F103的智能波克布林宝箱桌面摆件设计与实现最近在立创开源社区看到一个特别有意思的项目——一个能自动开合的波克布林宝箱。这可不是普通的摆件它不仅能当Switch卡带收纳盒还能放戒指作为惊喜展示盒而且功能相当智能。作为一个嵌入式爱好者我立刻被吸引了决定复刻一个顺便把整个从硬件到软件的实现过程整理成教程分享给大家。这个宝箱的设计参考了甄大大开源的波克布林宝箱外观但作者重绘了外壳和PCB并编写了全新的代码增加了不少实用的智能功能。比如你可以双击它来开合它有振动反馈还能切换底座来适应卡带或戒指。更贴心的是它还设计了外力保护和低功耗管理防止宝箱被意外损坏也延长了电池续航。如果你也想动手做一个这样既好玩又有技术含量的桌面摆件或者想学习如何用STM32单片机结合舵机、触摸感应等模块来实现一个完整的智能硬件项目那么这篇教程就是为你准备的。我会从硬件选型、电路设计、软件编程到功能调试一步步带你走完整个流程。1. 项目概览与硬件清单咱们先来看看这个波克布林宝箱到底是个啥以及做它需要准备哪些“食材”。1.1 项目功能亮点这个宝箱不仅仅是个静态模型它集成了好几个智能交互功能让桌面摆件“活”了起来双击控制在宝箱的特定位置通过触摸感应实现快速双击可以控制宝箱盖的自动打开或关闭。这比物理按键更酷也更有科技感。振动反馈当宝箱执行开合动作或者检测到异常时会通过振动电机给出触觉反馈让交互更有实感。底座可切换设计了两款底座一款适合放置Switch游戏卡带另一款适合放置戒指。你可以根据需求自由更换实现一物多用。外力保护机制这是一个非常实用的安全设计。震动提示当宝箱盖打开时如果受到过大的外力比如有人想强行关上它会通过振动发出警告。自动保护如果外力持续过大系统会自动进入保护模式可能是停止舵机动作或进入特定状态防止机械结构或电机损坏。无缝按键使用TTP223触摸感应芯片实现了无物理开孔的触摸按键让宝箱外观更完整、精致。低功耗管理当电池电量低时系统会自动进入休眠模式切断不必要的功耗保护锂电池不会因过放而损坏。1.2 核心硬件清单与选型做硬件项目第一步就是把物料备齐。下面这个表格是我根据开源资料整理的BOM物料清单包含了所有关键元器件。你可以照着买也可以根据手头有的物料进行等效替换注意引脚和参数要匹配。材料数量说明与选型要点主控芯片STM32F103C6T61执行机构舵机 SG901用户交互TTP223触摸按键模块1电源管理锂电池 (350mAh)1锂电池充电模块1AMS1117-3.31L7805ABD2T-TR1状态指示RGB全彩LED模块2LED硬灯条1电流检测INA219AIDR1辅助元件拨动开关 (SS12D11)1FPC/FFC软排线及接插件1套结构外壳3D打印外壳 (PLA材料)1套提示表格中的电阻、电容如100nF, 4.7kΩ是电路中的必要元件用于滤波、上拉/下拉等画PCB时需要按原理图放置。TC118S是电机驱动芯片可能用于驱动振动电机。2. 系统设计与核心电路解析硬件齐了我们得知道它们是怎么连接和工作的。这部分我们聊聊系统的整体框架和几个关键电路。2.1 系统框图与工作流程你可以把整个宝箱想象成一个智能机器人感知通过TTP223触摸芯片“感觉”到用户的双击指令。思考STM32单片机接收到触摸信号结合当前宝箱状态开/关、电量、是否受外力判断该执行什么动作。执行STM32发出PWM信号控制SG90舵机转动从而拉动宝箱盖。同时控制LED显示颜色控制振动电机提供反馈。监测INA219芯片持续监测电池电压和系统电流STM32据此判断电量并在电量低时进入休眠。整个系统的电力来源于那块350mAh的锂电池通过两个稳压芯片L7805和AMS1117分别产生5V和3.3V为不同部件供电。2.2 电源电路设计要点电源是项目稳定的基础这里有几个坑我踩过大家要注意双路稳压舵机工作时电流可能瞬间达到几百mA如果和单片机共用一路电源会产生电压波动可能导致单片机复位。所以一定要用独立的L7805为舵机供电。单片机、触摸芯片、INA219等则使用AMS1117产生的3.3V。滤波电容在每路稳压芯片的输入和输出端一定要就近放置滤波电容比如表格里的100nF和330nF。它们能吸收电源线上的毛刺保证芯片工作稳定尤其是舵机启停的瞬间。电池保护除了软件上的低功耗休眠硬件上的拨动开关是最后一道防线。长期不用时务必关闭开关。2.3 触摸检测与舵机控制这是两个最核心的输入输出环节。TTP223触摸按键它的使用非常简单。模块通常有三个引脚VCC接3.3V、GND、OUT信号输出。默认情况下OUT输出低电平当手指触摸感应区域时OUT变为高电平。STM32只需要读取连接这个OUT的GPIO引脚的电平状态即可。难点在于用软件实现“双击”检测这需要精确的计时和状态机编程我们会在软件部分详细讲。SG90舵机控制舵机有三根线电源红接5V、地棕接GND、信号橙接STM32的PWM输出引脚。控制舵机角度本质上就是控制PWM信号的脉冲宽度。SG90的周期一般为20ms50Hz其中高电平脉冲宽度在0.5ms到2.5ms之间变化对应着0度到180度的位置。你需要用STM32的定时器功能来生成这样一路PWM。// 示例使用STM32标准库初始化定时器产生PWM以TIM3_CH2为例控制PA7引脚 void PWM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // 1. 开启时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 2. 配置GPIO为复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 3. 配置定时器基础产生50Hz (20ms) 周期 // 假设系统时钟72MHz预分频7200则计时器时钟为10kHz // 自动重装载值设为200则周期为 200 / 10kHz 20ms TIM_TimeBaseStructure.TIM_Period 200 - 1; TIM_TimeBaseStructure.TIM_Prescaler 7200 - 1; TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); // 4. 配置PWM模式 TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_ENABLE; TIM_OCInitStructure.TIM_Pulse 15; // 初始脉冲宽度对应约1.5ms舵机中位 TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC2Init(TIM3, TIM_OCInitStructure); // 初始化通道2 // 5. 使能预装载和定时器 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM3, ENABLE); TIM_Cmd(TIM3, ENABLE); } // 函数设置舵机角度 (0~180度) void Set_Servo_Angle(uint8_t angle) { uint16_t pulse_width; // 将角度映射到脉冲宽度 (0.5ms ~ 2.5ms) // 脉冲计数值 (0.5 angle * (2.0 / 180)) * 10 // 10是因为定时器时钟10kHz1ms对应10个计数值 pulse_width 5 angle * 10 / 180; // 简化计算 if(pulse_width 25) pulse_width 25; // 限制上限 if(pulse_width 5) pulse_width 5; // 限制下限 TIM_SetCompare2(TIM3, pulse_width); // 更新通道2的捕获比较值 }3. 软件功能实现与代码解析硬件搭好了接下来就是赋予它灵魂的软件部分。我们重点讲解几个核心功能的实现思路。3.1 双击检测算法这是人机交互的关键。单纯的触摸是“按下”双击是“快速按下-释放-再按下”。我们需要用状态机来实现。// 双击检测状态机示例 typedef enum { TOUCH_IDLE, // 空闲状态等待第一次按下 TOUCH_FIRST_PRESS, // 第一次按下 TOUCH_FIRST_RELEASE, // 第一次释放等待第二次按下 TOUCH_SECOND_PRESS // 第二次按下判定为双击 } TouchState; TouchState tState TOUCH_IDLE; uint32_t firstPressTime 0; uint32_t intervalTimeout 300; // 双击间隔超时时间单位ms通常300-500ms void Touch_Scan(void) { uint8_t currentTouch GPIO_ReadInputDataBit(TOUCH_GPIO_PORT, TOUCH_GPIO_PIN); switch(tState) { case TOUCH_IDLE: if(currentTouch 1) { // 检测到按下 tState TOUCH_FIRST_PRESS; firstPressTime GetSysTick(); // 记录第一次按下的时间 } break; case TOUCH_FIRST_PRESS: if(currentTouch 0) { // 第一次释放 tState TOUCH_FIRST_RELEASE; } break; case TOUCH_FIRST_RELEASE: if(currentTouch 1) { // 在超时时间内再次按下 // 计算时间间隔 if((GetSysTick() - firstPressTime) intervalTimeout) { tState TOUCH_SECOND_PRESS; // 双击事件触发 DoubleClick_Callback(); // 重置状态准备下一次检测 tState TOUCH_IDLE; } else { // 超时视为无效回到空闲 tState TOUCH_IDLE; } } // 检查是否超时 if((GetSysTick() - firstPressTime) intervalTimeout) { tState TOUCH_IDLE; } break; default: tState TOUCH_IDLE; break; } } // 需要在主循环或定时器中断中定期调用 Touch_Scan()3.2 低电量检测与休眠管理利用INA219芯片我们可以实时读取电池电压。STM32通过I2C总线与INA219通信。// 简化示例读取INA219的总线电压寄存器地址0x02 // INA219 I2C地址通常为0x40 (默认) 或 0x41 #define INA219_ADDR 0x40 #define INA219_REG_BUSVOLTAGE 0x02 float Read_Battery_Voltage(void) { uint16_t raw_voltage; float voltage; // 1. 发送要读取的寄存器地址 I2C_WriteByte(INA219_ADDR, INA219_REG_BUSVOLTAGE); // 2. 读取两个字节的数据 raw_voltage I2C_ReadWord(INA219_ADDR); // 3. 数据转换 (INA219总线电压寄存器每LSB为4mV) // 先右移3位寄存器格式再乘以4mV voltage (raw_voltage 3) * 0.004; return voltage; // 单位伏特 } // 在主循环中检查电量 void Check_Battery(void) { float vbat Read_Battery_Voltage(); if(vbat 3.5) { // 设置一个阈值例如3.5V // 触发低电量警告例如让LED闪烁红色 LowBattery_Warning(); if(vbat 3.3) { // 更低阈值进入休眠 Enter_Sleep_Mode(); } } }进入休眠模式后STM32可以关闭大部分外设时钟自身也进入低功耗模式如Stop模式仅保留唤醒源如外部中断有效。此时整个系统的功耗可以降到极低有效保护电池。3.3 外力保护逻辑实现外力保护可以通过监测舵机电流或堵转状态来实现。更简单的方法是在宝箱盖的机械结构上安装一个微动开关或霍尔传感器检测盖子是否被意外强行移动。这里以软件思路为例当宝箱处于打开状态时程序记录下当前舵机的目标角度如90度。如果此时检测到触摸信号用户想双击关闭并且通过某种方式如额外的传感器检测到盖子有异常阻力则先不执行关闭动作而是触发振动电机报警。如果阻力持续则控制舵机回到打开位置并锁定进入保护模式需要重启或特殊操作才能解除。4. 组装调试与心得分享最后我们把所有部分拼装起来并聊聊调试过程中可能遇到的问题。4.1 机械组装与走线3D打印件处理打印好的外壳可能需要打磨支撑和毛刺确保舵机安装位和转轴孔位顺畅。舵机安装与连杆这是最需要耐心的地方。舵机需要牢固固定并且通过连杆可以用铁丝或3D打印的连杆连接到宝箱盖上。需要反复调试连杆的长度和安装孔位使得舵机从0度转到180度时宝箱盖能完成从完全闭合到完全打开的动作。建议先用手动转动舵机测试再上电。内部走线使用FPC软排线连接主板、触摸传感器、LED灯和振动电机。用胶带或热熔胶固定线缆避免与舵机齿轮干涉。电池要妥善固定最好用双面胶贴在空旷位置。4.2 软件调试技巧分模块调试不要一下子把所有代码都写完。先调通LED闪烁系统跑起来了再调通触摸按键能打印检测状态然后调通舵机能用手势控制转动最后调通INA219能读出电压。每步都确认无误再整合。利用串口打印在代码关键位置用printf通过串口打印变量值如触摸状态、电压值、角度值这是最直接的调试手段。STM32可以通过USB转TTL模块连接电脑串口助手。保护措施在调试舵机PWM时初始化的脉冲宽度值一定要设置在安全范围如1.5ms左右避免一上电舵机就打到极限位置损坏机械结构。4.3 常见问题与解决舵机抖动或不转检查5V电源功率是否足够电池电量足吗L7805输入输出电容接了吗。检查PWM信号频率50Hz和脉冲宽度是否在有效范围。触摸按键不灵敏检查TTP223模块的触发模式设置跳线有些模块可调保持或触发模式。确保触摸焊盘或导线没有受到干扰可以尝试调整触摸灵敏度电容如果有。INA219读数不准检查I2C上拉电阻通常4.7kΩ是否接好。确认INA219的配置寄存器是否正确初始化开源代码中一般会提供配置函数。耗电太快检查程序是否真的进入了休眠。用万用表测量系统在“关闭”状态下的总电流如果还有几十mA说明有模块没断电。确保在休眠函数中将不用的GPIO设置为模拟输入最省电关闭所有外设时钟。这个波克布林宝箱项目麻雀虽小五脏俱全涵盖了嵌入式开发从电源管理、传感器采集、执行器控制到低功耗设计的多个核心知识点。把它做出来放在桌上不仅是个有趣的摆件更是一个你亲手打造的智能小装置成就感满满。希望这篇教程能帮你少走弯路顺利做出属于自己的智能宝箱。如果在制作过程中遇到问题不妨回到立创开源的原项目页面看看其他制作者的经验分享一起交流学习。