1. 低成本视觉追踪云台的设计初衷
作为一名热衷于嵌入式开发的电子爱好者,我一直在寻找能够将软件算法与硬件控制完美结合的项目。视觉追踪系统无疑是一个极具挑战性的选择,它不仅需要处理图像识别算法,还要实现精准的机械控制。市面上成熟的视觉云台产品价格昂贵,动辄上千元,这让我萌生了自己动手打造一个低成本解决方案的想法。
这个项目的核心目标很明确:用尽可能低的成本实现一个功能完整的视觉追踪系统。我给自己设定的预算是不超过50元,这相当于一顿火锅的钱。为了实现这个目标,我选择了最基础的硬件组件:STM32F103C8T6作为主控(俗称"蓝色药丸"),两个SG90舵机组成云台结构,电脑自带摄像头作为视觉传感器,再加上一个USB转TTL模块用于通信。
提示:SG90舵机虽然价格低廉(仅3元左右),但存在明显的机械虚位和死区问题,这为后续的控制算法设计带来了巨大挑战。
2. 硬件架构与选型解析
2.1 核心组件清单与功能
主控芯片:STM32F103C8T6
- 价格:约15元
- 优势:Cortex-M3内核,72MHz主频,足够处理PWM生成和串口通信
- 关键特性:内置定时器可产生精确的PWM波形控制舵机
执行机构:SG90舵机(180度版本)×2
- 价格:约3元/个
- 参数:工作电压4.8-6V,扭矩1.5kg·cm
- 限制:存在约5-10度的机械虚位,响应时间约0.12秒/60度
视觉传感器:笔记本电脑内置摄像头
- 分辨率:640×480(足够用于目标追踪)
- 帧率:30fps
- 优势:零成本,直接通过OpenCV调用
通信模块:CH340 USB转TTL
- 价格:约5元
- 通信速率:设置为115200bps
- 作用:建立PC与STM32之间的数据通道
2.2 机械结构搭建要点
云台的机械结构虽然简单,但有几个关键点需要注意:
-
舵机安装角度:两个舵机呈正交安装,一个控制水平(X轴)转动,一个控制垂直(Y轴)转动。确保两个舵机的旋转轴心尽可能重合,减少运动干涉。
-
负载平衡:激光头(或其他负载)应尽量靠近舵机转轴安装,避免产生过大惯性力矩导致舵机响应变慢。
-
结构刚性:使用3D打印件或亚克力板制作支架时,要确保连接部位牢固。我在初期使用热熔胶固定时发现,长时间运行后胶接处会出现松动,改用螺丝固定后稳定性明显提升。
-
供电设计:虽然SG90标称工作电压为4.8-6V,但实际测试发现,在5V供电时舵机力矩和速度表现最佳。建议使用独立的5V 2A电源为舵机供电,避免与主控芯片共用电源导致电压波动。
3. 软件系统架构设计
3.1 上位机(Python)处理流程
上位机程序采用Python编写,主要依赖OpenCV和pyserial库。处理流程如下:
- 图像采集与预处理
python复制import cv2
cap = cv2.VideoCapture(0) # 打开默认摄像头
ret, frame = cap.read()
if ret:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 转换到HSV色彩空间
blur = cv2.GaussianBlur(hsv, (11, 11), 0) # 高斯模糊降噪
- 目标检测与定位
python复制# 定义目标颜色范围(以橙色小球为例)
lower_orange = np.array([5, 100, 100])
upper_orange = np.array([15, 255, 255])
# 创建掩膜并寻找轮廓
mask = cv2.inRange(blur, lower_orange, upper_orange)
contours, _ = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if len(contours) > 0:
# 找到最大轮廓
c = max(contours, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(c)
# 计算目标中心与图像中心的偏差
error_x = x - frame.shape[1]/2
error_y = y - frame.shape[0]/2
- PID控制计算
python复制pid_x = PID(kp=0.5, ki=0, kd=0.2) # X轴PID控制器
pid_y = PID(kp=0.5, ki=0, kd=0.2) # Y轴PID控制器
output_x = pid_x.compute(error_x)
output_y = pid_y.compute(error_y)
- 串口数据发送
python复制import serial
ser = serial.Serial('COM3', 115200, timeout=1)
command = f"X{output_x:.1f},Y{output_y:.1f}\n" # 格式化指令
ser.write(command.encode())
3.2 下位机(STM32)处理流程
STM32端使用HAL库开发,主要完成以下任务:
- 串口数据接收与解析
c复制char buffer[32];
uint8_t idx = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if(buffer[idx-1] == '\n') { // 检测到完整指令
float x, y;
if(sscanf(buffer, "X%f,Y%f", &x, &y) == 2) {
set_servo_angle(SERVO_X, x);
set_servo_angle(SERVO_Y, y);
}
idx = 0; // 重置缓冲区
}
HAL_UART_Receive_IT(&huart1, &buffer[idx++], 1); // 继续接收
}
- PWM舵机控制
c复制void set_servo_angle(SERVO_Type servo, float angle) {
// 限制角度范围
angle = fmaxf(-90, fminf(90, angle));
// 转换为PWM脉宽(SG90: 0.5ms-2.5ms对应0-180度)
uint32_t pulse = (uint32_t)(500 + angle * 2000/180);
// 设置对应定时器的比较值
if(servo == SERVO_X) {
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse);
} else {
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, pulse);
}
}
4. 核心算法实现与优化
4.1 改进的PID控制算法
针对SG90舵机的特性,我对传统PID算法做了以下改进:
- 死区处理:当误差小于阈值时,直接输出0,避免舵机在目标位置附近微幅振荡。
python复制def compute(self, error):
# 死区处理
if abs(error) < self.dead_zone:
return 0
# 原有PID计算逻辑
...
- 输出限幅:限制最大输出幅度,防止舵机因过大指令而剧烈运动。
python复制output = max(-self.max_output, min(self.max_output, output))
- 微分项滤波:对微分项进行低通滤波,减少噪声带来的影响。
python复制# 使用一阶低通滤波平滑微分项
self.filtered_derivative = 0.3 * derivative + 0.7 * self.filtered_derivative
d_out = self.kd * self.filtered_derivative
4.2 视差补偿技术
由于摄像头与激光发射器存在物理距离(约5cm),会导致瞄准误差。我通过以下方法进行补偿:
-
标定过程:
- 在距离云台1米处放置标靶
- 移动目标到画面中心,记录激光实际落点
- 计算两者偏差作为补偿值
-
软件实现:
python复制# 视差补偿参数(需实际测量)
OFFSET_X = 15 # 像素
OFFSET_Y = -10 # 像素
# 应用补偿
error_x = x - (frame.shape[1]/2 + OFFSET_X)
error_y = y - (frame.shape[0]/2 + OFFSET_Y)
5. 系统调试与性能优化
5.1 关键参数整定步骤
-
比例系数(Kp)调试:
- 先将Ki和Kd设为0
- 逐渐增大Kp直到系统开始振荡
- 取振荡前值的50-60%作为最终Kp
-
微分系数(Kd)调试:
- 固定Kp
- 逐渐增加Kd直到抖动明显减少
- 注意过大的Kd会导致响应变慢
-
死区设置:
- 观察舵机的最小响应角度
- 设置死区略大于该值(通常30-50像素)
5.2 常见问题排查指南
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 目标识别不稳定 | HSV阈值设置不当 | 使用cv2.inRange()的滑动条动态调整阈值 |
| 舵机不响应 | 电源功率不足 | 使用独立5V 2A电源为舵机供电 |
| 串口数据丢失 | 波特率不匹配 | 确保PC和STM32使用相同波特率(115200) |
| 云台运动迟缓 | PID参数过小 | 逐步增大Kp提高响应速度 |
| 终点位置振荡 | 微分项不足或死区过小 | 增加Kd或扩大死区范围 |
6. 实际效果与改进方向
经过多次调试,这套低成本系统已经能够稳定追踪移动的橙色小球,在1米距离上的追踪误差小于3cm。虽然受限于SG90舵机的机械精度,无法达到工业级设备的性能,但作为学习项目和概念验证已经足够。
未来可能的改进方向包括:
- 使用步进电机替代舵机,提高控制精度
- 增加IMU传感器进行姿态补偿
- 移植算法到树莓派,实现独立运行
- 引入机器学习算法,实现多目标识别与跟踪
这个项目最宝贵的收获不是最终成品,而是在解决各种实际问题过程中积累的经验。从图像处理算法到硬件控制,从通信协议到机械结构,每个环节都充满了挑战和学习的乐趣。
