ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从PID控制到视觉反馈:滚球平衡系统设计与电赛实战

从PID控制到视觉反馈:滚球平衡系统设计与电赛实战 大家好我是专注于嵌入式系统与自动控制技术分享的博主。在准备电子设计类竞赛或课程设计时一个经典且富有挑战性的题目就是“滚球控制系统”。它综合了传感器技术、电机控制、PID算法和系统集成等多个核心知识点是检验学生工程实践能力的绝佳项目。本文将以2017年全国大学生电子设计竞赛B题“滚球控制系统”为蓝本系统性地拆解其设计思路、硬件选型、软件实现与调试技巧。无论你是正在备赛的学生还是对自动控制感兴趣的开发者都能从零开始跟随本文搭建一套完整的滚球平衡控制系统。1. 系统概述与核心需求分析1.1 项目背景与题目解析全国大学生电子设计竞赛是面向大学生的国家级权威赛事其题目往往紧扣前沿技术并强调工程实现。2017年B题“滚球控制系统”要求设计一个能够控制小球在平板上运动的装置。平板通过两个正交安装的舵机或步进电机控制其倾角从而利用重力使小球在二维平面内滚动。系统需能引导小球完成指定轨迹运动如直线、圆形并最终稳定在预设的目标位置。这个题目的核心在于将一个二维平面倒立摆问题球是摆锤平板是支撑面转化为一个双输入X轴倾角、Y轴倾角双输出球在平面的X坐标、Y坐标的实时闭环控制系统。它完美融合了自动控制原理、嵌入式系统开发和机器视觉/传感器融合等关键技术。1.2 系统核心功能需求根据题目要求系统通常需要实现以下基本和发挥功能基本功能手动控制通过键盘、按键或手机APP等方式能够手动控制小球在平板上任意移动。自动归位无论小球初始在何处系统能自动控制小球回到平板中心原点。轨迹跟踪控制小球沿指定轨迹运动如直线、圆、矩形等。发挥功能快速定位要求小球从任意点运动到指定点的时间尽可能短超调小。抗干扰能力在平板上施加轻微扰动如轻吹或轻触小球后系统能快速恢复稳定。路径规划自动避开平板上的障碍物如果题目设置。控制精度稳态误差小定位精准。1.3 系统总体架构一个典型的滚球控制系统由以下几个部分组成被控对象小球和平板。执行机构两个分别控制平板X轴和Y轴倾斜的电机常用舵机或步进电机。传感器单元用于检测小球在平板上实时位置的装置。常见方案有摄像头OpenMV/OpenCV上方架设摄像头通过图像处理识别小球位置。激光测距阵列在平板四周安装多对激光发射与接收管通过遮挡判定位置。电阻/电容触摸膜特制的触摸屏平板直接读取坐标成本高少见。控制器核心处理单元如STM32、ESP32、树莓派等微控制器或微处理器。负责读取传感器数据、运行控制算法、生成电机控制信号。人机交互按键、显示屏、蓝牙/WIFI模块等用于设定模式、输入目标、显示状态。2. 硬件系统设计与选型2.1 核心控制器选型控制器的选择需平衡算力、外设和开发难度。STM32F4系列推荐性价比高具有FPU浮点运算单元能流畅运行浮点型PID计算。拥有丰富的定时器用于产生PWM控制舵机以及UART、I2C、SPI等接口连接传感器。是电赛中的主流选择。ESP32系列集成Wi-Fi和蓝牙便于实现无线控制和数据传输到上位机进行调试。双核处理器性能强劲但实时性需精心设计任务优先级。树莓派Raspberry Pi算力强大可直接运行完整的Linux系统和OpenCV实现复杂的图像处理算法。但实时性不如单片机且系统复杂度高功耗大。建议对于初次接触或追求稳定性的队伍STM32F407或F429是稳妥且强大的选择。2.2 执行机构——电机选型与驱动电机的选择直接决定系统的响应速度和带载能力。舵机Servo Motor优点控制简单只需PWM信号即可指定角度内部自带闭环控制。扭矩大定位精度尚可。缺点响应速度有上限一般0.1s/60°且存在死区。角度范围通常为180°或270°可能限制平板倾角。选型建议选择数字舵机响应更快。扭矩建议在15kg·cm以上以确保能平稳驱动平板。需注意供电电流通常需要独立电源。步进电机Stepper Motor优点可精确控制旋转角度和速度无累积误差。配合丝杠或连杆可以将旋转运动转化为精确的直线倾斜。缺点需要专门的驱动器如A4988、TMC2208控制逻辑比舵机复杂。低速可能振动高速可能丢步。驱动必须使用步进电机驱动模块控制器通过脉冲PUL和方向DIR信号进行控制。建议多数成功方案采用大扭矩数字舵机因其易用性高足以满足题目要求。若追求极高精度和响应可考虑步进电机闭环系统。2.3 传感器——小球位置检测方案详解这是系统的“眼睛”是关键难点之一。方案一摄像头视觉方案主流且推荐硬件OpenMV Cam H7、树莓派摄像头、普通USB摄像头。原理摄像头垂直安装在平板上方拍摄整个平板画面。通过图像处理颜色阈值、轮廓查找、圆心拟合识别小球的像素坐标再通过校准将其转换为实际物理坐标。优点非接触式精度高可获取丰富信息颜色、形状易于调试能看到画面。缺点受光照影响大计算开销大在MCU上运行需优化。OpenMV示例代码颜色追踪# OpenMV IDE 中的简单示例 import sensor, image, time, math # 初始化摄像头 sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) # 320x240 sensor.skip_frames(time 2000) sensor.set_auto_gain(False) # 必须关闭自动增益 sensor.set_auto_whitebal(False) # 必须关闭白平衡 # 定义小球的颜色阈值 (LAB色彩空间) red_threshold (30, 65, 25, 75, 10, 60) # 示例需根据实际小球颜色调整 while(True): img sensor.snapshot() # 寻找色块 blobs img.find_blobs([red_threshold], pixels_threshold100, area_threshold100, mergeTrue) if blobs: # 找到最大的色块 largest_blob max(blobs, keylambda b: b.pixels()) # 在图像上画框和十字 img.draw_rectangle(largest_blob.rect()) img.draw_cross(largest_blob.cx(), largest_blob.cy()) # 计算实际坐标 (需要标定) # ball_x, ball_y convert_pixel_to_mm(largest_blob.cx(), largest_blob.cy()) print(Ball at pixel: ({}, {}).format(largest_blob.cx(), largest_blob.cy()))与STM32通信OpenMV通过串口将坐标(cx, cy)发送给STM32。方案二激光对管扫描方案硬件多对红外/激光发射管和接收管安装在平板相邻两边。原理小球滚过时会遮挡特定的发射-接收光路。通过快速扫描所有对管可以判断小球在X和Y方向上的遮挡位置进而解算出坐标。优点不受光照影响响应速度极快成本较低。缺点精度受对管密度限制安装调试复杂容易受环境光干扰需调制解调。2.4 机械结构设计要点平板要求轻质、平整、有一定刚度。常用亚克力板、碳纤维板或轻木板。表面可贴白色哑光纸以减少反光便于视觉识别。支架需要稳固的支架来固定摄像头和电机。确保摄像头光轴与平板垂直减少图像畸变。传动机构若使用舵机通常通过舵盘和连杆直接推动平板边缘形成“跷跷板”结构。两个舵机正交安装分别控制X和Y方向的倾斜。务必保证运动顺滑无卡滞。3. 控制系统建模与算法设计3.1 系统简化模型我们可以将系统在平衡点平板水平小球在中心附近进行线性化分析。假设平板倾角很小小球滚动无滑动忽略摩擦。 对于X轴方向动力学方程可简化为a_x g * θ_x其中a_x是小球在X方向的加速度。g是重力加速度。θ_x是平板绕Y轴的旋转角度即X方向的倾角。这是一个典型的二阶积分环节。Y轴方向同理。因此整个系统可以看作是两个独立的、由角度控制加速度的通道。3.2 核心控制算法——PID控制器PID是此类系统最经典有效的控制算法。我们需要为X和Y方向分别设计一个PID控制器。位置式PIDu(k) Kp * e(k) Ki * ∑e(j) Kd * [e(k) - e(k-1)]其中u(k)是输出通常是目标角度或PWM占空比e(k)是当前误差目标位置 - 当前位置。增量式PIDΔu(k) Kp*[e(k)-e(k-1)] Ki*e(k) Kd*[e(k)-2e(k-1)e(k-2)]u(k) u(k-1) Δu(k)增量式更适用于执行机构带积分性质的场合如步进电机且不易积分饱和。PID参数整定步骤手动“试凑法”置零先将Ki和Kd设为0。调Kp逐渐增大Kp直到小球能响应控制但开始围绕目标点持续振荡。记下此时Kp值为Ku振荡周期为Tu。调Kd加入Kd以抑制振荡。Kd有助于增加系统阻尼使小球平稳接近目标。根据齐格勒-尼科尔斯法则可初设Kp 0.6*Ku, Ki 2*Kp/Tu, Kd Kp*Tu/8然后微调。调Ki最后加入Ki以消除静态误差。Ki值不宜过大否则会引起系统超调或振荡。3.3 进阶算法串级PID与模糊PID串级PID外环是位置环输入是位置误差输出是期望速度内环是速度环通过位置差分估算速度输出是平板倾角。这种结构能更好地处理系统的非线性控制效果更平滑。模糊PID针对系统在不同区域如误差大时和误差小时特性不同可以设计模糊规则在线调整PID参数适应性强但设计复杂。C语言 PID 结构体与实现示例位置式// pid.h typedef struct { float Kp, Ki, Kd; // PID系数 float integral; // 积分项 float prev_error; // 上一次误差 float output_max; // 输出限幅 float output_min; float integral_max; // 积分限幅 } PID_Controller; void PID_Init(PID_Controller *pid, float kp, float ki, float kd, float out_max, float out_min); float PID_Update(PID_Controller *pid, float setpoint, float measurement, float dt); // pid.c #include pid.h void PID_Init(PID_Controller *pid, float kp, float ki, float kd, float out_max, float out_min) { pid-Kp kp; pid-Ki ki; pid-Kd kd; pid-integral 0.0f; pid-prev_error 0.0f; pid-output_max out_max; pid-output_min out_min; pid-integral_max out_max * 0.5f; // 积分限幅通常为输出限幅的一半 } float PID_Update(PID_Controller *pid, float setpoint, float measurement, float dt) { float error setpoint - measurement; // 比例项 float proportional pid-Kp * error; // 积分项抗饱和 pid-integral error * dt; if (pid-integral pid-integral_max) pid-integral pid-integral_max; else if (pid-integral -pid-integral_max) pid-integral -pid-integral_max; float integral pid-Ki * pid-integral; // 微分项用误差的微分对测量值微分更抗噪 float derivative pid-Kd * (error - pid-prev_error) / dt; pid-prev_error error; // 计算总输出并限幅 float output proportional integral derivative; if (output pid-output_max) output pid-output_max; else if (output pid-output_min) output pid-output_min; return output; }4. 软件系统设计与代码实现4.1 系统软件架构采用前后台或实时操作系统如FreeRTOS架构。主要任务包括传感器数据采集任务定时读取摄像头坐标或扫描对管。控制算法任务以固定周期如10ms运行PID计算。执行器输出任务根据PID输出更新PWM占空比控制电机。通信与调试任务处理串口命令向上位机发送数据。人机交互任务扫描按键更新显示屏。4.2 STM32主程序流程示例// main.c 核心逻辑框架 #include stm32f4xx_hal.h #include pid.h #include servo.h #include vision.h // 或 sensor.h #include uart_debug.h PID_Controller pid_x, pid_y; float ball_x_mm, ball_y_mm; // 小球当前坐标毫米 float target_x_mm 0.0f, target_y_mm 0.0f; // 目标坐标 float output_angle_x, output_angle_y; // 输出角度 int main(void) { HAL_Init(); SystemClock_Config(); UART_Init(); // 初始化调试串口 Vision_Sensor_Init(); // 初始化视觉传感器 Servo_Init(); // 初始化舵机PWM PID_Init(pid_x, 1.5f, 0.05f, 0.8f, 10.0f, -10.0f); // 角度限幅±10° PID_Init(pid_y, 1.5f, 0.05f, 0.8f, 10.0f, -10.0f); // 系统校准获取平板中心像素坐标、比例系数等 System_Calibration(); while (1) { // 1. 获取小球位置假设此函数非阻塞快速返回 if(Vision_GetBallPosition(ball_x_mm, ball_y_mm)) { // 2. 运行PID控制器 (控制周期假设为10ms) output_angle_x PID_Update(pid_x, target_x_mm, ball_x_mm, 0.01f); output_angle_y PID_Update(pid_y, target_y_mm, ball_y_mm, 0.01f); // 3. 将角度转换为舵机PWM并输出 Servo_SetAngleX(output_angle_x); Servo_SetAngleY(output_angle_y); // 4. 调试输出可通过串口绘图软件观察 UART_SendDebugData(ball_x_mm, ball_y_mm, output_angle_x, output_angle_y); } // 5. 处理模式切换、目标点设置等放在另一个低优先级任务或中断中 Handle_User_Input(); HAL_Delay(10); // 简单延时实际应用建议用定时器中断 } }4.3 关键模块驱动示例舵机控制// servo.c #include servo.h #include tim.h // STM32 HAL 定时器头文件 // 假设使用TIM1 CH1和CH2产生PWM舵机中值对应1.5ms脉冲周期20ms #define SERVO_MID_PULSE_MS 1.5f #define PWM_PERIOD_MS 20.0f #define PWM_CLOCK_FREQ 1000000.0f // 定时器时钟1MHz每微秒一个计数 uint32_t mid_count_x, mid_count_y; uint32_t angle_to_count_ratio; // 每度对应的计数值变化量 void Servo_Init(void) { // 初始化定时器和PWM通道... HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_2); // 计算中位值计数值 (1.5ms / (1/1MHz) 1500 counts) mid_count_x mid_count_y (uint32_t)(SERVO_MID_PULSE_MS * 1000); // 微秒数 // 假设舵机转动范围 ±60° 对应脉冲变化 ±0.5ms angle_to_count_ratio (uint32_t)(500.0f / 60.0f); // 每度约8.33个计数值 } void Servo_SetAngleX(float angle_deg) { // 限制角度范围 if(angle_deg 60.0f) angle_deg 60.0f; if(angle_deg -60.0f) angle_deg -60.0f; // 计算PWM比较值 uint32_t pulse_count mid_count_x (int32_t)(angle_deg * angle_to_count_ratio); __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, pulse_count); } void Servo_SetAngleY(float angle_deg) { // 同理 if(angle_deg 60.0f) angle_deg 60.0f; if(angle_deg -60.0f) angle_deg -60.0f; uint32_t pulse_count mid_count_y (int32_t)(angle_deg * angle_to_count_ratio); __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_2, pulse_count); }5. 系统调试与性能优化5.1 调试方法与工具串口打印调试将小球坐标、目标坐标、PID输出、误差等关键变量通过串口发送到电脑使用串口助手或SerialPlot、MATLAB等工具绘图直观分析系统响应。上位机软件可以开发简单的上位机如C#、Python PyQt实时显示小球位置、轨迹、并支持在线修改PID参数。离线数据分析将系统运行数据记录到SD卡事后用MATLAB/Python分析指导参数调整。分模块测试先测试舵机给定固定PWM看平板倾角是否符合预期。再测试视觉单独运行摄像头程序看能否稳定输出坐标。最后闭环先用手动模式如键盘控制角度感受小球运动特性再接入PID闭环。5.2 常见问题与解决方案问题现象可能原因排查与解决思路小球完全不动或乱动1. 传感器数据错误或未更新。2. PID输出极性反了。3. 电机接线或供电问题。1. 检查传感器数据是否正常、稳定。2. 尝试将PID输出取反或交换电机接线。3. 用万用表测量电机供电电压和PWM信号。小球振荡严重1. PID参数不合适比例或微分过大。2. 传感器数据噪声大或延迟大。3. 机械结构松动有回程间隙。1. 大幅降低Kp和Kd尤其是Kd。2. 对传感器数据做低通滤波如一阶滞后滤波。3. 紧固机械连接消除间隙。小球响应慢到达目标时间长1. PID参数过小尤其是Kp。2. 电机扭矩不足或速度慢。3. 平板摩擦力过大。1. 适当增大Kp可轻微增大Ki。2. 更换更大扭矩舵机确保供电充足。3. 清洁平板或使用更光滑的小球如轴承钢球。稳态时有固定偏差积分项Ki太小或积分饱和。适当增大Ki并检查是否设置了合理的积分限幅。视觉识别坐标跳动1. 光照变化。2. 阈值设置不合理。3. 图像中存在类似颜色的干扰物。1. 增加遮光罩使用均匀光源。2. 在OpenMV IDE中实时调整LAB阈值。3. 优化算法如用面积、圆度过滤或改用红色激光笔照小球形成高亮斑点。5.3 性能优化技巧传感器滤波对读取的坐标进行软件滤波如滑动平均滤波、卡尔曼滤波能有效平滑数据减少突变。#define FILTER_LEN 5 float filter_buffer_x[FILTER_LEN] {0}; float filter_buffer_y[FILTER_LEN] {0}; int filter_index 0; void LowPassFilter(float new_x, float new_y, float *out_x, float *out_y) { filter_buffer_x[filter_index] new_x; filter_buffer_y[filter_index] new_y; filter_index (filter_index 1) % FILTER_LEN; *out_x 0; *out_y 0; for(int i0; iFILTER_LEN; i) { *out_x filter_buffer_x[i]; *out_y filter_buffer_y[i]; } *out_x / FILTER_LEN; *out_y / FILTER_LEN; }控制周期确保控制周期固定且合适。太快可能计算不过来或受噪声影响大太慢则系统响应迟缓。10-20ms是一个常用范围。非线性补偿在平板边缘小球重力分力与倾角的正弦关系更明显可考虑根据小球位置对PID输出进行非线性补偿如乘以一个系数。轨迹规划对于轨迹跟踪不要直接给一系列离散点。应对目标轨迹进行插值如线性插值、样条插值并计算目标速度作为串级PID的输入使运动更平滑。6. 工程实践与扩展思路6.1 从原型到稳定作品电源管理舵机、控制器、摄像头分开供电避免大电流负载导致控制器复位。使用大容量电容稳压。结构稳固性所有连接处使用螺丝、螺母加固避免使用胶水。确保平板在运动时不会扭曲变形。代码健壮性添加超时判断、数据有效性校验、软件看门狗防止程序跑飞。标定流程上电后应有标定程序例如让用户将小球依次放在几个已知位置自动计算像素到毫米的转换矩阵和畸变系数。6.2 功能扩展与创新点无线控制与监控利用ESP32的Wi-Fi创建Web服务器通过网页实时观看小球视频流并控制目标点。人工智能应用使用神经网络如TinyML替代PID控制器或用于视觉识别中的小球特征提取。多球控制升级视觉算法同时识别并控制多个小球实现更复杂的编队或游戏。加入扰动观测器设计扰动观测器来估计并补偿平板摩擦、风扰等外部干扰提升鲁棒性。6.3 备赛与报告撰写建议分工明确硬件、软件、算法、报告各司其职但需紧密协作。迭代开发先实现基本功能再优化性能最后增加发挥部分。每步都做好测试记录。数据说话在报告中使用图表展示系统性能如阶跃响应曲线、轨迹跟踪误差图、抗干扰恢复时间等。突出亮点在报告中清晰阐述你的创新点无论是算法优化、机械设计还是调试方法。滚球控制系统是一个麻雀虽小五脏俱全的典型嵌入式控制系统项目。从需求分析、硬件选型、建模算法到软硬件联调完整走一遍这个流程对理解自动控制理论、提升嵌入式开发能力有极大的帮助。希望这篇详细的教程能为你提供清晰的路径和实用的代码参考。在实际动手过程中遇到问题多查资料、多思考、多调试积累的经验才是最宝贵的财富。
返回列表