用STM32F103C8T6+红外传感器DIY自动开盖垃圾桶实战指南
周末整理工作室时,被角落里散发着异味的传统垃圾桶惹恼了——每次扔垃圾都得手动掀盖,手上沾满颜料时尤其不便。这让我萌生了改造一个智能垃圾桶的念头:当手靠近时自动开盖,离开后延时关闭。经过多次迭代,最终用最经济的STM32方案实现了这个功能,整套成本不到百元。下面将完整分享这个项目的实现细节,从元器件选型到代码调试的每个环节。
1. 硬件选型与成本控制
1.1 核心控制器选择
在创客圈里,STM32F103C8T6(俗称"蓝 pill")堪称性价比之王。这款Cortex-M3内核的MCU具有:
- 72MHz主频处理传感器数据绰绰有余
- 64KB Flash + 20KB RAM 的存储配置
- 丰富的GPIO和外设接口
- 市面上单价仅10元左右
相比Arduino Uno动辄七八十元的价格,STM32方案在性能翻倍的情况下成本反而更低。需要注意的是购买时要认准"ST"原厂标志,市面上存在国产仿制芯片,虽然便宜但稳定性较差。
1.2 传感器方案对比
测试了三种常见的人体检测方案:
| 传感器类型 | 单价 | 检测距离 | 功耗 | 适用场景 |
|---|---|---|---|---|
| HC-SR501红外 | 5元 | 3-7米 | 65μA | 通用型 |
| VL53L0X激光 | 35元 | 2米 | 20mA | 精准测距 |
| RCWL-0516微波 | 8元 | 5-7米 | 3mA | 穿透非金属 |
最终选择HC-SR501的原因在于:
- 价格低廉且满足基础需求
- 自带延时调节电位器(可设置2-5秒保持)
- 3.3V/5V兼容,与STM32直连无需电平转换
1.3 执行机构选型
垃圾桶盖开合需要扭矩足够的舵机,测试数据如下:
# 常见舵机参数对比 servos = { 'SG90': {'price':12, 'torque':1.8kg/cm', 'angle':180}, 'MG996R':{'price':25, 'torque':13kg/cm', 'angle':120}, 'DS3218':{'price':35, 'torque':18kg/cm', 'angle':270} }普通塑料垃圾桶盖重量约200-300g,SG90在力臂10cm时理论可承受1.8kg重量,实测完全够用。若使用金属桶盖,则需要选择MG996R等高扭矩型号。
2. 电路连接与供电设计
2.1 整体接线方案
系统连接关系如下图所示(实际接线时建议使用杜邦线+面包板过渡测试):
[红外传感器] --GPIO--> [STM32] --PWM--> [舵机] | | +--5V电源------------+具体引脚分配:
- HC-SR501 OUT → PA0(外部中断引脚)
- 舵机信号线 → PA6(TIM3_CH1 PWM输出)
- OLED显示屏 → I2C1(PB6/PB7)
注意:舵机供电需单独处理,当多个舵机同时动作时,USB供电可能不足导致STM32复位。建议使用5V/2A以上的外接电源,通过7805稳压芯片为系统供电。
2.2 防干扰设计
在工作室测试时发现,当附近有手机充电器工作时,红外传感器会出现误触发。通过以下措施解决:
- 在传感器输出端添加0.1μF去耦电容
- 使用带屏蔽层的双绞线连接传感器
- 在代码中增加软件去抖逻辑:
// 去抖检测代码示例 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET){ HAL_Delay(50); // 延时50ms再次检测 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET){ // 确认有效触发 open_lid(); } }3. 固件开发关键实现
3.1 PWM舵机控制
SG90舵机控制需要50Hz的PWM信号,脉宽0.5ms-2.5ms对应0-180度。使用STM32的硬件PWM实现:
// TIM3初始化代码 TIM_HandleTypeDef htim3; TIM_OC_InitTypeDef sConfigOC = {0}; htim3.Instance = TIM3; htim3.Init.Prescaler = 72-1; // 72MHz/72 = 1MHz htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 20000-1; // 1MHz/20000 = 50Hz HAL_TIM_PWM_Init(&htim3); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 1500; // 初始位置(1.5ms) sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);角度转换函数:
void set_servo_angle(uint16_t angle){ // 将角度转换为Pulse值 (500-2500) uint16_t pulse = 500 + angle * (2000 / 180); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pulse); }3.2 状态机设计
为避免快速连续触发导致舵机抖动,采用状态机管理垃圾桶盖状态:
stateDiagram [*] --> CLOSED CLOSED --> OPENING: 检测到人体 OPENING --> OPEN: 舵机到达位置 OPEN --> CLOSING: 持续5秒无人 CLOSING --> CLOSED: 舵机复位完成对应代码实现:
typedef enum { LID_CLOSED, LID_OPENING, LID_OPEN, LID_CLOSING } LidState; LidState lid_state = LID_CLOSED; void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if(GPIO_Pin == GPIO_PIN_0 && lid_state == LID_CLOSED){ lid_state = LID_OPENING; set_servo_angle(90); // 开盖角度 } } // 在main循环中处理状态转换 while(1){ switch(lid_state){ case LID_OPENING: if(servo_reached_position()) lid_state = LID_OPEN; break; case LID_OPEN: if(HAL_GetTick() - open_time > 5000){ // 5秒后开始关盖 lid_state = LID_CLOSING; set_servo_angle(0); } break; // 其他状态处理... } }4. 外壳改造与安装技巧
4.1 垃圾桶结构改造
普通塑料垃圾桶改造需要注意:
- 在桶盖转轴处钻孔安装舵机支架
- 使用3M VHB双面胶固定红外传感器(避免打孔破坏外观)
- 线路走线可用热熔胶固定在桶壁内侧
实测发现,将传感器安装在距桶口15-20cm高度时检测效果最佳。角度略微向下倾斜(约15度),可以避免远处经过误触发。
4.2 功耗优化技巧
为提升电池供电时的续航能力:
- 设置STM32进入Stop模式,通过外部中断唤醒
- 调整红外传感器检测间隔为500ms
- 关闭未使用的LED指示灯
// 进入低功耗模式 void enter_low_power(){ HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 唤醒后需要重新初始化时钟 SystemClock_Config(); }经过优化后,使用2000mAh锂电池可连续工作约3周时间。若想进一步延长续航,可换用RCWL-0516微波传感器(持续工作电流仅3mA)。
5. 常见问题排查指南
5.1 舵机抖动问题
现象:上电后舵机不停抖动但不转动 解决方法:
- 检查供电是否充足(建议单独5V供电)
- 确认PWM信号接地与电源共地
- 更换优质舵机线(劣质线内阻会导致电压下降)
5.2 红外传感器灵敏度调节
HC-SR501有两个调节电位器:
- 灵敏度:顺时针旋转增加检测距离(建议设置在3米内)
- 延时时间:控制输出信号保持时长(通常调至3秒左右)
调试技巧:用手机摄像头观察传感器(红外LED会显示为白光),测试不同距离的触发情况。
5.3 OLED显示异常
当I2C显示屏出现乱码时:
- 检查上拉电阻(4.7KΩ到3.3V)
- 降低I2C时钟频率(STM32默认100kHz可能过高)
- 确认初始化序列正确,特别是对于SSD1306驱动:
// 正确的初始化命令序列 const uint8_t oled_init_cmds[] = { 0xAE, // 关闭显示 0xD5, 0x80, // 设置时钟分频 0xA8, 0x3F, // 设置多路复用比例 0x20, 0x00, // 设置内存地址模式 // 更多命令... };这个项目最让我惊喜的是其扩展性——后续可以轻松添加超声波测距模块实现防夹手功能,或者增加WiFi模块实现满桶提醒。实际使用三个月后,传感器位置积灰会导致灵敏度下降,建议定期用酒精棉片清洁红外透镜。