站内搜索
更多
自动巡逻安防智能小车
专业版

自动巡逻安防智能小车

简介

基于STM32F407VET6与K230视觉模块的智能巡逻小车,集成DHT11温湿度、HC-SR04超声波避障、SU03T语音交互、AT8236电机驱动及蓝牙遥控,支持自动巡航与手动遥控双模式。

简介:基于STM32F407VET6与K230视觉模块的智能巡逻小车,集成DHT11温湿度、HC-SR04超声波避障、SU03T语音交互、AT8236电机驱动及蓝牙遥控,支持自动巡航与手动遥控双模式。
复刻成本:700

开源协议

GPL 3.0

(未经作者授权,禁止转载)
创建时间:2026-06-09 16:44:49更新时间:2026-06-10 14:37:00

描述

智能巡逻监护小车

题目要求

本作品为基于STM32F407VET6的智能巡逻监护小车,实现功能如下:

  1. 实时采集环境温湿度数据
  2. 切换到自动模式时:通过超声波模块小车自助巡航主动避让
  3. K230识别老人跌倒,老人呼叫APP语言提示
  4. 视频数据回传手机(备用ESP32CSAM)
  5. 切换到手动模式:小车可以通过手机遥控操作
  6. 语音交互功能
  7. 跟随功能(人体跟踪)

题目分析

本项目以STM32F407VET6作为主控核心,选型理由在于其拥有丰富的外设接口(多路UART、定时器、PWM输出),能够同时驱动多个传感与执行模块。系统按功能可分为四个层次:感知层(DHT11温湿度、HC-SR04超声波、电压采集)、视觉与交互层(K230视觉模块、SU03T语音模块、按键、OLED)、通信层(蓝牙JDY-31、备用ESP32CSAM WiFi视频回传)、执行层(AT8236电机驱动、SG90舵机、蜂鸣器)。

技术难点主要在于多传感器数据的融合调度与实时性保障。K230视觉模块的人体检测与跌倒识别需要在有限算力下运行推理模型,而超声波避障与自动驾驶模式则依赖PID闭环控制算法实现平稳的差速转向。蓝牙遥控与自动模式的平滑切换通过全局状态机管理,确保模式切换时小车立即停车,避免失控风险。

软件架构建议采用前后台系统,主循环负责传感器数据采集、OLED刷新、蓝牙指令解析和模式调度,定时器中断中完成PID速度环计算与电机PWM输出更新,K230与SU03T语音模块通过独立串口中断接收数据。

总体设计方案框图

硬件直框图.png

