
简介本资源是一套完整的STM32智能垃圾桶毕业设计/课程设计实战项目面向电子信息、自动化、嵌入式等专业本科生及实践开发者解决垃圾分类终端设备的软硬件协同开发痛点。压缩包共含程序源码工程Keil MDK、原理图与PCB设计文件Altium Designer格式、任务书、开题报告、答辩PPT、硬件采购清单、功能说明文档及参考资料总计608.57MB文件结构清晰覆盖从需求分析、电路设计、传感器驱动、多任务调度到人机交互的全链路实现。已有609人学习下载适合用于课程设计答辩、毕业设计参考或嵌入式综合实训。读者可直接部署运行支持语音唤醒垃圾名称识别自动开盖、四色垃圾桶颜色识别联动步进电机、红外感应自动启闭、光敏LED照明、HX711称重显示、MQ-2烟雾超标联动水泵与蜂鸣报警等八大核心功能配套文档详述各模块接线逻辑与关键代码注释大幅降低二次开发门槛。1. 项目概述与核心价值最近在整理过往的嵌入式项目时翻出了一个挺有意思的“老伙计”——一个基于STM32F103C8T6设计的智能垃圾桶。这可不是一个简单的感应开盖垃圾桶它集成了语音控制、颜色识别、称重、环境光强检测、烟雾监测、人体感应并且通过步进电机控制开盖甚至还有一个水泵模块用于可能的消毒或除臭功能。这个项目代号“资料编号25”算是我早期玩转STM32多传感器融合的一个典型练手作。虽然现在回头看代码架构和硬件选型上有些可以优化的地方但它的功能完整性和实现思路对于想从点灯、按键跳到综合项目实战的嵌入式爱好者来说依然有很高的参考价值。这个项目的核心在于如何让一块经典的“蓝桥杯”大赛常用芯片——STM32F103C8T6这颗只有72MHz主频、64KB Flash、20KB RAM的Cortex-M3内核MCU去协调管理七八个不同类型的传感器和外设并实现一些初步的“智能”决策。它解决的不是单一问题而是一个小型嵌入式系统在资源受限下的多任务调度、实时数据采集与简单逻辑判断的综合挑战。无论是学生做毕业设计、电子爱好者DIY还是工程师寻找传感器集成方案都能从这个项目中找到对应的模块代码和连接方法。接下来我就把这个项目的设计思路、关键实现细节、踩过的坑以及完整的工程文件梳理逻辑分享给大家你可以把它看作一个可裁剪的“智能硬件功能库”。2. 整体系统架构与硬件选型解析2.1 核心控制器与最小系统项目的“大脑”是STM32F103C8T6选择它原因很直接性价比高、资料丰富、生态成熟。对于这样一个多外设的项目其拥有的3个USART、2个I2C、2个SPI以及多个定时器和ADC通道基本够用。我使用的是市面上最常见的“核心板”形态自带3.3V LDO、复位电路和8MHz晶振通过2.54mm排针引出所有IO极大方便了在洞洞板或自制PCB上搭建系统。注意STM32F103C8T6的IO口是5V容忍的但ADC输入引脚只能承受3.3V。在连接一些输出为5V电平的传感器模块如某些型号的HC-SR501人体感应模块时需要确认模块输出是否是3.3V兼容或者使用电平转换电路避免损坏ADC。2.2 传感器与执行器模块清单整个系统的感知和执行层由以下模块构成它们的选型直接决定了项目的成本和功能上限语音识别模块选用的是LD3320非特定人语音识别芯片模块。它内置DSP和优化算法能离线识别数十条预设指令如“打开垃圾桶”、“关闭”通过SPI或并口与MCU通信。选择它而非更强大的在线语音方案是出于离线、实时性和隐私的考虑。颜色识别传感器采用TCS34725。这是一款数字RGB颜色光传感器通过I2C通信能直接输出RGB三原色和光强的数字值。用它来识别投入垃圾的包装颜色辅助进行简单的垃圾分类提示例如识别到蓝色包装可能对应可回收物。称重模块基于HX711压力传感器ADC芯片。连接一个标准称重传感器如5kg量程24位高精度ADC通过简单的两线SCK DT串行通信实现重量测量。这是实现“桶满报警”功能的关键。光强传感器使用BH1750FVI数字环境光强度传感器。同样是I2C器件分辨率高直接输出lux值。用于实现“光线暗时开盖自动补光”或调节指示灯亮度。烟雾传感器选用MQ-2模拟气体传感器。它检测可燃气体、烟雾的浓度输出模拟电压信号。通过STM32的ADC通道读取用于厨房等环境的安全监测浓度超标时报警。人体感应模块最常用的HC-SR501红外热释电传感器。检测人体移动输出高/低电平信号。用于实现“人来开盖人走延时关闭”的自动感应功能。步进电机与驱动控制桶盖开合。选用28BYJ-48五线四相步进电机搭配ULN2003驱动板。这种电机扭矩适中价格低廉通过脉冲序列控制适合这种慢速、精确角度控制如开盖90度的场景。水泵模块一个小型12V直流水泵通过一个MOS管或继电器模块由STM32的GPIO控制通断。初衷是连接一个微型喷雾装置用于喷洒空气清新剂或消毒液实现定时或触发式除臭。2.3 供电与电路设计要点系统供电是一个需要仔细规划的部分。由于存在步进电机5V和水泵12V这类功率器件不能直接从STM32的3.3V或USB 5V取电。我的方案是采用一个12V/2A的直流电源适配器作为总输入。12V直接供给水泵通过MOS管开关。12V通过一个DC-DC降压模块如LM2596降到5V为步进电机驱动板、语音模块、传感器等供电。5V再通过AMS1117-3.3线性稳压芯片为STM32核心板、BH1750、TCS34725等3.3V器件供电。实操心得务必在电机和水泵的电源入口处并联一个大容量电解电容如470uF~1000uF进行储能和滤波防止电机启动时的瞬间大电流导致整个系统电压跌落引发STM32复位。同时控制电机和水泵的GPIO口一定要用三极管或MOS管驱动进行隔离切勿直接驱动3. 核心功能模块的软件实现与代码剖析3.1 多传感器数据采集与任务调度在资源有限的Cortex-M3上管理这么多传感器裸机编程采用“前后台超级循环中断”的方式是务实的选择。我构建了一个简单的协作式调度器雏形。主循环框架大致如下int main(void) { // 初始化所有硬件时钟、GPIO、定时器、ADC、I2C、SPI、USART等 All_Init(); // 初始化各传感器模块 Sensor_Init(); // 初始化功能状态机 StateMachine_Init(); while (1) { // 任务1读取ADC值烟雾、电池电压 - 优先级低慢速采样 if (timer_flag.adc_read) { timer_flag.adc_read 0; Read_ADC_Values(); } // 任务2查询I2C传感器颜色、光强 - 中等速度 if (timer_flag.i2c_read) { timer_flag.i2c_read 0; Read_Color_Sensor(); Read_Light_Sensor(); } // 任务3查询语音模块状态 if (timer_flag.voice_check) { timer_flag.voice_check 0; Voice_Process(); } // 任务4处理称重数据HX711需连续时钟单独处理 Weight_Process(); // 任务5扫描人体感应等数字输入 Check_Digital_Inputs(); // 任务6执行主状态机根据传感器数据决策 Main_StateMachine_Run(); // 任务7处理显示和通信如OLED 串口调试 Display_Update(); } }这里的timer_flag是一个结构体由SysTick定时器中断服务函数周期性置位从而实现不同任务以不同频率执行。例如ADC每100ms读一次I2C传感器每200ms读一次语音查询每50ms一次。3.2 语音识别模块的集成与指令处理LD3320的集成是重点也是难点。它有两种模式寄存器模式和FIFO模式。我使用的是更常见的寄存器模式。关键步骤硬件连接模块的SPI接口MISO MOSI SCK CS连接STM32的SPI1另需一个GPIO连接模块的复位引脚一个GPIO连接中断输出引脚。初始化与ASR配置上电后通过SPI写入一系列寄存器配置芯片的时钟、麦克风增益、识别列表等。其中识别列表的写入是关键。需要将你希望识别的拼音串如“da kai la ji tong”转换成LD3320特定的编码通过SPI写入其指定RAM区域。// 示例添加识别条目“打开垃圾桶” LD3320_AddOneCode(da kai la ji tong, CMD_OPEN); // CMD_OPEN是自定义的指令编号中断驱动将模块的中断输出引脚连接到STM32的外部中断引脚。当LD3320识别到有效指令后会触发中断。在中断服务函数中读取结果寄存器获取识别到的指令编号。指令处理在主循环或中断中根据指令编号执行相应操作如设置状态机标志位。踩坑记录LD3320对供电噪声敏感SPI通信速率不能太高建议1MHz。识别列表的拼音串要尽可能符合日常发音且不宜过长。初期调试时最好先用串口打印出芯片的各个状态寄存器值确保初始化流程正确。3.3 颜色识别与简单分类逻辑TCS34725的使用相对标准。通过I2C初始化后使其开始积分光强然后读取RGBC清晰四个通道的16位数据。颜色判断不是直接看RGB值而是计算归一化的色度坐标以消除光强影响uint32_t sum r g b; if (sum 0) { float r_norm (float)r / sum; float g_norm (float)g / sum; // float b_norm (float)b / sum; // 实际上 r_norm g_norm b_norm 1 if (r_norm 0.4 g_norm 0.3) { // 红色占主导可能是红色包装 color_type COLOR_RED; } else if (g_norm 0.4 r_norm 0.3) { // 绿色占主导 color_type COLOR_GREEN; } else if (r_norm 0.3 g_norm 0.3) { // 红绿混合可能是黄色或橙色 color_type COLOR_YELLOW; } else { // 其他或无法判断 color_type COLOR_UNKNOWN; } }得到颜色类型后可以通过RGB LED或OLED屏幕给出提示例如“检测到红色包装建议投入有害垃圾箱”。这只是非常基础的演示真实的垃圾分类需要更复杂的图像识别。3.4 称重模块的校准与滤波HX711是称重的核心。其驱动简单但要做好需要两点校准和滤波。校准在桶内无物时读取HX711的值作为offset皮重。放置一个已知重量的标准砝码如500g读取此时的HX711值raw_weight_with_known。计算比例系数scale (raw_weight_with_known - offset) / 500.0。后续测量中实际重量 (当前读数 - offset) / scale。软件滤波HX711的24位输出仍有噪声。我采用了一阶互补滤波低通滤波结合中值滤波。// 一阶低通滤波new_weight a * current_raw (1-a) * last_weight; // 中值滤波连续采样5次排序后取中间值作为current_raw long median_filter(short nums, ...) { /* 中值滤波实现 */ } float low_pass_filter(float current, float last, float a) { /* 低通滤波实现 */ }经过滤波后的重量值稳定很多用于判断桶是否将满例如重量持续超过设定阈值的80%。3.5 步进电机控制与桶盖动作28BYJ-48是单极步进电机采用8拍模式A-AB-B-BC-C-CD-D-DA控制时步距角最小运行最平稳。我使用一个定时器如TIM2产生固定频率的PWM脉冲在中断中根据预设的步数序列表切换GPIO输出控制ULN2003的四个输入引脚。关键点在于动作规划桶盖的开启和关闭不是瞬间完成的需要加速-匀速-减速的过程否则会失步或产生噪音。我实现了一个简单的梯形加减速算法typedef struct { uint32_t total_steps; // 总步数如开盖需500步 uint32_t accel_steps; // 加速阶段步数 uint32_t decel_steps; // 减速阶段步数 uint32_t current_step; // 当前已走步数 uint16_t current_delay; // 当前步进间隔决定速度 uint16_t min_delay; // 匀速段速度对应最快频率 uint16_t max_delay; // 启动速度对应最慢频率 } MotorCtrl_t; // 在定时器中断中调用 void Motor_Step_Handler(MotorCtrl_t *motor) { if (motor-current_step motor-total_steps) { // 1. 根据当前步数计算应处的阶段加速、匀速、减速 // 2. 根据阶段计算或查表得到本次的步进间隔 current_delay // 3. 重设定时器ARR为 current_delay 以改变速度 // 4. 输出下一拍相位 // 5. motor-current_step; } else { // 动作完成停止定时器 HAL_TIM_Base_Stop_IT(htim2); } }这样桶盖的开启和关闭动作就显得平滑且可靠。4. 系统状态机设计与多模态交互逻辑4.1 主状态机定义所有传感器数据最终汇聚到一个主状态机决定垃圾桶当前的行为模式。我定义了以下几个主要状态IDLE空闲状态。桶盖关闭持续监测人体、语音和重量。AUTO_OPENING自动开盖状态。检测到人体接近启动电机开盖。AUTO_OPEN自动开盖保持状态。盖已打开等待人体离开或超时。AUTO_CLOSING自动关盖状态。人体离开或超时启动电机关盖。VOICE_CTRL语音控制状态。响应语音指令进行开盖或关盖。FULL_ALARM桶满报警状态。重量超阈值声光报警拒绝新垃圾盖不自动开。SMOKE_ALARM烟雾报警状态。烟雾浓度超阈值声光报警可能联动水泵喷雾如果用于消防演示。状态之间的转换由事件触发例如EVENT_HUMAN_DETECTEDEVENT_VOICE_OPENEVENT_WEIGHT_FULLEVENT_TIMEOUT等。4.2 多传感器数据融合与冲突处理当多个传感器同时触发时需要有优先级策略。例如烟雾报警优先级最高任何状态下一旦检测到烟雾超标立即进入SMOKE_ALARM状态并打断当前动作如正在关盖。桶满报警次之在IDLE或AUTO_OPEN状态下检测到桶满进入FULL_ALARM自动感应和语音开盖功能暂时禁用。人体感应 vs 语音控制在IDLE状态下两者均可触发开盖。但如果正在语音控制开盖过程中VOICE_CTRL人体感应事件会被忽略避免冲突。这些逻辑都在Main_StateMachine_Run()函数中通过switch-case语句实现。4.3 用户反馈与交互设计一个好的产品离不开清晰的反馈。这个项目通过多种方式与用户交互视觉反馈一个0.96寸OLED屏幕显示状态如“正常”、“桶满”、重量、检测到的颜色提示。另外RGB LED用不同颜色指示状态蓝色-正常 红色-报警 绿色-识别到可回收色。听觉反馈蜂鸣器。短促“嘀”一声表示操作成功如语音识别成功急促“嘀嘀”声表示报警播放一段旋律表示欢迎上电自检完成。触觉反馈步进电机平稳的转动声本身也是一种反馈。在FULL_ALARM状态下可以控制电机轻微震动提示。5. 工程文件结构解析与移植指南“资料编号25.zip”解压后工程结构清晰基于标准库或HAL库构建我后期用HAL库重构了一版。核心目录如下Project_25/ ├── Core/ │ ├── Inc/ │ │ ├── main.h │ │ ├── gpio.h adc.h tim.h i2c.h spi.h usart.h // 硬件抽象层配置 │ │ ├── bsp_voice.h bsp_color_sensor.h bsp_hx711.h ... // 各模块驱动头文件 │ │ └── state_machine.h data_filter.h // 应用层头文件 │ └── Src/ │ ├── main.c // 主循环、初始化 │ ├── 各外设的MSP回调函数 │ ├── bsp_voice.c bsp_color_sensor.c ... // 各模块驱动源文件 │ └── state_machine.c data_filter.c // 应用层源文件 ├── Drivers/ │ ├── CMSIS/ │ └── STM32F1xx_HAL_Driver/ ├── MDK-ARM/ // Keil工程文件 │ └── Project_25.uvprojx └── README.txt // 硬件连接表、使用说明移植到你的硬件平台需要修改的地方Core/Inc/main.h和Core/Src/main.c根据你的核心板修改SystemClock_Config时钟配置。Core/Inc/下的外设头文件检查并修改#define的引脚定义确保与你实际的接线一致。例如// bsp_hx711.h #define HX711_SCK_PIN GPIO_PIN_0 #define HX711_SCK_PORT GPIOA #define HX711_DT_PIN GPIO_PIN_1 #define HX711_DT_PORT GPIOA模块驱动初始化函数部分模块如LD3320的初始化序列可能因模块批次略有差异如果遇到问题需对照最新数据手册调整。参数调整在state_machine.c或各模块驱动中有大量可调参数如重量满阈值、光强阈值、烟雾报警阈值、电机加减速曲线、语音识别列表等需要根据你的实际硬件和应用场景重新校准和设定。6. 常见问题排查与调试心得6.1 电源与噪声问题现象系统运行不稳定偶尔复位传感器读数跳动大。排查首先用万用表测量3.3V和5V电源轨的电压在电机启停时观察是否有大幅跌落。在电源入口和各IC的电源引脚附近增加去耦电容104瓷片电容并联10uF电解电容。将模拟部分如HX711 MQ-2的ADC输入和数字部分MCU 电机驱动的电源走线在物理上分开单点接地。心得嵌入式系统电源是基石。多电机、多传感器的项目电源设计必须留足余量并做好滤波。6.2 I2C通信失败现象TCS34725或BH1750读不出数据。排查确认上拉电阻通常4.7kΩ已正确连接到SDA和SCL线。用逻辑分析仪或示波器抓取I2C波形看起始信号、地址、ACK是否正常。STM32的I2C时钟频率不宜过高初期可设为100kHz。检查从设备地址是否正确。TCS34725的地址是0x297位 BH1750默认是0x23。注意I2C总线上的电平是3.3V还是5V确保所有设备电平兼容。6.3 语音识别率低现象LD3320经常识别错误或不识别。排查与优化环境噪声在安静环境下测试。可以尝试在麦克风输入端增加简单的RC低通滤波电路。供电质量确保LD3320的3.3V供电干净最好单独用一颗LDO供电。识别列表优化拼音串尽量用常见的、发音差异大的词。例如“打开”比“开启”识别率可能更高。可以适当增加列表容量但不要超过芯片限制。软件优化在识别到指令后增加一个简单的“防抖”处理例如连续两次查询到相同结果才确认避免误触发。6.4 步进电机抖动或失步现象电机转动不顺畅有噪音或者实际转动角度与预期不符。排查驱动电流不足ULN2003驱动28BYJ-48是足够的但确保驱动板的输入电压5V稳定。电机堵转会消耗大电流检查电源能否承受。时序问题检查步进脉冲序列的时序是否正确8拍顺序不能错。在切换相位之间加入微秒级的延时HAL_Delay_us()有时能改善。机械负载检查桶盖的机械结构是否顺滑有无卡滞。电机轴与负载的连接是否同心。加减速曲线如果直接从静止跳到高速极易失步。务必使用前面提到的梯形加减速算法并调整accel_steps和decel_steps参数找到最适合你机械结构的曲线。6.5 称重数据漂移现象放上同一物体每次读数有微小差异或者长时间放置零点漂移。优化硬件称重传感器要安装稳固避免侧向力。使用质量好的HX711模块其基准电压稳定是关键。软件滤波结合中值滤波和低通滤波已能解决大部分随机噪声。对于缓慢的温漂可以定期在确认桶内无物时进行“自动清零”更新offset但需谨慎使用避免误清零。校准使用多点校准如空载、半量程、满量程并存储校准参数到STM32的Flash中可以提高线性度。这个项目就像一个小型的“嵌入式技术博览会”涵盖了MCU基础外设、多种通信协议、传感器应用、电机控制、状态机设计、电源管理和简单的数据融合。虽然每个模块单独看都不复杂但将它们有机整合并稳定可靠地运行才是真正的挑战所在。希望这份详细的拆解能为你实现自己的智能硬件创意提供扎实的参考。工程文件中的代码注释比较详细结合本文的说明你应该能较快地上手和修改。本文还有配套的精品资源点击获取