一、项目概述

本项目基于STM32F103C8T6微控制器,设计并实现了一款具备多种智能功能的垃圾桶。系统通过各类传感器感知环境与用户需求,实现自动开盖、消毒、火灾预警、状态监测及手机交互等功能,体现了嵌入式系统在智能家居领域的应用。

二、硬件模块清单

模块名称功能说明
主控芯片STM32F103C8T6(核心控制单元)
电源模块为系统各模块提供稳定电源
独立按键模块手动控制、功能切换
继电器控制紫外线消毒灯等高功率设备
UV紫外线消毒灯垃圾桶内部自动杀菌
红外光电传感器检测人手或物体,触发开盖
SG90舵机模块驱动垃圾桶盖自动开合
火焰传感器检测火源,实现火灾报警
HC-SR04超声波传感器测量垃圾高度,提醒清理
蓝牙模块与手机通信,实现远程控制与状态查看
OLED显示屏显示垃圾桶状态(如垃圾量、模式等)
LED模块状态指示(如消毒中、已满、报警等)
蜂鸣器模块火灾报警、提醒提示音
手机(嘿嘿)用户终端,通过蓝牙与垃圾桶交互

三、涉及的主要通信协议与外设

协议/外设类型在项目中的应用场景
GPIO控制LED、蜂鸣器、按键输入、继电器开关
UART蓝牙模块与STM32间的串口通信
IIC驱动OLED显示屏
TIM(定时器)1. 产生PWM信号控制舵机角度
2. 为超声波传感器提供时序控制
3. 系统延时与定时任务
外部中断用于按键紧急触发、火焰传感器报警等即时响应事件

四、关键步骤与遇到的问题

1. 蓝牙模块(AT指令配置)
  • 关键步骤

    1. 将蓝牙模块的KEY(或EN)引脚拉高(接VCC),使其进入AT指令模式。

    2. 通过STM32的UART(或USB转TTL)连接蓝牙模块的TXRX

    3. 使用串口调试助手,以纯英文模式(注意字符编码)发送AT指令(如AT+NAME=SmartBin)进行名称、配对码、波特率等参数配置。

    4. 配置完成后,将KEY引脚拉低,使其退出AT模式进入正常工作(透传)模式。

  • 遇到的问题与解决

    • 问题1:无法进入AT模式

      • 现象:仅给模块断电(VCC),再上电后发送AT指令无回应。

      • 原因:模块状态未完全复位。KEY引脚电平可能未在正确时刻保持高电平。

      • 解决确保VCC和KEY引脚都完全断电后,先拉高KEY引脚,再给VCC上电。这是进入AT模式的关键时序。

    • 问题2:AT指令无响应或返回错误

      • 现象:发送指令后无OK返回。

      • 原因:串口调试助手输入法为中文,导致指令中包含不可见的中文字符(如空格);或波特率设置错误。

      • 解决:在串口工具中切换至英文输入法重新输入;或发送纯英文的AT(无任何后缀)测试连接,并核对双方波特率。

2. OLED显示屏显示汉字
  • 关键步骤

    1. 取模软件:使用PC端OLED取模软件(如PCtoLCD2002)。

    2. 设置参数:根据所用OLED驱动芯片(通常是SSD1306),设置正确的取模方式。常见设置为:列行式、逆向、C51格式(十六进制数组)

    3. 生成字模:输入所需汉字,生成对应的点阵数据数组(如const unsigned char Chinese[]={...})。

    4. 调用显示函数:在程序中调用OLED驱动库的图形显示函数,将字模数组写入显示RAM。

  • 遇到的问题与解决

    • 问题:直接显示汉字出现乱码或错位。

    • 原因:OLED本身不含中文字库,必须使用点阵数据。乱码通常是因为取模格式(逐行/逐列、字节顺序)与驱动程序的显示函数不匹配。

    • 解决核对并统一取模软件设置与驱动程序的数据处理逻辑。通常需要调整取模软件的“取模方式”并进行测试。