原理图设计说明

  • STM32F407VET6 主控:基于ARM Cortex-M4内核,主频168MHz。采用最小系统板方案,外接8MHz晶振和32.768kHz RTC晶振。BOOT0和BOOT1接地确保从Flash启动,复位电路采用RC复位+按键。

  • DHT11温湿度模块:采用成品数字温湿度传感器模块,单总线接口与MCU GPIO相连。模块内部已集成8位MCU完成数模转换和校准,对外输出40位数字信号,无需自行设计信号调理电路。建议DATA引脚外接4.7kΩ上拉电阻以保证通信稳定性。

  • HC-SR04超声波模块:采用成品超声波测距模块,Trig和Echo引脚直连MCU GPIO。Trig发送10μs以上高电平脉冲触发测距,Echo输出高电平持续时间对应距离。工作电压5V,需注意与MCU的3.3V电平匹配,建议Echo引脚串联分压电阻。

  • AT8236电机驱动模块:AT8236为双路H桥电机驱动芯片,峰值电流3.6A。通常采用成品驱动板方案,MCU通过PWM控制转速、GPIO控制方向。需在电机两端并联续流二极管(如已内置则无需额外添加),电源输入端建议并联100μF电解电容+0.1μF瓷片电容滤波。

  • SU03T语音模块:采用成品离线语音识别模块,通过UART与MCU通信。模块已内置语音指令集,用户可通过串口配置关键词。建议供电3.3V,RX/TX直连MCU对应UART引脚。

  • K230视觉模块:嘉楠科技K230 AI视觉模组,通过UART与MCU通信传输识别结果。模块内部运行轻量级目标检测模型。需独立供电(5V/2A),与MCU之间仅需TX/RX两根线连接。

  • 蓝牙JDY-31:采用成品BLE透传模块,UART接口与MCU通信。HC-06指令集兼容,默认波特率9600bps。工作电压3.3V,直连MCU UART引脚即可。

  • 0.96寸OLED屏幕:SSD1306驱动,I2C接口。采用成品模块,SCL和SDA直连MCU I2C引脚,需外接4.7kΩ上拉电阻(部分模块已内置)。

  • SG90舵机:微型舵机,PWM控制角度(0.5ms2.5ms对应0°180°)。采用成品模块,信号线直连MCU定时器PWM输出通道,工作电压5V。

  • 蜂鸣器(声光报警):有源蜂鸣器通过NPN三极管驱动,基极串联限流电阻后接MCU GPIO。LED报警指示灯串联限流电阻接MCU GPIO。

  • 电压采集:电池电压通过电阻分压后接入MCU ADC通道。分压比根据电池最大电压(如8.4V锂电2S)计算,确保分压后不超过3.3V。建议分压电阻旁并联0.1μF电容进行滤波。

  • 按键*4:轻触按键,一端接GND,另一端接MCU GPIO并配置内部上拉。软件中需做消抖处理(延时20ms或状态机消抖)。

PCB设计说明

  • 布局:电源电路(电池输入、稳压)放置在PCB一侧,远离模拟信号采集区域。电机驱动AT8236布局在PCB边缘靠近电机接口处。MCU及数字电路集中在中间区域,OLED、按键等放在便于人机交互的位置。K230模块因功耗较大且对发热敏感,建议独立成板或预留足够的散热间距。

  • 布线:电源走线宽≥40mil(1mm),电机驱动电源线宽≥80mil(2mm)。信号线宽10mil,线间距≥8mil。ADC电压采集走线尽量短且远离PWM等高频信号线,并铺地包围以降低噪声干扰。

  • 散热与隔离:AT8236电机驱动为大功率器件,需在PCB上预留散热铜皮面积或外加散热片。电机回路与数字电路回路应单点接地(星形接地),避免电机干扰通过地线耦合到MCU。K230模块电流较大(峰值2A),独立走粗电源线并加去耦电容。

  • 接口:各模块连接器采用2.54mm排针/排母,标注丝印名称和方向。电源输入采用DC座或XT30接口,反接保护二极管串接在电源输入端。

软件说明

代码基于STM32 HAL库开发,采用前后台架构:主循环负责传感器数据采集、OLED显示刷新、蓝牙指令解析和模式调度,定时器中断中完成PID速度环闭环控制与电机输出更新。

代码结构概览:

  1. 初始化阶段main函数前半部分):依次初始化HAL库、系统时钟(168MHz)、延时函数、LED、定时器、编码器、电机PWM、舵机PWM、超声波、自动驾驶系统、DHT11、电压检测、OLED、按键、串口(蓝牙+K230)以及PID控制器。初始化完成后蜂鸣器关闭,进入主循环。

  2. 主循环while(1)):轮询按键扫描,切换OLED显示页面(数据页面和设置页面);根据当前模式(自动/手动/跟踪)调用对应的任务函数;接收处理蓝牙和K230的串口数据;通过蓝牙定时发送传感器数据到手机APP。

  3. 定时器中断GTIM_TIMX_INT_IRQHandler):每10ms触发一次,读取编码器转速,通过斜坡函数实现软启动/软停止,运行位置式或增量式PID计算出PWM值,最终通过Motor_SetSpeed输出到电机驱动。

主函数代码:

