板球控制系统调试过程及代码编写

问题

舵机的速度非常慢,而且只有 Kp的时候,

在这里插入图片描述
异常的振荡,首先板子两边加了围墙,这样掉不下去,所以球就在板子上来回满地图跑来跑去,不停地振荡。根本没有效果。加了D之后也特别抖,用手拨一下,拨得稍微大一点之后,就会反向运动好长,超调很大,没有挡板的话直就掉下去了,舵机反应很慢。静差也不小。

速度慢,有一个问题是每次计算出pid之后,舵机不是在平衡的位置加减的,而是在上一次的位置加减,这样速度会慢很多。(这里没有这么用,但是可以记录一下这个坑)
另外,之前的思路是

  • openmv程序设成20ms发送一次坐标,串口中断接收存到全局变量里。控制逻辑写在定时器2中断里,每40ms进一次,先接收数据,然后计算pid(是个角度),然后把这个角度给封装好的定时器的函数传进去计算出CCR值,对应占空比,给TIM3赋值。

首先,这里40ms有点长了,22ms可以
第二,直接用PWM就好了,换成角度,再换回来,其实是多次一举了。

下面针对两个问题具体解决

软件——舵机PID计算

初始思路(行不通)
/************************************
0.5ms-------2.5%---------0度;1000 ;
1ms ----------5%-------45度;2000 ;
1.5ms--------7.5%--------90度;3000 ;
2ms ----------10%-------135度;4000 ;
2.5ms --------12.5%-------180度;5000 ;
*************************************************/

封装好一个计算舵机角度的函数,直接给角度就好了。

#define Servo_Period 4000-1 //Servo_Duty*0.1
#define Servo_Static 1000-1 //*0.025


oid Servo_ANGLE_CH12(float angle1,float angle2)
{
	float temp1 = 0,temp2 = 0;
	angle1 = angle1 > 180 ? 180 : angle1; 
	angle2 = angle2 > 180 ? 180 : angle2; 
	temp1 = (angle1 / 180) * Servo_Period + Servo_Static;
	temp2 = (angle2 / 180) * Servo_Period + Servo_Static;
	__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, temp1);
	__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, temp2);

}
然后,进行PID计算

/**********************
首先openmv把绝对坐标传回来,放到Servo_pid.x_curr_posi中,
然后在xPID_Realize()函数中,Servo_pid.x_curr_posi减去绝对坐标Servo_pid.x_absolute_posi()
即可得到相对中心点的绝对坐标
*********************************/
float xPID_Realize(float target , float measure) //num为设定的目标点
{
	float pid_out;
	float error;
	static float error_last;
	float pteam,dteam;
	static float iteam;
	//计算相对坐标
	measure -= x_Servo_pid.absolute_posi;
	error = target - measure;
	pteam = x_Servo_pid.Kp*error;
	iteam += x_Servo_pid.Ki*error;
	dteam = x_Servo_pid.Kd*(error - error_last);	
	//积分限幅
	if(iteam > 30) iteam = 30;
	else if(iteam < -30) iteam = -30;
	pid_out = pteam + iteam + dteam;	
	//误差传递
	error_last = error;	
	return pid_out;
}

之后传值,

PID x_Servo_pid,y_Servo_pid;

float Position_x[9] = {-45,-45,-42,-1,0, 1, 46,49, 46};
float Position_y[9] = { 47, 0,-45,47,0,-46,47, 0,-46};
//控制函数
/************************
首先调用PID计算函数,求出有误差产生的PID的值pid_out
这是一个有正有负的值,pid_out加上balance就是现在需要的角度
那么,为了实现斜坡函数,即如果设定的值与当前的值的误差大于多少,误差就只认为有多少。

****************************/
void Servo_control(u8 x_i,u8 y_i)
{
	float temp[2];//用于斜坡函数、
	float step = 10.0;  //步长
	float x_pid,y_pid;
	temp[0] = x_Servo_pid.angle;
	temp[1] = y_Servo_pid.angle; //先获取当前的角度
	//获取增量
	x_pid = xPID_Realize(Position_x[x_i-1],x_Servo_pid.curr_posi);
	y_pid = yPID_Realize(Position_y[y_i-1],y_Servo_pid.curr_posi);
	//PIDOUT有正有负,加上板子平衡时的角度变成现在需要设定到的角度
	x_pid += x_Servo_pid.balance_angle;
	y_pid += y_Servo_pid.balance_angle;
	//斜坡函数
	    //设定与现在的角度的差值:这次需要设定到x_pid角度,而实际在x_Servo_pid.angle
	temp[0] = x_pid - x_Servo_pid.angle;
	temp[1] = y_pid - y_Servo_pid.angle;
	//   x的斜坡函数
	if(temp[0] > 0)
	{
		if(temp[0] > step) x_Servo_pid.angle += step;
		else 	x_Servo_pid.angle += temp[0];
	}
	else if(temp[0] < 0)
	{
		if(temp[0] < -step) x_Servo_pid.angle -= step ;
		else 	x_Servo_pid.angle += temp[0]; //这里注意,temp本身就是负的,所以用+,而step为正,所以用-
	}
	
	//   y的斜坡函数
	if(temp[1] > 0)
	{
		if(temp[1] > step) y_Servo_pid.angle += step;
		else 	y_Servo_pid.angle += temp[1];
	}
	else if(temp[1] < 0)
	{
		if(temp[1] < -step) y_Servo_pid.angle -= step ;
		else 	y_Servo_pid.angle += temp[1];
	}

	//输出限幅
	x_Servo_pid.angle = x_Servo_pid.angle > x_Servo_pid.max ? x_Servo_pid.max : x_Servo_pid.angle;
	x_Servo_pid.angle = x_Servo_pid.angle < x_Servo_pid.min ? x_Servo_pid.min : x_Servo_pid.angle;
	y_Servo_pid.angle = y_Servo_pid.angle > y_Servo_pid.max ? y_Servo_pid.max : y_Servo_pid.angle;
	y_Servo_pid.angle = y_Servo_pid.angle < y_Servo_pid.min ? y_Servo_pid.min : y_Servo_pid.angle;
}

在定时器中断中调用以上函数


/**
  * @brief  时间片任务调度函数
  * @param  void
  * @retval void
  * @attention 放入TIM2中使用,定时器中断优先级应高于其他中断,定时器时间应偏长
	OPENMV20ms发送一次,这里22ms进入一次中断
	*/
void Task_Dispatch_tim(void)
{
	system_tick++;
	System_GetValue();//获取openmv的坐标数据		
	//数据进行处理
	Servo_control(5,5);//计算PID并赋值	
	//设定值
	Servo_ANGLE_CH12(x_Servo_pid.angle,y_Servo_pid.angle);//给CCR赋值
	HAL_GPIO_TogglePin(FLAG_GPIO_GPIO_Port,FLAG_GPIO_Pin);//翻转IO口	
	ANO_DT_Data_Exchange();   //匿名上位机
	
}

思路改进

首先,把角度转换去掉,我只需要每次在知道平衡时的舵机角度对应的PWM基础上,把PID运算得出的值与其相加减即可。

舵机硬件问题

舵机供电——稳压电源5V

板球这个题的特点就是舵机是在快速动、停、动、停,所以舵机的瞬时电流比较大,最开始是用稳压电源接2596,12V降成5V,然后给32核心板和舵机供电,但是充电宝的电流都不够,2596更别说了。所以直接另开一路稳压电源5V供电

舵机信号PWM

但是对于舵机的控制信号,直接用32 的定时器PWM是可以的,3.3V和5V的影响不大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值