用STM32F103C8T6做个会说话的智能垃圾桶:从HC-SR04到LU-ASR01的保姆级教程
用STM32F103C8T6打造会说话的智能垃圾桶:从硬件搭建到语音交互全解析
最近在工作室捣鼓了一个特别有趣的小项目——给家里的垃圾桶装上"大脑",让它能感应开盖、语音提醒还能自动检测垃圾是否装满。这个基于STM32F103C8T6的智能垃圾桶不仅实用,还特别适合作为嵌入式开发的入门实战项目。下面我就把整个制作过程拆解成可落地的步骤,包括硬件选型、电路连接、代码编写以及那些只有亲手做过才会知道的调试技巧。
1. 项目规划与元器件选型
做电子项目最忌讳的就是拿到元器件就开始焊接,合理的规划能避免后期大量返工。这个智能垃圾桶需要实现三个核心功能:非接触感应开盖、语音交互反馈和满溢检测报警。
主控芯片我选择了经典的STM32F103C8T6,这款Cortex-M3内核的MCU性价比极高,72MHz主频完全够用,而且社区资源丰富。传感器部分主要用到:
- HC-SR04超声波模块:检测用户与垃圾桶的距离(建议采购带温度补偿的改进版)
- LU-ASR01语音识别模块:支持50条本地指令识别和TTS播报
- 红外对射传感器:安装在桶内顶部用于满溢检测
- SG90舵机:控制桶盖开合(注意要选金属齿轮版本)
其他配件清单:
| 元器件 | 型号/参数 | 数量 | 备注 |
|---|---|---|---|
| 开发板 | STM32F103C8T6最小系统 | 1 | 建议带BOOT0/1跳线 |
| 电源模块 | LM2596降压 | 1 | 输入12V输出5V/3A |
| 杜邦线 | 20cm公对公 | 30 | 建议不同颜色分组 |
| 洞洞板 | 7×9cm | 1 | 带铜柱安装孔 |
| 垃圾桶 | 10L脚踏式 | 1 | 改造原机械结构 |
提示:采购LU-ASR01时务必确认配套有咪头喇叭套装,单独模块无法发声。舵机建议预留至少1A的独立供电,避免与主控抢电流导致复位。
2. 硬件电路设计与搭建
电路搭建分为传感器供电、信号采集和执行控制三个部分。这里分享我的洞洞板布局方案:
- 电源分区:左上角布置LM2596模块,输出端并联1000μF电容滤波
- 主控区域:中央放置STM32核心板,保留SWD调试接口
- 传感器接口:
- PA0-PA1接HC-SR04的Trig/Echo
- PB10-PB11接LU-ASR01的UART3
- PC13接红外对射输出
- 执行机构:
- PA6接舵机PWM信号线
- +5V电源单独走线到舵机
超声波模块的安装有讲究:需要以15-30度仰角固定在桶盖内侧,避免直射时桌面反射干扰。实测安装高度与检测距离的关系:
| 安装高度(cm) | 最大检测距离(cm) | 建议阈值设置 |
|---|---|---|
| 15 | 80 | 30-50cm触发 |
| 20 | 120 | 40-70cm触发 |
| 25 | 150 | 60-100cm触发 |
遇到最头疼的问题是舵机工作时导致系统复位,后来发现是电流不足引起的。解决方案:
// 在main.c中添加电源检测代码 void Power_Check(void) { if(__HAL_PWR_GET_FLAG(PWR_FLAG_PVDO)) { HAL_Delay(100); LU_ASR01_Speak("电压不足请检查"); while(1); } }3. 核心代码实现与优化
程序架构采用前后台系统,通过定时器中断处理传感器数据。关键点在于超声波测距的滤波算法和语音模块的状态机设计。
超声波数据处理(定时器6中断服务程序):
// 在stm32f1xx_it.c中完善中断处理 void TIM6_IRQHandler(void) { static uint8_t sample_count = 0; static uint32_t distance_sum = 0; if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) { HCSR04_StartMeasure(); if(HCSR04_GetState() == MEASURE_OK) { uint32_t curr_dist = HCSR04_GetDistance(); distance_sum += curr_dist; if(++sample_count >= 5) { // 5次滑动平均 g_target_distance = distance_sum / 5; distance_sum = 0; sample_count = 0; // 距离阈值判断 if(g_target_distance < OPEN_DISTANCE && !g_cover_opened) { Servo_SetAngle(90); // 开盖 LU_ASR01_Speak("欢迎使用智能垃圾桶"); g_cover_opened = 1; } } } TIM_ClearITPendingBit(TIM6, TIM_IT_Update); } }语音模块交互逻辑需要特别注意串口通信稳定性:
// 在usart.c中添加自定义协议处理 void LU_ASR01_Process(uint8_t *buf) { if(strstr((char*)buf, "[ID00]")) { Servo_SetAngle(90); HAL_Delay(3000); Servo_SetAngle(0); } else if(strstr((char*)buf, "[FULL]")) { LU_ASR01_Speak("垃圾已满请清理"); HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); } } // 串口接收中断中加入超时判断 void USART3_IRQHandler(void) { static uint32_t last_tick = 0; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { uint8_t ch = USART_ReceiveData(USART3); if(HAL_GetTick() - last_tick > 100) { g_uart3_index = 0; memset(g_uart3_buf, 0, sizeof(g_uart3_buf)); } g_uart3_buf[g_uart3_index++] = ch; last_tick = HAL_GetTick(); } }4. 典型问题排查与性能优化
实际调试中遇到了几个教科书上不会写的问题,这里分享我的解决方案:
问题1:超声波偶尔测距异常
- 现象:在30cm处突然返回250cm+
- 排查:用逻辑分析仪抓取Echo信号发现波形畸变
- 解决:在Trig和Echo线上串联100Ω电阻,并添加如下软件滤波:
#define DISTANCE_FILTER(buf, new_val) \ for(int i=1; i<FILTER_SIZE; i++) buf[i-1]=buf[i]; \ buf[FILTER_SIZE-1] = new_val; \ qsort(buf, FILTER_SIZE, sizeof(uint16_t), compare); \ return buf[FILTER_SIZE/2]; uint16_t MedianFilter(uint16_t new_val) { static uint16_t filter_buf[FILTER_SIZE] = {0}; DISTANCE_FILTER(filter_buf, new_val); }问题2:语音模块在舵机动作时死机
- 现象:每次开盖后语音模块无响应
- 排查:用示波器发现5V电源在舵机启动时跌至4.3V
- 解决:
- 给LU-ASR01增加1000μF储能电容
- 修改电源方案:
[12V输入] -> [LM2596 5V/3A] -> [主控+传感器] | V [AMS1117 3.3V] -> [逻辑电路]问题3:环境光导致误触发
- 现象:白天经常无故播报
- 优化:增加多条件判断逻辑
void Cover_Control(void) { static uint8_t night_mode = 0; // 光敏电阻检测 if(ADC_GetValue() < LIGHT_THRESHOLD) { night_mode = 1; HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); } else { night_mode = 0; HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); } // 综合判断条件 if(g_target_distance < OPEN_DISTANCE && !g_cover_opened && (night_mode || HAL_GPIO_ReadPin(TOUCH_GPIO_Port, TOUCH_Pin))) { Open_Cover(); } }5. 功能扩展与升级建议
基础功能实现后,可以考虑增加这些实用特性:
垃圾分类引导:
- 通过不同颜色LED指示投放类型
- 语音提示"请投放厨余垃圾"等场景化引导
物联网接入:
// 在ESP-01S上实现的WiFi报警功能 void WiFi_SendAlert(void) { if(g_trash_full) { ESP8266_SendCmd("AT+CIPSTART=\"TCP\",\"192.168.1.100\",8080"); HAL_Delay(1000); ESP8266_SendCmd("AT+CIPSEND=20"); HAL_Delay(500); ESP8266_SendData("TRASH_FULL_ALERT"); } }- 能耗优化:
- 增加PIR人体传感器作为二级唤醒
- 实现STM32的低功耗模式:
void Enter_StopMode(void) { HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0xFFFF, RTC_WAKEUPCLOCK_RTCCLK_DIV16); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); // 唤醒后重新初始化时钟 }- 结构改进方案:
- 用步进电机替代舵机实现无极调节
- 增加霍尔传感器检测盖体到位
- 采用防水设计用于户外场景
这个项目最让我惊喜的是LU-ASR01的识别率,在50cm距离内能达到95%以上。不过要注意避免将喇叭与超声波模块安装在同一侧,否则回声会导致持续误触发。另外建议给垃圾桶加装软胶密封条,既减少开合噪音又能防止异味扩散。