/**
 ****************************************************************************************************
 * @file        main.c
 * @author      Mr.Sea
 * @version     V1.0
 * @date        2026-1-15
 * @brief       自动巡逻智能小车
 ****************************************************************************************************
 */
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/timer.h"
#include "./BSP/AT8236/at8236.h"
#include "encoder.h"
#include "pid.h"
#include "pid_inc.h"
#include "sg90.h"
#include "hcsr04.h"
#include "auto_drive.h"
#include "oled.h"
#include "dht11.h"
#include "voltage.h"
#include "dev_bluetooth.h"
#include "bsp_usart.h"
#include "key.h"
#include "dev_k230.h"
//C库函数
#include 
#include "stdio.h"
#include "math.h"
#include "stdbool.h"
#include "su_03t.h"

/*--------------------------------------全局变量声明-----------------------------------------------*/

/* === 这是送给 PID 计算的"当前爬升速度" (初始化为0) === */
float target_rpm_real_fl = 0.0f;
float target_rpm_real_fr = 0.0f;
float target_rpm_real_rl = 0.0f;
float target_rpm_real_rr = 0.0f;

#define PID_MODE 1                //  1 位置式PID  0 是增量式PID

DHT11_Data_TypeDef dht11;         //  DHT11 结构体变量声明

char oled_buf[128];               //  oled 数据缓存

uint8_t key_num;                  //按键键值
uint8_t Page_flag=1;

char sensor_data[256]; /*发送数据到APP*/
uint8_t BT_Send_flag=1; /*蓝牙发送标志位*/

/*---------------------------------------------------------------------------*/


/*---------------------------------------函数声明-------------------------------------*/
void Ramp_Target(float final, float *curr, float step);
void Show_Data(void);
void Show_Speed(void);
void Page_setting(void);

/*---------------------------------------------------------------------------*/

int main(void)
{
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);     /* 设置时钟,168Mhz */
    delay_init(168);                        /* 延时初始化 */
    SU_03T_Init(115200);
    led_init();                             /* 初始化LED */
    gtim_timx_int_init(100 - 1, 8400 - 1);  /* 定时器初始化 */
    gtim_tim10_int_init(49999, 8399);
    Encoder_Init();                         /* 初始化编码器 (TIM2, 3, 4, 5) */
    Motor_Hardware_Init();                  /* 初始化电机 PWM */
    SG90_Init();                            /* 初始化SG90舵机 PWM */
    Hcsr04Init();                           /*超声波初始化 */
    Auto_Drive_Init();                      /*自动驾驶系统初始化 (归位舵机) */
    DHT11_Init();                           /*初始化DHT11*/
    Voltage_Init();                         /*初始化电压检测*/
    OLED_Init();                            /*OLED 初始化*/
    OLED_Clear(0);                          /*初始化 清屏*/
    key_init();                             /* 按键初始化 */
    BSP_USART_Init();                       /* 串口 蓝牙 K230初始化*/

  #if PID_MODE
    System_PID_Init();                      /*位置式PID算法 初始化*/
  #else
    PID_INC_Init();                         /*增量式PID算法 初始化*/
  #endif

    BEEP = OFF;                             /*初始化 蜂鸣器关*/
    TIM11_Init_Config();                    /*定时器11初始化*/

    printf("START!");
    while(1)
    {
        key_num=key_scan(0);                /* 按键扫描 */
        if(key_num == 1) {
            Page_flag++;
            Page_flag %= 2;
            OLED_Clear(0);
        }

        switch(Page_flag) {
            case 1:
                Show_Data();                //数据显示页面
                break;
            case 0:
                Page_setting();             //设置页面
                break;
        }

        /* 自动驾驶模式 */
        if(C_MODE==auto_mode){Auto_Drive_Task();}

        /* 接收处理蓝牙信息 */
        BT_Task_Parse();

        /* 接收处理K230信息 */
        K230_Task_Parse();

        /* 蓝牙定时发送传感器数据 */
        if(BT_Send_flag==1)
        {
            int len = snprintf(sensor_data, sizeof(sensor_data),
                "data#%d#%d#%d#%d#%3d#%d#\r\n",
                (int)C_MODE,
                dht11.temp_int,
                dht11.humi_int,
                Voltage_Get_Percentage(),
                (int)Hcsr04GetLength(),
                k210_flag);
            if(len > 0 && len < sizeof(sensor_data))
            {
                HAL_UART_Transmit(&huart3, (uint8_t*)sensor_data, len, 100);
            }
            BT_Send_flag=0;                 /*重置发送标志位*/
        }
    }
}

