返回项目列表
基于 FreeRTOS 的自主导航车

基于 FreeRTOS 的自主导航车

2026.02 – 2026.04嵌入式小车
STM32FreeRTOSPID电机控制超声波语音交互

基于 STM32 与 FreeRTOS 的多任务自主导航小车,集成循迹、避障、离线语音交互与电机闭环控制,采用串级 PID + 积分分离算法实现稳定巡迹。

硬件平台
  • STM32F103C8T6
  • L298N / TB6612 电机驱动
  • HC-SR04 超声波模块 × 3
  • 红外循迹传感器阵列
  • 离线语音模块
  • 编码器测速
软件工具
  • Keil MDK
  • FreeRTOS
  • 标准库开发
  • 串级 PID 控制器

项目概述

本项目为校级嵌入式设计竞赛参赛作品,设计了一款基于 STM32 + FreeRTOS 的自主导航小车。系统集成了循迹、多方位超声波避障、离线语音交互与电机闭环控制功能,通过合理的 RTOS 任务划分与串级 PID 控制,实现了复杂场景下的稳定运行。

核心指标:

  • 控制周期:10 ms(100 Hz)
  • 循迹精度:中心线偏差 < 5 mm
  • 避障响应:检测距离 2 cm ~ 400 cm
  • 语音指令识别率:> 90%(安静环境)

系统架构

┌─────────────────────────────────────────────┐
│              FreeRTOS 内核                    │
│  ┌─────────┐ ┌─────────┐ ┌──────────────┐  │
│  │ 循迹任务 │ │ 避障任务 │ │  语音交互任务 │  │
│  │ 高优先级 │ │ 中优先级 │ │   中优先级    │  │
│  └────┬────┘ └────┬────┘ └──────┬───────┘  │
│       │           │             │           │
│  ┌────┴────┐ ┌────┴────┐ ┌──────┴───────┐  │
│  │ 电机控制 │ │ 状态机  │ │   指令解析    │  │
│  │ 任务    │ │ 管理    │ │              │  │
│  └────┬────┘ └────┬────┘ └──────┬───────┘  │
│       └───────────┴─────────────┘           │
│              消息队列 + 事件组               │
└─────────────────────────────────────────────┘

FreeRTOS 多任务设计

任务划分

| 任务 | 优先级 | 周期 | 职责 | |------|--------|------|------| | 循迹任务 | 3(高) | 10 ms | 读取红外阵列,计算偏差 | | 避障任务 | 2(中) | 50 ms | 超声波测距,决策避障策略 | | 语音交互任务 | 2(中) | 100 ms | 解析语音指令,发布控制事件 | | 电机控制任务 | 3(高) | 10 ms | 串级 PID 更新,输出 PWM | | 状态显示任务 | 1(低) | 200 ms | OLED 刷新、LED 指示 |

消息队列与阻塞唤醒

采用 消息队列 替代传统轮询,传感器数据通过队列投递至控制任务:

/* 传感器数据队列 */
QueueHandle_t xSensorQueue;
xSensorQueue = xQueueCreate(10, sizeof(SensorData_t));

/* 循迹任务:采样后入队 */
void TrackTask(void *pvParameters) {
    SensorData_t data;
    while (1) {
        data.error = ReadTrackSensor();
        xQueueSend(xSensorQueue, &data, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

/* 电机控制任务:阻塞等待队列数据 */
void MotorControlTask(void *pvParameters) {
    SensorData_t data;
    while (1) {
        if (xQueueReceive(xSensorQueue, &data, portMAX_DELAY)) {
            PID_Update(&pid, data.error);
            SetMotorPWM(pid.output);
        }
    }
}

串级 PID 控制器

双环结构

  • 外环(位置环):以循迹偏差为输入,输出目标速度
  • 内环(速度环):以编码器测速为反馈,输出 PWM 占空比
typedef struct {
    float Kp, Ki, Kd;
    float err, err_last;
    float integral;
    float output_max;
    uint8_t integral_separate;  /* 积分分离标志 */
} PID_Controller;

float PID_Update(PID_Controller *pid, float setpoint, float feedback)
{
    float err = setpoint - feedback;

    /* 积分分离:大偏差时不积分,消除超调 */
    if (fabs(err) < INTEGRAL_THRESHOLD) {
        pid->integral += err;
    } else {
        pid->integral = 0;
    }

    float output = pid->Kp * err
                 + pid->Ki * pid->integral
                 + pid->Kd * (err - pid->err_last);

    pid->err_last = err;
    return constrain(output, -pid->output_max, pid->output_max);
}

积分分离效果

| 工况 | 无积分分离 | 有积分分离 | |------|-----------|-----------| | 直道起步 | 超调 15% | 超调 3% | | 低速弯道 | 等幅振荡 | 稳定跟踪 | | 急弯切换 | 脱线率 20% | 脱线率 5% |

避障与多指令冲突处理

平滑调速策略

避障时不是直接关断 PWM,而是采用 渐进减速 + 转向绕行

void ObstacleAvoidance(float distance) {
    if (distance < 10.0f) {
        target_speed *= 0.3f;   /* 急刹减速 */
        steering = EMERGENCY_TURN;
    } else if (distance < 30.0f) {
        target_speed *= 0.6f;   /* 平滑减速 */
        steering = GENTLE_TURN;
    }
}

新指令覆盖策略

语音指令与自动循迹/避障可能产生冲突,采用 有限状态机(FSM) 管理模式优先级:

        ┌─────────┐
   ┌───▶│  待机   │◀───┐
   │    └────┬────┘    │
   │         │ 语音启动 │
   │         ▼         │
   │    ┌─────────┐    │
   └────│  循迹   │────┘
        └────┬────┘
             │ 检测到障碍
        ┌─────────┐
   ┌───▶│  避障   │────┐
   │    └─────────┘    │
   │         │         │
   └─────────┴─────────┘
  • 语音指令具有最高优先级,可强制切换状态
  • 避障完成后自动恢复循迹
  • 新指令覆盖旧指令,避免队列堆积

项目成果

  • 小车支持离线语音控制(前进/后退/左转/右转/停止)
  • 三方位超声波实现多角度避障,无盲区
  • 循迹稳定,直道与弯道切换流畅
  • 获校级嵌入式设计竞赛一等奖