3. OLED驱动初始化与显示
  • 关键步骤

    1. 系统上电后,首先进行OLED硬件初始化(通过I2C或SPI发送一系列配置命令)。

    2. 初始化后清屏,再执行后续的显示操作。

  • 遇到的问题与解决

    • 问题1:屏幕无任何显示

      • 原因:初始化序列未成功执行或时序不对;I2C地址错误;硬件连接(SDA、SCL)不可靠。

      • 解决确保OLED_Init()函数在任何显示操作前被调用;用逻辑分析仪或示波器检查I2C总线信号;核对模块的I2C地址(通常是0x780x7A)。

    • 问题2:程序烧录后必须手动复位才能显示

      • 现象:下载程序后屏幕仍是空白,按下复位键后正常。

      • 原因:系统上电后,OLED模块的电源和内部控制器需要一定的准备时间(几毫秒到几十毫秒),而STM32的初始化速度过快,在OLED还未就绪时就发送了初始化命令,导致命令被忽略。

      • 解决:在单片机初始化后、OLED初始化前,增加一个足够长的延时(如100ms),确保OLED模块已完全上电就绪。也可以在OLED初始化函数中,在发送软复位命令后增加延时。

AI给出的加延时的底层原因

4. 舵机控制(SG90)
  • 关键步骤

    1. 明确舵机类型:确认使用的是180°位置舵机(用于控制开盖角度)还是360°连续旋转舵机(只能控制速度和方向)。

    2. PWM信号生成:使用STM32的TIM(定时器)输出PWM信号,周期设置为20ms(50Hz)

      • 对于180°舵机:通过调节占空比(高电平时间)控制角度。通常:

        • 0.5ms → 0°

        • 1.5ms → 90°

        • 2.5ms → 180°

      • 对于360°舵机:占空比控制旋转速度和方向:

        • 1.5ms → 停止

        • 1.0ms → 全速正转(具体方向取决于接线)

        • 2.0ms → 全速反转

    3. 配置
       

    4. 代码

    5. 供电隔离:舵机必须使用独立的5V电源供电(可从Type-C口取电),避免与单片机共用3.3V电源,同时确保两者的GND相连。

  • 遇到的问题与解决

    • 问题1:舵机不转动或抖动

      • 现象:舵机发出“滋滋”声但不转动,或轻微抖动。

      • 原因供电不足。SG90工作电流在150-300mA左右,而STM32的3.3V输出或DAPLink的3.3V引脚无法提供足够电流。

      • 解决使用外部5V电源单独为舵机供电,确保电源能提供至少1A的电流。同时,将外部电源的GND与STM32的GND连接。

    • 问题2:舵机一直旋转(死循环)

      • 现象:180°舵机不停旋转而不停止在指定角度。

      • 原因:错误地使用了360°连续旋转舵机,或者PWM信号参数设置错误(如周期不对、占空比超出范围)。

      • 解决:首先确认舵机型号。若为180°舵机,则检查PWM周期是否为20ms,并确保占空比在0.5ms-2.5ms之间。若为360°舵机,则只能控制其旋转时间和速度来间接控制“角度”。

    • 问题3:控制信号电压不足

      • 现象:供电正常,但舵机响应不灵敏或角度不准。

      • 原因:STM32的IO口输出为3.3V,而舵机控制信号理想电压为5V。

      • 解决:添加电平转换电路(如使用三极管或MOS管)将3.3V PWM信号升压至5V。在实际测试中,3.3V信号有时也能驱动,但5V信号更可靠。

5. 供电问题(DAPLink与USB)
  • 关键步骤

    1. 区分供电角色:DAPLink主要用于程序下载和调试,其3.3V引脚电流能力有限(通常≤200mA)。

    2. 系统供电设计:当需要驱动舵机、继电器等大电流设备时,必须使用外部电源(如通过开发板的Type-C/USB口输入5V,或使用独立的5V电源模块)。

    3. 电源隔离:对电机类负载(如舵机)采用独立供电,并在电源线上并联大电容(如100µF)以吸收电流突变。

  • 遇到的问题与解决

    • 问题:使用DAPLink供电时系统不稳定

      • 现象:连接舵机或继电器后,单片机复位、程序跑飞或DAPLink断开。

      • 原因:DAPLink的3.3V输出电流过载,触发其保护机制或导致电压跌落。

      • 解决绝不使用DAPLink的3.3V引脚为整个系统供电。仅将其用于调试接口,系统电源应通过开发板的电源接口(如Type-C)提供。如果开发板无此设计,则需自行搭建5V转3.3V的稳压电路为STM32供电。