/**
 * @brief  定时器中断服务函数 (PID速度环)
 */
void GTIM_TIMX_INT_IRQHandler(void)
{
    if(__HAL_TIM_GET_FLAG(&timer_handle, TIM_FLAG_UPDATE) != RESET)
    {
        Encoder_Get_All_Speed(10, &motor_fl, &motor_fr, &motor_rl, &motor_rr);

      #if PID_MODE
        float ramp_step = 20.0f;
        Ramp_Target(target_rpm_fl, &target_rpm_real_fl, ramp_step);
        Ramp_Target(target_rpm_fr, &target_rpm_real_fr, ramp_step);
        Ramp_Target(target_rpm_rl, &target_rpm_real_rl, ramp_step);
        Ramp_Target(target_rpm_rr, &target_rpm_real_rr, ramp_step);

        float pwm_fl = PID_Compute(&pid_fl, target_rpm_real_fl, motor_fl.rpm);
        float pwm_fr = PID_Compute(&pid_fr, target_rpm_real_fr, motor_fr.rpm);
        float pwm_rl = PID_Compute(&pid_rl, target_rpm_real_rl, motor_rl.rpm);
        float pwm_rr = PID_Compute(&pid_rr, target_rpm_real_rr, motor_rr.rpm);
      #else
        float ramp_step = 5.0f;
        Ramp_Target(pid_inc_target_rpm_fl, &target_rpm_real_fl, ramp_step);
        Ramp_Target(pid_inc_target_rpm_fr, &target_rpm_real_fr, ramp_step);
        Ramp_Target(pid_inc_target_rpm_rl, &target_rpm_real_rl, ramp_step);
        Ramp_Target(pid_inc_target_rpm_rr, &target_rpm_real_rr, ramp_step);

        float pwm_fl = PID_Inc_Compute(&pid_inc_fl, target_rpm_real_fl, motor_fl.rpm);
        float pwm_fr = PID_Inc_Compute(&pid_inc_fr, target_rpm_real_fr, motor_fr.rpm);
        float pwm_rl = PID_Inc_Compute(&pid_inc_rl, target_rpm_real_rl, motor_rl.rpm);
        float pwm_rr = PID_Inc_Compute(&pid_inc_rr, target_rpm_real_rr, motor_rr.rpm);
      #endif

        Motor_SetSpeed(MOTOR_FL, (int)pwm_fl);
        Motor_SetSpeed(MOTOR_FR, (int)pwm_fr);
        Motor_SetSpeed(MOTOR_RL, (int)pwm_rl);
        Motor_SetSpeed(MOTOR_RR, (int)pwm_rr);

        __HAL_TIM_CLEAR_IT(&timer_handle, TIM_IT_UPDATE);
    }
}

/**
 * @brief  斜坡函数 (实现软启动/软停止)
 */
void Ramp_Target(float final, float *curr, float step)
{
    if (*curr < final) {
        *curr += step;
        if (*curr > final) *curr = final;
    }
    else if (*curr > final) {
        *curr -= step;
        if (*curr < final) *curr = final;
    }
}

/**
 * @brief  TIM10 中断服务函数 (定时发送)
 */
