1. 项目概述
去年夏天,我在自家车库捣鼓出了一个能通过手机遥控的智能小车。这个看似简单的玩具项目,实际上涉及了嵌入式开发、无线通信、传感器融合等多个技术领域的知识整合。今天就来详细聊聊这个无线智能小车的软件架构设计和实现过程中的关键点。
这个小车的核心功能包括:通过WiFi或蓝牙实现手机遥控、自动避障、实时视频传输等。整套系统采用模块化设计,主控使用STM32系列单片机,搭配ESP8266 WiFi模块和HC-05蓝牙模块实现双模无线控制,通过超声波传感器和红外传感器实现环境感知。
2. 系统架构设计
2.1 硬件平台选型
主控芯片的选择是整个项目的基础。经过对比Arduino、Raspberry Pi和STM32三种方案后,我最终选择了STM32F103C8T6(俗称"蓝莓派")作为主控。这款芯片具有72MHz主频、64KB Flash和20KB RAM,性能足够应对实时控制需求,同时价格仅20元左右,性价比极高。
注意:STM32的开发环境配置比Arduino复杂,但提供了更精细的底层控制能力,适合需要精确时序控制的应用。
传感器方面,我使用了:
- HC-SR04超声波模块(测距精度2cm-400cm)
- TCRT5000红外反射传感器(用于边缘检测)
- MPU6050六轴加速度计/陀螺仪(用于姿态感知)
2.2 软件架构设计
整个软件系统采用分层架构设计:
code复制应用层:遥控指令处理、自动控制算法
中间层:传感器数据融合、电机控制
驱动层:外设驱动程序(PWM、UART、I2C等)
硬件抽象层:STM32 HAL库
这种分层设计使得各功能模块解耦,便于后期维护和功能扩展。例如,当需要更换无线模块时,只需修改中间层的通信协议解析部分,而不影响其他模块。
3. 核心功能实现
3.1 无线通信模块
无线通信采用双模设计,同时支持WiFi和蓝牙连接。ESP8266模块负责WiFi通信,通过AT指令与主控交互;HC-05模块实现蓝牙连接,使用串口透传模式。
通信协议设计为简单的文本格式,例如:
code复制"M1F100" 表示电机1正向100%速度
"SR" 请求传感器数据
这种设计虽然效率不高,但调试方便,适合原型开发阶段。在实际测试中,WiFi模式的延迟约50-100ms,蓝牙模式延迟约20-50ms。
3.2 电机控制算法
小车采用差速转向方式,通过两个直流电机分别控制左右轮。电机驱动使用L298N模块,PWM频率设置为10kHz。
速度控制算法采用PID调节:
c复制// 简化版PID实现
float PID_Control(float setpoint, float actual) {
static float integral = 0;
static float last_error = 0;
float error = setpoint - actual;
integral += error * dt;
float derivative = (error - last_error) / dt;
last_error = error;
return Kp*error + Ki*integral + Kd*derivative;
}
参数调优过程:
- 先调Kp使系统快速响应但不振荡
- 再调Kd抑制超调
- 最后调Ki消除稳态误差
3.3 自动避障功能
避障算法基于超声波和红外传感器的数据融合:
c复制#define SAFE_DISTANCE 20 // cm
void AvoidObstacle() {
float distance = GetUltrasonicDistance();
int edge_detected = GetInfraredStatus();
if (distance < SAFE_DISTANCE || edge_detected) {
StopMotors();
Backward(50); // 50%速度后退
Delay(500);
TurnRandomDirection(); // 随机转向
}
}
实际测试中发现,超声波在检测细小障碍物(如桌腿)时效果不佳,因此增加了红外传感器作为补充。两种传感器的数据融合显著提高了避障可靠性。
4. 手机端控制APP开发
4.1 Android控制界面
使用Android Studio开发简易控制APP,核心功能包括:
- 摇杆控制(通过Touch事件获取坐标)
- 速度调节滑块
- 传感器数据显示
- 摄像头画面显示(使用Mjpeg-streamer)
关键代码片段:
java复制// 摇杆控制处理
joystickView.setOnMoveListener((angle, strength) -> {
int speed = (int)(strength * maxSpeed);
int direction = (int)(angle / 45); // 8方向
String command = String.format("M%dD%d", direction, speed);
sendCommand(command);
});
4.2 视频传输方案
视频传输尝试了三种方案:
- RTSP流:延迟低但实现复杂
- MJPEG over HTTP:简单易实现,延迟约200ms
- WebRTC:效果最好但需要较多资源
最终选择了MJPEG方案,在STM32端使用OV7670摄像头模块,通过ESP8266的WiFi功能建立HTTP服务器。虽然画质一般(640x480@15fps),但完全满足实时监控需求。
5. 系统优化与调试
5.1 电源管理优化
初期使用普通18650电池,续航仅30分钟。通过以下措施提升至2小时:
- 增加电压监测,电量低时自动减速
- 优化电机PWM占空比,减少无效功耗
- 无线模块在不使用时进入睡眠模式
电源管理状态机设计:
c复制typedef enum {
POWER_FULL, // 全速运行
POWER_LOW, // 限速70%
POWER_CRITICAL // 停止运行
} PowerState;
void UpdatePowerState() {
float voltage = ReadBatteryVoltage();
if (voltage > 3.7) currentState = POWER_FULL;
else if (voltage > 3.3) currentState = POWER_LOW;
else currentState = POWER_CRITICAL;
}
5.2 无线通信稳定性提升
实测中发现WiFi在复杂环境中容易断连,通过以下改进:
- 增加心跳包机制(每500ms发送"PING")
- 实现自动重连功能
- 数据包增加校验和
- 重要指令采用应答机制
改进后的通信协议示例:
code复制[发送] CMD:M1F100
[回复] ACK:M1F100
6. 常见问题与解决方案
6.1 电机响应迟缓
可能原因及解决方法:
- PWM频率过低 → 提高到10-20kHz
- PID参数不合适 → 重新调参
- 电源电压不足 → 检查电池状态
6.2 无线控制延迟大
优化建议:
- 减少数据包大小
- 关闭不必要的传感器数据回传
- 尝试不同的无线信道
- 改用UDP协议替代TCP
6.3 视频卡顿
调试步骤:
- 检查WiFi信号强度(RSSI > -70dBm)
- 降低视频分辨率(如320x240)
- 减少帧率(如10fps)
- 确认ESP8266固件为最新版本
7. 项目扩展方向
在基础功能实现后,可以考虑以下扩展:
- 增加ROS支持,实现SLAM建图
- 改用ESP32替代STM32+ESP8266组合
- 添加机械臂实现抓取功能
- 开发Web控制界面
- 实现基于OpenCV的视觉跟踪
我在实际开发中发现,使用PlatformIO作为开发环境比传统的Keil或IAR更方便,特别是需要同时开发STM32和ESP8266固件时。PlatformIO的库管理功能和跨平台支持大大提高了开发效率。
