用STM32F103C8T6和F9P模组DIY一台RTK高精度导航小车(附PCB文件与源码)
用STM32F103C8T6和F9P模组打造高精度RTK导航小车的完整指南
在创客圈子里,导航小车一直是热门项目,但普通GPS的定位精度往往让人失望——误差动辄两三米,根本无法满足精准控制的需求。而RTK(实时动态定位)技术能将定位精度提升到厘米级,这为DIY导航小车打开了全新可能。本文将手把手教你如何用STM32F103C8T6主控和F9P RTK模块,从零开始打造一台真正可用的高精度导航小车。
1. 核心硬件选型与原理
1.1 为什么选择STM32F103C8T6作为主控
这款经典的"蓝色药丸"开发板在创客圈经久不衰是有原因的:
- 性价比突出:20元左右的价位提供了72MHz主频的Cortex-M3内核
- 丰富外设:3个USART、2个SPI、2个I2C接口完美适配各类传感器
- 开发生态成熟:无论是HAL库还是标准库都有海量参考资料
- 引脚兼容性:48脚的LQFP封装方便自制PCB时布线
实际项目中,我们主要用到了它的以下资源:
USART1 - 连接F9P模块获取RTK数据 USART2 - 连接蓝牙模块用于调试 TIM1/TIM4 - 生成PWM控制电机 SPI1 - 连接陀螺仪模块1.2 F9P RTK模块的工作原理
F9P是u-blox推出的双频RTK接收模块,其核心技术特点包括:
| 参数 | 普通GPS | F9P RTK |
|---|---|---|
| 定位精度 | 2-5米 | 1-2厘米 |
| 刷新率 | 1-10Hz | 最高20Hz |
| 启动时间 | 30秒 | <10秒 |
| 价格 | 100-300元 | 约800元 |
RTK实现厘米级定位的关键在于:
- 基站与移动站同时接收卫星信号
- 基站将定位误差数据通过无线数传发送给移动站
- 移动站进行载波相位差分计算
提示:如果预算有限,可以使用开源RTK基站方案如RTKLIB,但商用基站(如千寻位置)的稳定性更好。
2. 电路设计与PCB制作
2.1 电机驱动电路设计
TB6612FNG是比传统L298N更优的选择:
- 效率更高:MOSFET驱动比L298N的达林顿管发热小
- 集成度高:单芯片包含双H桥和逻辑控制
- 保护完善:内置过热关断和短路保护
典型应用电路如下:
VM - 接7-12V电源 VCC - 接5V逻辑电源 AO1/AO2 - 接电机A BO1/BO2 - 接电机B PWMA/PWMB - 接STM32 PWM输出 AIN1/AIN2 - 电机方向控制2.2 PCB布局注意事项
在绘制四层PCB时,我总结了几个关键经验:
电源分区:
- 电机驱动部分单独供电
- 数字地与模拟地通过0Ω电阻单点连接
- 每个IC旁放置0.1μF去耦电容
信号完整性:
- F9P的UART走线远离PWM信号
- 晶振下方禁止走线
- 保持差分对等长(如USB D+/D-)
散热设计:
- TB6612底部敷铜并开窗
- LDO加装小型散热片
- 避免大电流走线过孔
注意:首次打板建议选择嘉立创的"经济型"选项,5元/10片足够验证设计。
3. 软件架构与关键算法
3.1 多任务调度设计
在FreeRTOS上,我划分了以下任务:
RTK数据处理任务(优先级3)
- 解析UBX协议
- 坐标转换(WGS84转局部坐标系)
- 卡尔曼滤波
电机控制任务(优先级4)
- 增量式PID计算
- PWM占空比更新
- 编码器计数读取
无线通信任务(优先级2)
- 蓝牙AT指令处理
- 数传模块数据打包
状态监控任务(优先级1)
- 电池电压检测
- 系统异常报警
任务间通过消息队列通信,关键数据使用互斥锁保护。
3.2 增量式PID实现
小车直线行驶的稳定性全靠PID算法,以下是经过实测调优的参数:
typedef struct { float Kp; // 比例系数 float Ki; // 积分系数 float Kd; // 微分系数 float integral_limit; // 积分限幅 float output_limit; // 输出限幅 float last_error; // 上次误差 float prev_error; // 上上次误差 } PID_HandleTypeDef; void PID_Update(PID_HandleTypeDef *pid, float error) { float p_out = pid->Kp * error; pid->integral += error; pid->integral = constrain(pid->integral, -pid->integral_limit, pid->integral_limit); float i_out = pid->Ki * pid->integral; float d_out = pid->Kd * (error - pid->last_error); pid->output = p_out + i_out + d_out; pid->output = constrain(pid->output, -pid->output_limit, pid->output_limit); pid->prev_error = pid->last_error; pid->last_error = error; }调试技巧:
- 先调P直到出现小幅振荡
- 加入D抑制振荡
- 最后加I消除静差
- 户外测试时准备螺丝刀随时微调
4. 组装调试与实战技巧
4.1 机械组装要点
经过三次迭代,我的结构设计总结:
- 重心分配:电池放在底盘中部偏后位置
- 轮距选择:20cm轮距适合室内外通用
- 天线安装:F9P天线尽量远离电机和金属部件
- 减震设计:在底盘与上层板之间加装橡胶柱
常见问题排查表:
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 定位漂移 | 天线被遮挡 | 调整天线位置 |
| 电机抖动 | PWM频率过低 | 改为20kHz |
| 串口丢包 | 波特率不匹配 | 检查两端配置 |
| 突然重启 | 电源线虚焊 | 重新焊接 |
4.2 场地测试经验
在不同环境下的实测表现:
开阔广场:
- 固定解时间:<30秒
- 定位精度:±1cm
- 续航时间:2小时
林荫道:
- 固定解时间:1-2分钟
- 定位精度:±3cm
- 需注意树叶遮挡
室内近窗:
- 仅能获得浮点解
- 精度下降至±50cm
- 需融合陀螺仪数据
一个实用技巧:在场地四角放置反射标记,当RTK信号丢失时可以通过视觉辅助定位。