void GTIM_TIM10_INT_IRQHandler(void)
{
    if(__HAL_TIM_GET_FLAG(&timer10_handle, TIM_FLAG_UPDATE) != RESET)
    {
        k210_flag=1;
        BT_Send_flag=1;
        __HAL_TIM_CLEAR_IT(&timer10_handle, TIM_IT_UPDATE);
    }
}

/**
 * @brief  OLED显示温湿度、电量、模式
 */
void Show_Data(void)
{
    static uint16_t dht_timer = 0;
    if(++dht_timer > 5) {
        dht_timer = 0;
        Read_DHT11(&dht11);
    }

    snprintf(oled_buf, sizeof(oled_buf), "温 度:%3d%℃", dht11.temp_int);
    OLED_ShowText(0, 0, (uint8_t *)oled_buf, 0);
    snprintf(oled_buf, sizeof(oled_buf), "湿 度:%3d%%", dht11.humi_int);
    OLED_ShowText(0, 2, (uint8_t *)oled_buf, 0);
    snprintf(oled_buf, sizeof(oled_buf), "电 量:%3d%%", Voltage_Get_Percentage());
    OLED_ShowText(0, 4, (uint8_t *)oled_buf, 0);

    if(key_num==2){
        C_MODE++; if(C_MODE>2){C_MODE=manual_mode;}
        Car_SetMotion(0,0);
    }

    static char mode_text[16];
    switch (C_MODE) {
        case auto_mode:   strcpy(mode_text, "自动"); break;
        case manual_mode: strcpy(mode_text, "手动"); break;
        case gz_mode:     strcpy(mode_text, "跟踪"); break;
        default:          strcpy(mode_text, "未知"); break;
    }
    sprintf(oled_buf, "模 式: %s", mode_text);
    OLED_ShowText(0, 6, (uint8_t*)oled_buf, 0);
}

/**
 * @brief  OLED显示四轮转速
 */
void Show_Speed(void)
{
    snprintf(oled_buf, sizeof(oled_buf), "FL:%3.1f", motor_fl.rpm);
    OLED_ShowText(0, 0, (uint8_t *)oled_buf, 0);
    snprintf(oled_buf, sizeof(oled_buf), "FR:%3.1f", motor_fr.rpm);
    OLED_ShowText(0, 2, (uint8_t *)oled_buf, 0);
    snprintf(oled_buf, sizeof(oled_buf), "BL:%3.1f", motor_rl.rpm);
    OLED_ShowText(0, 4, (uint8_t *)oled_buf, 0);
    snprintf(oled_buf, sizeof(oled_buf), "BR:%3.1f", motor_rr.rpm);
    OLED_ShowText(0, 6, (uint8_t *)oled_buf, 0);
}

/**
 * @brief  设置页面 (速度、安全距离)
 */
void Page_setting(void)
{
    static uint8_t Index_flag = 0;
    snprintf(oled_buf, sizeof(oled_buf), "速  度:%d",  SPEED);
    OLED_ShowText(16, 0, (uint8_t *)oled_buf, 0);
    snprintf(oled_buf, sizeof(oled_buf), "安全距离A:%3d", OBSTACLE_FRONT_DIST);
    OLED_ShowText(16, 2, (uint8_t *)oled_buf, 0);
    snprintf(oled_buf, sizeof(oled_buf), "安全距离B:%3d", OBSTACLE_SIDE_DIST);
    OLED_ShowText(16, 4, (uint8_t *)oled_buf, 0);

    if(key_num == 2) {
        Index_flag++;
        Index_flag = Index_flag % 3;
    }

    switch(Index_flag) {
        case 0:
            OLED_ShowString(0, 0, (uint8_t *)">", 16);
            OLED_ShowString(0, 2, (uint8_t *)" ", 16);
            OLED_ShowString(0, 4, (uint8_t *)" ", 16);
            break;
        case 1:
            OLED_ShowString(0, 0, (uint8_t *)" ", 16);
            OLED_ShowString(0, 2, (uint8_t *)">", 16);
            OLED_ShowString(0, 4, (uint8_t *)" ", 16);
            break;
        case 2:
            OLED_ShowString(0, 0, (uint8_t *)" ", 16);
            OLED_ShowString(0, 2, (uint8_t *)" ", 16);
            OLED_ShowString(0, 4, (uint8_t *)">", 16);
            break;
    }

    if(Index_flag == 0 && key_num == 3) SPEED++;
    if(Index_flag == 0 && key_num == 4) { SPEED > 0 ? SPEED-- : 0; }
    if(Index_flag == 1 && key_num == 3) OBSTACLE_FRONT_DIST++;
    if(Index_flag == 1 && key_num == 4) { OBSTACLE_FRONT_DIST > 0 ? OBSTACLE_FRONT_DIST-- : 0; }
    if(Index_flag == 2 && key_num == 3) OBSTACLE_SIDE_DIST++;
    if(Index_flag == 2 && key_num == 4) { OBSTACLE_SIDE_DIST > 0 ? OBSTACLE_SIDE_DIST-- : 0; }
}

