Cust17 智能小车技术文档¶
1. 项目概述¶
本项目是基于 ESP32-S3 的麦克纳姆轮智能小车项目。采用 PlatformIO (Arduino 框架) 开发,支持蓝牙手柄控制、MQTT 远程控制、网页遥控和 TTL 串口通信等多种控制方式,具备 PID 闭环速度控制、姿态感知、OTA 固件升级等功能。
项目定位: 四轮全向移动底盘,适用于机器人教育、ROS 底层平台、远程监控等场景。
2. 硬件平台¶
硬件差异说明: 项目支持 V3 和 V5 两代小车,电机参数不同(见
Head.h)。开发文档中的默认值为 V3 车参数,使用 V5 车需切换注释并测量实际轮距轴距。
| 组件 | 说明 |
|---|---|
| 主控芯片 | ESP32-S3 (ESP32-S3-DevKitC-1) |
| 电机驱动 | QGPMaker EmotionPI 驱动板 (MCPWM 控制) |
| 电机 | 4路直流减速编码器电机 (1:90 减速比 / 1:50 减速比) |
| 编码器 | 霍尔编码器,48 线/圈 (经倍频后每圈 48×4 = 192 脉冲) |
| 轮系 | 麦克纳姆轮/普通橡胶轮 (可切换) |
| IMU | MPU6050 六轴陀螺仪+加速度计 |
| 磁力计 | QMC5883L 三轴电子罗盘 |
| 显示 | SSD1306 OLED 128×64 (I2C) |
| LED | WS2812B 单灯珠 |
| 舵机 | 4路舵机接口 |
| 供电 | 24V 锂电池 (带分压 ADC 采样) |
2.1 引脚定义¶
编码器引脚(可配置,默认):
| 通道 | A 相 | B 相 |
|---|---|---|
| 电机 1 | 42 | 41 |
| 电机 2 | 39 | 40 |
| 电机 3 | 4 | 18 |
| 电机 4 | 48 | 38 |
电机 PWM 引脚:
| 通道 | PWM A | PWM B |
|---|---|---|
| 电机 1 | 3 | 10 |
| 电机 2 | 11 | 12 |
| 电机 3 | 14 | 13 |
| 电机 4 | 47 | 21 |
舵机引脚: 5, 6, 7, 15
其他引脚: - LED: GPIO 46 - 电池 ADC: GPIO 2 - 串口 1: RX=15, TX=16
3. 软件架构¶
src/
├── main.cpp # 主程序:初始化和主循环
├── main.h # 主头文件:声明和全局变量
└── html/ # 网页遥控器前端
├── joy.html # 网页遥控器界面
├── main.js # MQTT 通信和摇杆逻辑
└── style.css # 样式表
lib/
├── Head/
│ ├── Head.h # 硬件参数配置和数据结构
│ └── utils.h # 工具函数:WiFi、OTA、电池、IMU初始化等
├── Config/
│ ├── ConfigSeting.h # 配置管理类声明
│ └── ConfigSeting.cpp # NVS 配置读写实现
├── motor/
│ ├── EMotionPI.h # 电机驱动库 (QGPMaker)
│ └── EMotionPI.cpp # 直流电机、编码器电机、舵机、底盘控制
├── encoder/
│ ├── Encoder.h # 编码器封装类
│ └── Encoder.cpp # RPM 计算实现
├── Pid/
│ └── pid.h # PID 控制器实现 (全头文件)
├── protocal/
│ └── protocol.h # 串口通信协议 (全头文件)
├── ControlStick/
│ ├── BLEControlStick.h/cpp # BLE 蓝牙手柄
│ ├── StickCB.h/cpp # 手柄回调处理
│ ├── BLEControlStick.h/cpp # BLE 手柄接入
├── MqttServer/
│ ├── MqttServer.h/cpp # MQTT 远程控制
├── OTA/
│ ├── OTAupdate.h/cpp # 远程固件升级
├── display/
│ ├── Display.h/cpp # OLED 显示
├── kinematics/
│ ├── kinematics.h/cpp # 运动学解算
├── mpu6050/
│ ├── Imu.h/cpp # MPU6050 封装
│ └── MPU6050_*.h/cpp # MPU6050 库
└── QMC5883LCompass/
└── QMC5883LCompass.h/cpp # 磁力计库
4. 模块详解¶
4.1 主控流程 (main.cpp)¶
初始化顺序 (setup):
- 串口初始化 (Serial + Serial1)
- 从 NVS 读取配置 (编码器引脚、速度参数)
- 初始化编码器 (4路)
- 初始化 BLE 蓝牙手柄
- 初始化 QMC5883L 磁力计 + MPU6050 陀螺仪
- 连接 WiFi、初始化 WS2812 LED
- 初始化 PID 控制器
- 初始化 MQTT 服务
- 创建 FreeRTOS 任务
xCore_task(运行在 Core 0)
主循环 (loop):
- 心跳 20ms:处理 MQTT 消息
- 停车检测:超过 200ms 无命令自动停车
- TTL 串口数据收发:解析控制协议
Core 0 任务 (xCore_task):
- 更新 BLE 手柄状态
- 编码器引脚自动测试(按住 START 键触发)
- 姿态数据上报(每 100ms):电压、角度、四轮 RPM → 线速度/角速度 → CRC 打包 → Serial1 发送
- 电压补偿:低于 24V 标准电压时自动降低最大 RPM
4.2 控制模式¶
4.2.1 蓝牙手柄控制¶
通过 BLE 连接标准游戏手柄(服务 UUID: 1812,特征值 UUID: 2A4D)。
手柄按键映射:
| 按键 | 功能 |
|---|---|
| 左摇杆 | 前后/横移 (速度按幅度比例) |
| 右摇杆 (左右) | 旋转 (麦轮模式) / 舵机 (普通模式) |
| 方向键 ↑↓ | 前后 |
| 方向键 ←→ | 横移 (麦轮) / 旋转 (普通) |
| L1/R1 | 降低/提高最大速度上限 |
| L2/R2 | 降低/提高最低起步速度 |
| SELECT | 切换车型:麦轮模式(蓝灯) / 普通模式(红灯) |
| START | 进入编码器自动测试模式 |
| A/B/X/Y | 预留功能键 |
| 右摇杆 (上下) | 舵机角度控制 |
4.2.2 串口协议控制 (TTL)¶
通过 Serial1 (波特率 115200) 与上位机通信。协议详见第 5 节。
4.2.3 MQTT 远程控制¶
通过 MqttServer 模块连接远端 MQTT 服务器(121.40.244.99:1883),订阅 evtopic/wfjy/{clientId} 主题,接收 JSON 格式的控制指令。
4.2.4 网页遥控器¶
前端项目位于 src/html/,提供:
- 双摇杆控制(锁定/自由模式可切换)
- 方向键 + A/B/X/Y 按钮
- MQTT 直连通信(WebSocket)
- 通讯标识可配置(Cookie 存储)
4.3 运动学¶
4.3.1 麦克纳姆轮逆解¶
wheelDelta = z_rpm × (轮距 + 轴距) / 轮周长
轮1 (左前) = x_rpm + y_rpm + wheelDelta
轮2 (右后) = x_rpm - y_rpm - wheelDelta
轮3 (左后) = x_rpm - y_rpm + wheelDelta
轮4 (右前) = x_rpm + y_rpm - wheelDelta
4.3.2 PID 闭环控制¶
每个电机独立 PID 控制器:
| 参数 | 值 |
|---|---|
| Kp | 0.25 |
| Ki | 0.02 |
| Kd | 0.5 |
| 输出范围 | -100 ~ 100 |
特性:
- 积分限幅 ±10
- 死区补偿(PWM < deadPwm 时直接设为 deadPwm)
- 满负荷检测:连续 10 次输出达 ±100 时自动降低速度因子(每次 -0.1,最低 50%)
4.4 姿态感知¶
融合算法:互补滤波
fusion = 0.7 × 编码器角速度 + 0.3 × IMU 角速度
- 编码器角速度:通过四轮差速公式计算
- IMU 角速度:MPU6050 DMP 输出的角度差/时间 (100ms)
- 最终输出经低通滤波平滑 (
last × 0.3 + current × 0.7)
4.5 编码器测试¶
按住手柄 START 键进入自动测试模式: 1. 4 个电机同向低速旋转 2. 检测编码器计数值变化方向 3. 若计数为负(接线反),自动交换 A/B 相并保存配置 4. 重启生效
4.6 配置管理 (NVS)¶
使用 ESP32 NVS (Preferences) 存储:
| 配置项 | 说明 |
|---|---|
| model | 0=麦轮, 1=普通 |
| max_speed | 最大速度百分比 (0-100) |
| min_speed | 最低起步速度百分比 (0-100) |
| E1_a~E4_b | 编码器引脚定义 |
| wifi_ssid/pwd | WiFi 凭据 |
| mqtt_cid | MQTT 客户端 ID |
默认配置存储为 JSON 字符串,键为 wifi_ssid,命名空间 mynamespace。
5. 通信协议¶
注意: 所有多字节字段(数据长度、数据体、CRC)均采用小端序(Little Endian),低字节在前。
5.1 数据包格式¶
帧头(2B) + 数据长度(2B) + 设备ID(1B) + 命令字(1B) + 数据体(NB) + CRC16(2B)
| 偏移 | 大小 | 说明 |
|---|---|---|
| 0 | 1 | 帧头1: 0xAA |
| 1 | 1 | 帧头2: 0x55 |
| 2 | 2 | 数据长度 (设备ID+命令+数据体) 小端 |
| 4 | 1 | 设备 ID |
| 5 | 1 | 命令字 |
| 6 | N | 数据体 (小端) |
| 6+N | 2 | CRC16 (Modbus) 小端 |
5.2 命令定义¶
| 命令 | 值 | 方向 | 说明 |
|---|---|---|---|
| CMD_pwmDrive | 0x0A | 上位机→小车 | PWM 速度控制 |
| CMD_rosDrive | 0x0B | 上位机→小车 | 三轴速度控制 (mm/s) |
| CMD_rotation | 0x0C | 上位机→小车 | 旋转控制 |
| CMD_pose | 0x30 | 小车→上位机 | 姿态数据上报 |
5.3 控制命令数据体¶
CMD_pwmDrive (0x0A) - PWM 百分比控制:
| 偏移 | 类型 | 说明 |
|---|---|---|
| 0-1 | int16 LE | X 轴速度 (-100~100) |
| 2-3 | int16 LE | Y 轴速度 (-100~100) |
| 4-5 | int16 LE | Z 轴旋转速度 (-100~100) |
内部转换:targetRPM = speed × maxRpm × 0.01
CMD_rosDrive (0x0B) - 物理速度控制:
| 偏移 | 类型 | 说明 |
|---|---|---|
| 0-1 | int16 LE | X 轴线速度 (mm/s) |
| 2-3 | int16 LE | Y 轴线速度 (mm/s) |
| 4-5 | int16 LE | Z 轴角速度 (deg/s) |
内部转换:线速度 → RPM,角速度 → 差速 RPM
5.4 姿态上报数据体 (CMD_pose 0x30)¶
小车每 100ms 自动向串口发送:
| 偏移 | 类型 | 说明 |
|---|---|---|
| 0-1 | int16 LE | 电池电压 (×0.1V) |
| 2-3 | int16 LE | Z 轴角度 (0~359°) |
| 4-5 | int16 LE | X 轴线速度 (mm/s) |
| 6-7 | int16 LE | Y 轴线速度 (mm/s) |
| 8-9 | int16 LE | Z 轴角速度 (deg/s, 融合值) |
5.5 CRC16 算法 (Modbus)¶
多项式: 0xA001
初始值: 0xFFFF
计算范围: 帧头 + 长度 + 设备ID + 命令 + 数据体
6. 使用指南¶
6.1 开发环境搭建¶
- 安装 VS Code + PlatformIO 扩展
- 打开
cust17/目录 - PlatformIO 将自动安装依赖库
- 编译上传:
PlatformIO: Upload
6.2 项目配置¶
platformio.ini 关键配置:
[env:esp32dev]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
依赖库:
| 库 | 用途 |
|---|---|
| NimBLE-Arduino | BLE 蓝牙 |
| ArduinoJson | JSON 解析 |
| ESP32Servo | 舵机控制 |
| ESP32Encoder | 编码器计数 |
| PubSubClient | MQTT 客户端 |
| ESPAsyncWebServer-esphome | 异步 Web 服务器 |
| FastLED | WS2812 LED |
6.3 硬件参数校准¶
Head.h 中的以下参数必须根据实际车体测量调整:
| 参数 | 说明 | 默认值 | 测量方法 |
|---|---|---|---|
maxRpm |
电机理论最大转速 (RPM) | 110 (1:90减速) / 120 (1:50减速) | 查电机规格书 |
gear |
减速器齿数比 | 90 / 50 | 减速器标识 |
encoderTicksPerRevolution |
编码器每圈线数 | 48 | 编码器规格书 |
deadPwm |
电机启动最小 PWM | 40 / 30 | 实测:逐渐增大PWM至轮子刚好转动 |
wheelCircumference |
轮子周长 (mm) | π × 80 / π × 127 | 实测:轮子转一圈前进距离 |
wheelSpacing |
轮距 (mm) | 220 | 左右轮中心距 |
wheelBase |
轴距 (mm) | 200 | 前后轮中心距 |
⚠️ 务必根据实际车体测量上述参数,否则会导致速度控制不准、旋转偏移等问题。
6.4 首次使用¶
- 编译并上传固件至 ESP32-S3
- 上电后 OLED 显示"奇果派"启动画面
- 蓝牙手柄搜索并连接 (服务名
BLE-ControlStick) - 手柄 SELECT 键切换车型模式
- 摇杆控制车辆移动
6.5 速度参数调优¶
- 手柄实时调节: L1/R1 调最大速度,L2/R2 调起步速度
- 代码修改: 硬件物理参数见
Head.h(详见 6.3 节),PID 参数见pid.h - PID 调节:
pid.h中setupPID()函数的 Kp/Ki/Kd
7. 注意事项¶
- 电压补偿: 电池电压低于 24V 时自动降速,每降低 1V 最大转速降低 10%
- 过载保护: PID 输出持续满负荷时自动降低速度因子,防止电机过热
- 停车安全: 200ms 无控制命令自动停止
- 编码器接线: 首次使用建议按住 START 键运行编码器自检
- 通信冲突: 蓝牙手柄命令和 TTL 串口命令间隔需大于 500ms
8. 版本历史¶
| 版本 | 日期 | 说明 |
|---|---|---|
| 1.0 | - | 初始版本 |
文档生成日期:2026年6月