基于 双 ESP32 微控制器的智能小车系统,集成蓝牙遥控、五路 ADC 红外循迹、视觉里程计与任务链自动执行。
采用 MicroPython 运行时环境,模块化分层架构。
┌──────────────────────────────────┐
│ 手机 / 上位机 │
│ BLE 4.2 Nordic UART │
└──────────────┬───────────────────┘
│ BLE 广播 (EspCar-049)
▼
┌──────────────────────────────────────────────────────────┐
│ ESP32-V1 (主控制器) │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 应用层 app/ car_app.py (状态机 + 调度器) │ │
│ │ mode_*.py (5种工作模式) │ │
│ ├────────────────────────────────────────────────────┤ │
│ │ 算法层 alg/ task_chain.py (任务链表执行器) │ │
│ ├────────────────────────────────────────────────────┤ │
│ │ 底盘层 chassis/ diffChassis.py (差速运动学) │ │
│ ├────────────────────────────────────────────────────┤ │
│ │ 驱动层 peripheral/ BLE / CAM UART / 电机 / 循迹 │ │
│ └────────────────────────────────────────────────────┘ │
└──────────────────────┬───────────────────────────────────┘
│ UART 115200bps
▼
┌──────────────────────────────────────────────────────────┐
│ ESP32-S3-CAM (视觉感知单元) │
│ MPU6050 (I2C) → 姿态估计 → 航向角 │
│ OV2640 → [预留] │
│ 里程计数据 5Hz 推送 │
└──────────────────────────────────────────────────────────┘
| 模组 | 芯片 | 功能 |
|---|---|---|
| 主控制器 | ESP32-V1 (Xtensa LX6, 240MHz) | BLE 遥控、五路 ADC 循迹、电机控制、任务链执行 |
| 视觉模块 | ESP32-S3-CAM + OV2640 + MPU6050 | 航向角解算、加速度里程计、UART 数据推送 |
- STANDBY [0] — 待机安全态
- REMOTE [1] — 蓝牙摇杆遥控(手机 / PC / 游戏手柄)
- TRACKING [2] — PD 闭环循迹(五路 ADC 加权质心 + 三态出线恢复)
- TASK CHAIN [3] — 任务链自动执行(链表式多节点编排)
- FUSION [4] — 融合里程计(编码器 + CAM 航向角)
START 键循环切换:STANDBY → REMOTE → TRACKING → TASK → FUSION → STANDBY
EspCar/
├── .gitignore
├── 创新认知与实践(二)-综合设计报告.docx # 课程设计报告模板
├── PPT制作指南.md # PPT 制作参考
│
├── espv3/ # ── 主控制器 (ESP32-V1) ──
│ ├── task_chain_plan.md # 任务链系统设计文档
│ ├── docs/
│ │ ├── board/ProDoc_ESP_32_2_2026-05-23.eprj2 # PCB 设计文件
│ │ └── esp32v1/ # 板级规格书与原理图
│ └── src/ # ★ 固件源码
│ ├── main.py # 入口 (→ car_app.run())
│ ├── pin_map.py # GPIO 引脚绑定 + 安全校验
│ ├── 协议.md # BLE 二进制帧协议规范 V1.0
│ ├── app/ # 应用层
│ │ ├── car_app.py # 整车状态机 + 帧分发调度器
│ │ ├── ble_handler.py # BLE 帧解析 FSM (6 状态)
│ │ ├── mode_standby.py # 待机模式
│ │ ├── mode_remote.py # 遥控模式 (摇杆 + 按键)
│ │ ├── mode_tracking.py # 循迹模式 (PD 控制)
│ │ └── mode_fusion.py # 融合里程计模式
│ ├── alg/ # 算法层
│ │ └── task_chain.py # TaskNode + TaskChain 链表执行器
│ ├── chassis/ # 底盘控制层
│ │ └── diffChassis.py # 开环/闭环差速底盘 (死区补偿 + PID)
│ ├── peripheral/ # 外设驱动层
│ │ ├── ble_uart.py # BLE 4.2 NUS GATT 服务
│ │ ├── cam_uart.py # CAM UART 协议 (握手/保活/帧解析)
│ │ ├── fusion.py # 融合里程计 (编码器 + CAM yaw)
│ │ ├── motor.py # 电机驱动 (Motor / Encoder / HWEncoder)
│ │ └── tracker.py # 五路 ADC 循迹 + 三态恢复状态机
│ ├── test/ # 模块测试脚本
│ │ ├── motor_openloop_test.py
│ │ ├── encoder_raw_test.py
│ │ ├── encoder_odometry_test.py
│ │ └── pcnt_test.py
│ ├── upper_example/ # PC 端上位机示例
│ │ ├── ble_uart_client.py # BLE 客户端 (Bleak + 手柄支持)
│ │ ├── pid.json # PID 参数模板
│ │ └── task.json # 任务链配置模板
│ └── Usr/ # 技术文档
│ ├── espcar_overview.tex # 技术白皮书 LaTeX 源码
│ └── espcar_overview.pdf # 编译版 PDF
│
└── esps3cam/ # ── 视觉模块 (ESP32-S3-CAM) ──
├── README.md # 模块说明
├── docs/ # 原理图与固件
│ ├── ESP32-S3EXB原理图.pdf
│ ├── ESP32-S3-N16R8核心板原理图.pdf
│ └── ESP32-S3-N16R8-MPY-V1.1.bin # MicroPython 固件
├── host/ble_uart_client.py # BLE 上位机模板 (占位)
└── src/ # ★ 固件源码
├── main.py # CAM 主程序
├── pin_map.py # I2C 引脚定义
├── docs/uart_protocol.md # CAM UART 通信协议规范
└── thirdparty/ # 第三方库
├── mpu6050/ # MPU6050 驱动 (MicroPython + C++源)
└── example/ # 外设驱动示例 (ADC/DHT/超声波等)
vL = v - ω·L/2 左轮速度 (m/s)
vR = v + ω·L/2 右轮速度 (m/s)
L = 0.133m (轮距) r = 0.024m (车轮半径)
电机存在约 38% 启动死区,采用线性插值补偿:
compensated = deadzone + (1 - deadzone) × |speed|
五路 ADC 归一化 → 二值化 → 质心偏移:
e = Σ(wi × bi) / Σ(bi) 权重 w = [-2, -1, 0, 1, 2]
ω = Kp·e + Kd·ė Kp=1.6, Kd=0.15
v = base_v - v_scale·|e| base_v=0.28, v_scale=0.06
Δd = Δpulse × 2πr / (PPR × 4) = Δpulse × 7.54×10⁻⁵ m
PPR = 500, 4 倍频正交解码
ONLINE ──(max(norm)<0.20 连续5次)──→ LOST ──(方向侧内传感器检测到黑线)──→ REENTER ──(中间传感器检测到黑线)──→ ONLINE
- 服务:Nordic UART Service (
6E400001-B5A3-F393-E0A9-E50E24DCCA9E) - 帧格式:
0x55 0xAA [Type] [Len] [Payload...] [Checksum] - 6 种帧类型:摇杆(0x01)、LED(0x02)、动作(0x03)、PID(0x04)、Work(0x05)、任务节点(0x06)
- 设备名:
EspCar-049
- 帧格式:
0xAA [Type] [Len] [Payload...] [CRC=XOR] - 8 种帧类型:握手(0x01/02)、里程计(0x05, 29B, 5Hz)、校准(0x08/09/0B)、数据控制(0x0A)、清零(0x0C)
- 参数:115200bps 8N1
- ESP32-V1 开发板 + L298N 驱动板 + 2× MG310 电机
- ESP32-S3-CAM 模组 + MPU6050 (I2C: SCL=21, SDA=47)
- 五路红外循迹传感器 (GPIO 27/33/32/35/34)
- 7.4V 2S LiPo 电池
使用 MicroPico (VS Code 插件) 上传固件:
- 将
espv3/src/目录同步到 ESP32-V1 - 将
esps3cam/src/目录同步到 ESP32-S3-CAM - 两块板上电后自动运行
# 安装依赖
pip install bleak pygame
# 启动 BLE 客户端 (交互模式)
python3 espv3/src/upper_example/ble_uart_client.py
# 启动 BLE 手柄模式
python3 espv3/src/upper_example/ble_uart_client.py --gamepad| 测试脚本 | 验证内容 |
|---|---|
test/motor_openloop_test.py |
PWM 占空比-转速映射、死区识别 |
test/encoder_raw_test.py |
编码器脉冲读取、正反转检测 |
test/encoder_odometry_test.py |
里程计累加精度 |
test/pcnt_test.py |
PCNT 硬件计数器 vs GPIO 中断对比 |
| 参数 | 值 | 说明 |
|---|---|---|
| 轮距 | 0.133 m | 左右轮中心距 |
| 车轮半径 | 0.024 m | 直径 4.8cm |
| 编码器 PPR | 500 | MG310 电机,4 倍频 → 2000 脉冲/转 |
| 最大线速度 | 0.87 m/s | 软件限幅 (70%) |
| 最大角速度 | 5.0 rad/s | |
| PID (循迹) | Kp=1.6, Ki=0, Kd=0.15 | |
| PID (电机闭环) | Kp=0.12, Ki=0.04, Kd=0.003 | |
| 循迹基础速度 | 0.28 m/s | 弯道自适应降至 0.16 m/s |
| 主循环周期 | 10 ms | |
| CAM 数据频率 | 5 Hz | 里程计推送 |
| 电机死区 | ~38% | 软件线性插值补偿 |
本项目仅用于教育目的。