软件架构说明:

系统共分为多个BSP(板级支持包)层模块,各模块职责如下:

模块文件功能
系统初始化sys.c时钟配置168MHz
电机驱动at8236.cAT8236 PWM/方向控制
编码器encoder.c四路编码器速度采集
PID控制pid.c / pid_inc.c位置式/增量式PID速度环
自动驾驶auto_drive.c超声波避障与自主巡航决策
舵机sg90.cSG90角度控制
超声波hcsr04.cHC-SR04测距驱动
温湿度dht11.cDHT11单总线读写
电压检测voltage.cADC电池电压采集
OLEDoled.cSSD1306 I2C显示驱动
蓝牙dev_bluetooth.c蓝牙数据收发解析
K230通信dev_k230.cK230串口指令解析
语音su_03t.cSU03T离线语音识别
按键key.c按键扫描与消抖

主循环在while(1)中交替执行:按键扫描→页面刷新→自动驾驶任务→蓝牙指令解析→K230数据解析→传感器数据定时发送。定时器中断以10ms周期执行PID闭环控制,斜坡函数Ramp_Target实现软启动/软停止,避免电机突然加减速造成的机械冲击。

实物展示说明

  • 正面整体照片,展示小车底盘、四轮、各传感器模块的布局位置

IMG_20260116_191023.jpg

IMG_20260117_000548.jpg

跌倒检测小车.jpg

注意事项

  • 焊接:电机驱动模块和K230模块供电电流较大,电源焊点需饱满,避免虚焊导致供电不稳定。各模块的VCC和GND不要接反。
  • 接线:蓝牙JDY-31的RX/TX注意交叉连接(MCU TX→蓝牙RX,MCU RX→蓝牙TX)。
  • 上电调试顺序:先单独测试各模块功能(LED→OLED→按键→DHT11→超声波→电机→蓝牙→语音→K230),确认各模块正常后再联调整体功能。初次上电前用万用表检测电源与地之间是否短路。
  • 常见问题:DHT11读取失败通常是因为时序不满足(延时函数不准确),检查系统时钟配置。电机不动或抖动可能是PWM频率太低,建议设置在10kHz以上。蓝牙无法连接时检查波特率是否匹配(JDY-31默认9600)。
  • K230模块:需独立5V/2A供电,不可与MCU共用同一路3.3V LDO。模块上电后需要约5秒初始化时间,MCU应在延时后发查询指令。
  • PID调试:车速闭环调试时,先调P(比例),观察到振荡后再加D(微分)抑制,最后加I(积分)消除稳态误差。实际调试时建议从小P值开始逐步增大。

演示视频

B站链接
https://www.bilibili.com/video/BV11sV66sEA4/?spm_id_from=333.1387.homepage.video_card.click&vd_source=1e24b3a879361f5e054c989322fca017

其它附件上传

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
暂无数据
克隆工程
添加到专辑
0
0
分享
侵权投诉
知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

底部导航