6.HC-SR04超声波传感器应用详解
(一)、HC-SR04基本原理

1. 工作原理

HC-SR04通过超声波测距,包含两个核心部件:

  • 发射器:发射超声波脉冲

  • 接收器:接收反射回来的超声波

2. 测量时序

Trigger: ___|¯¯ ¯¯ ¯¯ ¯¯ ¯¯|_________________ (碰到物体停止触发)
                 ↑                         ↑
               触发                  停止触发

Echo: ________________|¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯|____ (高电平持续时间=往返时间)                              ↑                            ↑
                                    回波开始                回波结束

3. 距离计算公式

距离(cm) = (高电平时间(μs) × 声速(340m/s)) ÷ 2 ÷ 10000
         = 高电平时间(μs) ÷ 58
         = 高电平时间(μs) × 0.017

关键配置说明

参数通道1通道2说明
触发边沿上升沿下降沿分别捕获Echo的起始和结束
中断使能只在下降沿触发中断处理
滤波器可选可选防干扰,建议4-8个时钟周期

(二)、STM32实现详解

1. 初始化配置(TIM输入捕获模式)

void hc_sr04_init(void)
{
	HAL_TIM_Base_Start(&htim1);
	HAL_TIM_IC_Start(&htim1,TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);
}

2. 脉冲触发实现

// 在主循环或超声波任务中计算距离
void hc_sr04_proc(void)
{
    static uint32_t last_trigger = 0;
    uint32_t now = HAL_GetTick();

    /* Trigger at a safe rate (HC-SR04 recommends >=60ms between triggers). */
    if ((uint32_t)(now - last_trigger) >= HC_SR04_TRIGGER_PERIOD_MS) {
        last_trigger = now;
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
        delay_us(15);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
        __HAL_TIM_SetCounter(&htim1, 0);
    }
 }

3. 测量计算与中断处理

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if(htim == &htim1 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
    {
        upEage = (uint16_t)HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);
        downEage = (uint16_t)HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2);
        
        // 只记录脉宽,不在中断中计算
        if(downEage >= upEage) {
            echo_width = downEage - upEage;
        } else {
            // 处理定时器溢出
            echo_width = 65535 - upEage + downEage;
        }
        new_data_ready = 1;
    }
}
    // 处理新数据
    if(new_data_ready) {
        new_data_ready = 0;
        
        // 计算距离
        float raw_distance = echo_width * 0.017f;  // (0.034/2)
        // 距离滤波(指数滑动平均)
        static float filtered_distance = TRASH_EMPTY_DISTANCE_CM;
        if (raw_distance > 0.0f && raw_distance < 500.0f) {
            filtered_distance = filtered_distance * 0.7f + raw_distance * 0.3f;
        }
        distance = filtered_distance; /* publish filtered distance */
				if(distance_flag==1){
				UART_Printf_DMA("distance:%.2f\r\n",distance);
				distance_flag=0;
				}
      }

4. 完整使用流程

// 主程序示例
int main(void)
{
    // 1. 初始化
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM1_Init();
    OLED_Init();
    hc_sr04_init();
    
    // 2. 主循环
    while (1)
    {
        // 触发一次测量
        hc_sr04_trigger();
        
        // 等待测量完成(最长40ms,对应约7m距离)
        uint32_t timeout = HAL_GetTick() + 50;  // 50ms超时
        while(!new_data_ready && HAL_GetTick() < timeout);
        
        // 显示结果
        hc_sr04_display_result();
        
        // 适当延时,避免频繁触发(HC-SR04最小测量周期60ms)
        HAL_Delay(100);
    }
}

Logo

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

更多推荐