一阶旋转到倒立摆
手动起摆
自动起摆
摆杆的运动
电动机的控制
可以看到,题目中所要求完成的就是通过对一个电机的控制来实现的,控制题的核心还是要落在控制上。历届电子设计大赛经常被人戏称为电子机械设计大赛,虽然控制题的核心是落在控制上,但系统的机械结构也至关重要。此次练习采用的是平衡小车之家的套件,所以省去了搭硬件的很多麻烦。单单就完成题目要求的功能来说,数值分析并不是很必要(强迫症或者冲击国奖者除外)。因此,本篇内容仅仅从代码的角度来进行分析。
俗话说的好,不写注释的程序猿是流氓。我个人很喜欢在主函数的前面写上所用引脚的定义,这样一来方便接线,二来可以避免引脚重复使用,造成不必要的麻烦。
先来谈一谈我程序的风格,
一、
在主函数里我将初始化的函数写在了Board_Init();这个函数里,这样看起来比较方便后期的更改与检查,减少了主函数的代码量,使得主函数看起来简洁、调理。
void Board_Init(void)
{
delay_init();
Adc_Init();
KEY_Init();
Ecoder_TIM4_Init();
Motor_Init();
Timer_pwm_Init(999,8);
uart_init(115200);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}
二、我一般习惯于建立两个文件夹:HARDWARE、CONTROL。其中前者用来存放于硬件相关的一些配置函数,后者用来放与软件相关的一些配置函数。这样方便后期的维护与移植。
对于其中用到的基本配置,如ADC,ENCODER,MOTOR等等,此处不再赘述。网上有很多的例程与讲解。
该题的核心控制为电机,关键函数如下:
void Motor_Config(short pwm)
{
int speed;
if(start == 1)
{
if(pwm<0 && pwm > -PWM_MAX)
{
speed = PWM_MAX + pwm;
if(speed < 0)
{
speed = 0;
}
TIM_SetCompare2(TIM3,speed);
Motor_reverse();
}
else if(pwm > 0 && pwm < PWM_MAX)
{
speed = PWM_MAX - pwm;
if(speed > 400)
{
speed = 400;
}
TIM_SetCompare2(TIM3,speed);
Motor_Forward();
}
}
else
{
Motor_stop();
}
}
传入的参数为电机ENCODER,电位器ADC采集值后经过PID处理的数据,具体的处理函数如下:
short PID_Pos_PosCalc(short NextPoint)
{
register float iError,dError;
iError = pos_Set_Pos - NextPoint;
pos_SumError += iError*0.2;
if(pos_SumError > 1000.0)
pos_SumError = 1000.0;
if(pos_SumError < -1000.0)
pos_SumError = -1000.0;
dError = iError - pos_LastError;
pos_LastError = iError;
return(short)(pos_p * iError*0.8 + pos_i * pos_SumError + pos_d * dError);
}
short PID_Ang_PosCalc(short NextPoint)
{
register float iError,dError;
iError = ang_Set_Pos - NextPoint;
ang_SumError += iError;
if(ang_SumError > 1000.0)
ang_SumError = 1000.0;
if(ang_SumError < -1000.0)
ang_SumError = -1000.0;
dError = iError - ang_LastError;
ang_LastError = iError;
return(short)(ang_p * iError + ang_i * ang_SumError + ang_d * dError);
}
void Task3(void)
{
short temp,temp1,temp2;
temp = 0;
temp1 = ANG_MIN_VAL;
temp2 = ANG_MAX_VAL;
ang_Cur_Pos = Get_Adc_Average(ADC_Channel_1,15);
ang_Set_Pos = ANG_MID_VAL;
if((ang_Cur_Pos > temp1)&&(ang_Cur_Pos<temp2))
{
temp += PID_Ang_PosCalc(ang_Cur_Pos);
start = 1;
}
else
{
start = 0;
}
pos_Cur_Pos = PID_Pos_PosCalc(Encoder),Position_Target=0;
temp -= pos_Cur_Pos;
Motor_Config(temp);
printf("%d ",temp);
printf("%d\r\n",Encoder);
}
该题的控制采用了双环的PID来进行处理,在进行学习的过程中发现,仅仅采用电位器环的PID可以使得摆杆倒立起来,但整个摆杆会整体顺时针或者逆时针的旋转,并不能满足题目要求。正如前面所述,在考虑机械结构时,要整体考虑,否则当做到这里时,发现需要用双环来进行控制,再改机械结构,会浪费很多的时间。
这里附上源码 (链接: Mycode(双环控制)
今天的文章电赛练习之旋转倒立摆分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/8442.html