摘要:本文设计并实现了板球控制系统,通过OV7725摄像头模块作为图像识别传感器对图像进行处理,获取小球的位置坐标。采用STM32F103ZET6 单片机作为主控制器,根据图像信息通过PID 控制算法控制数字舵机,舵机带动曲柄摇杆机构驱动平板运动,以此调整小球在平板上的位置,实现小球在板上任意点的稳定,以及任意区域之间的转移。测试表明,本系统能完成红外控制小球运动,画线,控制小球走正方形,控制小球画圆。
关键词:滚球控制系统;OV2275摄像头;图像处理;PID算法
本系统主要由采集模块、处理模块、执行模块、电源模块组成,下面分别论证这几个模块的选择。
1、机械结构的论证与选择方案一:四边悬吊结构。采用四边悬吊结构,结构简单,但是不稳定,重心不固定,而重心的变化会影响平板的调整,从而影响数据处理周期,造成延时。。
方案二:正交摇臂支撑结构。中间采用万向节固定支杆,另外两边使用舵机固定,平板与舵机支杆之间通过万向节连接,三角形结构稳定,固定支杆使平板重心不偏移,控制更为简单。
综合以上二种方案,选择方案二。
2、控制系统的论证与选择方案一:STC89C51。采用STC89C51单片机做控制芯片,该系列单片机价格低廉,入门简单,实用范围广,资料丰富。但是是传统的8位单片机,处理速度不行。
方案二:MSP430。采用TI的MSP430系列单片机做主控制器,该系列单片机资源较丰富,易控制且低功耗。但是由于单片机自身主频较低,因而处理速度一般。
方案三:STM32F103。采用STM32F103系列单片机做主控芯片,该单片机控制较为复杂,且内部定时器,IIC,SPI等资源丰富,运算处理速度快,适合控制系统的实时控制。
综合以上三种方案,选择方案三。
3、电机的论证与选择方案一:直流电机。直流电机力量大,调速范围广,动态特性好,传递函数 较为简单,速度快。但只能对转速进行控制,可控性差,较难控制电机停止位置。
方案二:步进电机。步进电机可以实现开环控制,无需反馈信号,适合高精度的控制,使用短距离频繁动作较佳,但控制复杂,延迟值高,转速慢,扭矩小,且动态特性差,难以处理,不适合实时控制。
方案三:舵机。舵机具有较高的稳定性,控制简单,扭力大,成本低,且加速和减速时也更加迅速,柔和,可以提供更好的精度和更好的固定力量,且防抖动性能优越,响应速度快。但对相应的周期有要求,满足周期条件后,适合实时控制。
综合以上三种方案,选择方案三。
小球的检测是通过OV7725摄像头模块完成的,本系统设计采用颜色识别来检测小球,平板为黑色,使用白色小球提高对比度。STM32将摄像头采集回来的彩色图像做二值化处理,得到一个数组,然后通过搜索整个数组里面所有白色像素点的最大X、Y坐标与最小X、Y坐标,分别对应小球在图像中上下左右四个顶点,通过四个顶点取中值进行确定质心位置。也就是小球的位置坐标。
2、控制方法的分析
本系统通过控制舵机带动曲柄摇杆机构从而控制小球在平板上的运动,采用PID位置环控制舵机输出量使小球到达指定位置。采用PID速度环控制舵机输出量使小球速度为0。
位置环PID计算公式:
Error_Postion=X1-X0;
Error_Postion_last=Error_Postion;
PID_Postion=KP*Error_Postion+KD*(Error_Postion-Error_Postion_last);
速度环PID计算公式:
Error_V=(X1-X0)/T-0;
Error_V_last=Error_V;
PID_V=KP*Error_V+KD*(Error_V-Error_V_last);
舵机输出PWM计算公式:
PID_PWM=PID_Postion+PID_V;
Y轴的PID与舵机的输出计算与X轴类似。
本系统电路共分为四个部分:采集模块,主控制器模块,执行模块和电源模块,系统总体框图如图3.3.1所示。摄像头负责采集小球在平板上的位置,并将信息送回到STM32F103控制器;STM32F103经过PID运算输出PWM波控制舵机转角,以此控制小球在平板上的运动,从而形成一个闭合反馈回路,达到系统功能要求;电源模块为以上模块提供所需电源。
图3.1.1
(2)降压系统电路
图3.1.2
2、程序的设计(1)程序功能描述与设计思路1、程序功能描述
根据题目要求软件部分主要实现摄像头模块的采集处理,红外设置和显示功能。
1)摄像头图像的采集:使用OV7725摄像头处理图像信息,提取小球的坐标与运动信息。
2)红外控制的设置:使用红外控制模块,通过按键控制模式选择,基本实现要求。
3)显示部分:采用LCD实时显示小球的运动坐标与运动信息,方便观察与调试。
2、程序设计思路
(2)程序流程图1、主程序流程图
如图3.2.1所示为主程序流程图,当按下按键时,检测按键状态,实现对应功能要求,过程如下:摄像头检测小球运动的轨迹,处理后,输出PWM波,控制舵机转动角度,同时摄像头检测小球运动状态,判断是否达到指定区域。若没有,继续调整舵机,直至到达指定区域为止。
图3.2
2、小球运动检测程序流程图
小球检测的前提是获取平板的坐标系,每次系统上电时完成坐标系的标定,摄像头进行图像的获取,小球位置实时检测流程图如图3.2.2.2所示。
图3.2.2小球位置检测流程图
3、执行机构控制算法流程图
小球的目标位置与实际测得的位置有偏差,运用PID控制器计算舵机输出量,通过MG996R舵机和曲柄连杆结构带动平板,实现系统功能,控制算法如图3.2.2.3所示。
图3.2.3 PID位置控制算法
四、测试方案与测试结果1、测试方案
测量前,首先检测直流稳压电源和舵机是否工作正常,测量时,使用秒表测量小球运动时间和停留时间,观察实验结果。
2、测试条件与仪器测试条件:检查多次,仿真电路和硬件电路必须与系统原理图完全相同,并且检查无误,硬件电路保证无虚焊。
测试仪器:秒表,小球(直径小于2cm)。
3、测试结果及分析(1)测试结果(数据)1)基本要求
① 小球在区域2内停留不少于5s。
测试方法:将球丢到平板上,记录小球在区域2停留的时间。
测试结果:小球可以实现在区域2稳定5s以上。
② 控制小球在15s内从区域1运动到区域5,且在区域5停留2s以上。
测试方法:手动将小球放置在区域1内,启动1-5模式,并开始计时,记
录小球从区域1到区域5所用时间以及在区域5停留的时间。
测试结果:小球可以完成从区域1到区域5,并且在区域5停留时间在2s以上,未进入其他区域。
③ 控制小球在20s内完成从区域1到区域4,在区域4停留2s以上,之后
进入区域5,在区域5停留2s以上。
测试方法:手动将小球放置在区域1内,启动1-4-5模式,并开始计时,记录小球完成两个动作的总时间以及在区域4和区域5停留的时间。
测试结果:小球可以完成从区域1到区域4再到区域5,并且在区域4,区域5停留时间均达到2s以上。
④控制小球在30s内从区域1运动到区域9,且在区域9停留2s以上。
测试方法:手动将小球放置在区域1内,启动1-9模式,并开始计时,记录小球完成运动的总时时间以及在区域9停留的时间。
测试结果:小球通过设置的中转点(在区域1到区域9路径上设置),可以完成题目要求,且在区域9停留时间2s以上。
2) 发挥部分
① 控制小球在40s内,从区域1先后经过区域2和区域6停在区域9,在区域9停留2s以上。
测试方法:手动将小球放置在区域1,启动1-2-6-9模式,并开始计时,记录小球运动的总时间以及在区域9停留的时间。
测试结果:小球可以完成题目要求,且在区域9停留时间2s以上。
③ 通过控制使得小球从区域4出发,绕区域5(不进入)做不少于3周运动后在区域9停留2s以上。
测试方法:手动将小球放置在区域4,启动绕区域5做环绕运动的模式,
观察小球的运动轨迹,记录小球在区域9停留时间。
测试结果:小球在区域4出发,围绕区域5做正方形路径,完成题目要求,且最后在区域9停留时间达2s以上。
(2)测试分析与结论根据上述测试数据,本系统能充分完成指标要求,响应速度快,可以实现小球在指定位置的稳定,能够按照指定的要求在平板上完成指定动作,测试中发现系统在平衡位置附近出现小幅度的抖动,分析原因是由于小球位置识别的微小偏差,解决方案是采用更精准的图像识别算法从而达到减小抖动的目的。还有机械结构搭建得不是特别好,导致平板在水平方向有稍微的偏移。
综上所述,本设计达到设计要求。
五、结论与心得经过这次制作,我们在设计硬件和搭建机械结构有了更大的全局观,提升了小组三人的合作能力,我们在面对系统共地问题,电路故障分析的运用也能通过设计电路来检测。同时我们更加了解了基本图像处理方法,对PID算法运用更熟练,为我们之后的制作过程做了很好的铺垫。
六:部分程序
int main(void)
{
u8 msgbuf[15];//消息缓存区
u8 tm=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组
uart_init(115200); //串口初始化为115200
uart3_init(9600); //蓝牙模块波特率初始化-9600
usmart_dev.init(72);//初始化USMART
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init();//初始化按键
LCD_Init(); //初始化LCD
TPAD_Init(6);//触摸按键初始化
POINT_COLOR=RED;//设置字体为红色
TIM2_Init(); //定时器2进行5ms中断
PWM_1_Init(); //舵机pwm输出TIM3
Remote_Init();//红外模块初始化--需要添加开启
//OV7725初始化
if(OV7725_Init()==0)
{
OV7725_Window_Set(240,240,0);//设置宽度与高度,QVGA模式输出
OV7725_CS=0; //关闭位选
}
EXTI8_Init();//使能外部中断8,捕获帧中断
LCD_ShowString(135,282,297,12,12,"KD_X:");
T_X=0;
T_Y=0;
while(1)
{
OV7725_camera_refresh();//更新显示,进行寻点寻点操作
remote_key(); //红外键值获取,模式切换
LCD_Show(); //lcd显示函数
}
}
Pid算法程序:
V_X = (X_white-Error_X_Last)/T;
V_Y = (Y_white-Error_Y_Last/T;
Set_point(); //红外控制函数
//===计算坐标偏差值===////===计算速度偏差值===//
Error_X=X_white-T_X;Error_V_X=V_X;
Error_Y=Y_white-T_Y;Error_V_Y=V_Y;
//=位置计算微分偏差值=////=速度计算微分偏差值=//
Bais_X=Error_X-Error_X_Last; Bais_V_X=Error_V_X-Error_V_X_Last;
Bais_Y=Error_Y-Error_Y_Last; Bais_V_Y=Error_V_Y-Error_V_Y_Last;
//======计算相对偏离位置用于计算速度======//
if(Bais_X!=0||Bais_Y!=0)
{
D_Bais_X=Bais_X;
D_Bais_Y=Bais_Y;
}
//============PID计算位置环PWM============//
//计算位置环PWM
PWM_X_P=(KP_X*Error_X + KD_X*D_Bais_X);
PWM_Y_P=(KP_Y*Error_Y + KD_Y*D_Bais_Y);
//============PID计算速度环PWM============//
PWM_V_X_P=(KP_V_X*Error_V_X + KD_V_X*Bais_V_X); PWM_V_Y_P=(KP_V_Y*Error_V_Y + KD_V_Y*Bais_V_Y);
//=============计算总输出PWM==============//
PWM_X=PWM_X_P+zhongzhi_X+PWM_V_X_P;
PWM_Y=PWM_Y_P+zhongzhi_Y+PWM_V_Y_P;
//================PWM限幅=================//
if(PWM_X>1850) PWM_X=1850;
if(PWM_X<1200) PWM_X=1200;//X轴限幅1157+-200
if(PWM_Y>1550) PWM_Y=1500;
if(PWM_Y<850) PWM_Y=850;//Y轴限幅1405+-200
//=========保存(坐标,速度)偏差=========//
Error_X_Last=Error_X;
Error_Y_Last=Error_Y;
图像处理函数:
for(i=0;i
{
// length_white=0;//换行清零 方案B启用
for(j=0;j
{
OV7725_RCK_L;
color=GPIOC->IDR&0XFF;//读数据
OV7725_RCK_H;
color<<=8;
OV7725_RCK_L;
color|=GPIOC->IDR&0XFF;//读数据
OV7725_RCK_H;
LCD->LCD_RAM= color;//显示rgb像素点
//获取RGB图像并对其计算
gm_red = color>>11;
gm_green = (color&0x07E0)>>5;
gm_blue = color&0x001F;
gray=(gm_red*19595 + gm_green*38469 +gm_blue *7472) >> 16;
if(gray>42) //白色处理
{
//LCD->LCD_RAM= WHITE;
if(((i>15&&i<220)&&(j>15&&j<220))) //过滤掉周围环境的噪点,
{
total_white++;
x_total_white +=i;
y_total_white +=j;
}
}
m=(x_total_white)/(total_white);
n=(y_total_white)/(total_white);//计算坐标
if(m>0&&n>0)//滤除0.0这个点
{
X_white=m;
Y_white=n;
if(total_white>20)//只标记最大的白色球体
{
devieat = (u8)(sqrt(total_white/3.14));//根据面积求出白球半径
}
LCD_Draw_Circle(Y_white,X_white,devieat);//在lcd上画圆标记
LCD_Draw_Circle(Y_white,X_white,devieat+1);//在lcd上画圆标记