在大一参加了2017年的全国大学生电子设计大赛,并且拿到了省赛二等奖,虽然效果不是特别的完美,但是实现了全部的功能。
因为每个点的位置差异,从点到点函数并不只有一种的情况啊
其实总共只有三种点的存在啊
2017年全国大学生电子设计大赛:
/*
1.不同于auto变量,被stati定义的变量的内存只分配一次的,因此在下次调用时仍然保持上次的值,这是一个很重要的功能,
而且也不用每次都开辟内存并写入相应的数据,为CPU减轻负担
2.此外,sttic关键字限制变量的作用域,只能被模块内所用函数访问,但不能被模块外其他函数访问
3.自动变量使用堆栈机制使用内存,而静态变量是分配固定的内存
4.register 请求将数据存到内部寄存器中,不用通过内存寻址来访问变量,提高访问效率
5.volatile 从他的内存中读取数据,而不使用寄存器缓存的值 即不使用寄存器优化
*/
/*typedef unsigned char uchar 对比着看这个你就应该懂啦吧 多多学习这些基础的东西 以后看别人的代码就不会太费事啦*/
// printf("count1=%d\r\n",usart2_dat);
u8 item3_flag=0;
u16 time_tingliu;
char cha_x,cha_y;
static uint32_t MoveTimeCnt = 0;
MoveTimeCnt += 5; //每5ms运算1次
if(item3_flag==0)
{
if( (target_BUF[6]<Position_BUF[6]) && (target_BUF[7]<Position_BUF[7]) )
{
target_BUF[6]=Position_BUF[0]+MoveTimeCnt*0.2; //这相当于是一个随动系统,但不知道那个效果好啊
target_BUF[7]=Position_BUF[1]+MoveTimeCnt*0.2; //到了调试时按照具体的现象定方案吧
}
PID_M1_SetPoint(target_BUF[6]); //X方向PID定位目标值0
PID_M1_SetKp(85);
PID_M1_SetKi(0);
PID_M1_SetKd(2000);
PID_M2_SetPoint(target_BUF[7]); //Y方向PID定位目标值0
PID_M2_SetKp(85);
PID_M2_SetKi(0);
PID_M2_SetKd(2000);
M1.PWM = PID_M1_PosLocCalc(Ball_x); // 电机一PWM计算
M2.PWM = PID_M2_PosLocCalc(Ball_y); // 电机二PWM计算 //但是暂时并没有使用积分分离,只有积分限幅最后加
if(M1.PWM > POWER1_MAX) M1.PWM = POWER1_MAX;
if(M1.PWM < POWER1_MIN) M1.PWM = POWER1_MIN;
if(M2.PWM > POWER2_MAX) M2.PWM = POWER2_MAX;
if(M2.PWM < POWER2_MIN) M2.PWM = POWER2_MIN;
MotorMove(M1.PWM,M2.PWM);
//这里计算的就是绝对的误差大小啦
cha_x=Position_BUF[6]-Ball_x;
cha_y=Position_BUF[7]-Ball_y;
if( (abs(cha_x)<4) && (abs(cha_y)<4) )
{
time_tingliu+=5;
if(time_tingliu==420)
{
item3_flag=1;
}
}
}
else //但是要求在P5停留至少两秒的程序并没有写,觉着并不需要 但是时间确实是需要特别注意的一个地方
{
if( (target_BUF[8]<Position_BUF[8]) && (target_BUF[9]<Position_BUF[9]) )
{
target_BUF[8]=Position_BUF[6]+MoveTimeCnt*0.2; //这相当于是一个随动系统,但不知道那个效果好啊
target_BUF[9]=Position_BUF[7]+MoveTimeCnt*0.2; //到了调试时按照具体的现象定方案吧
}
PID_M1_SetPoint(target_BUF[8]); //X方向PID定位目标值0
PID_M1_SetKp(85);
PID_M1_SetKi(0);
PID_M1_SetKd(2000);
PID_M2_SetPoint(target_BUF[9]); //Y方向PID定位目标值0
PID_M2_SetKp(85);
PID_M2_SetKi(0);
PID_M2_SetKd(2000);
M1.PWM = PID_M1_PosLocCalc(Ball_x); // 电机一PWM计算
M2.PWM = PID_M2_PosLocCalc(Ball_y); // 电机二PWM计算 //但是暂时并没有使用积分分离,只有积分限幅最后加
if(M1.PWM > POWER1_MAX) M1.PWM = POWER1_MAX;
if(M1.PWM < POWER1_MIN) M1.PWM = POWER1_MIN;
if(M2.PWM > POWER2_MAX) M2.PWM = POWER2_MAX;
if(M2.PWM < POWER2_MIN) M2.PWM = POWER2_MIN;
MotorMove(M1.PWM,M2.PWM);
}
}
/*------------------------------------------
函数功能:第4问PID计算
函数说明:电机M1控制X方向,电机M2控制Y轴方向
------------------------------------------*/
void item4()
{
u8 item4_flag=0;
u16 time_tingliu;
char cha_x,cha_y;
static uint32_t MoveTimeCnt = 0;
MoveTimeCnt += 5; //每5ms运算1次
if(item4_flag==0)
{
if( (target_BUF[8]<Position_BUF[8]) && (target_BUF[9]<Position_BUF[9]) )
{
target_BUF[8]=Position_BUF[0]+MoveTimeCnt*0.2; //这相当于是一个随动系统,但不知道那个效果好啊
target_BUF[9]=Position_BUF[1]+MoveTimeCnt*0.2; //到了调试时按照具体的现象定方案吧
}
PID_M1_SetPoint(target_BUF[8]); //X方向PID定位目标值0
PID_M1_SetKp(85);
PID_M1_SetKi(0);
PID_M1_SetKd(2000);
PID_M2_SetPoint(target_BUF[9]); //Y方向PID定位目标值0
PID_M2_SetKp(85);
PID_M2_SetKi(0);
PID_M2_SetKd(2000);
M1.PWM = PID_M1_PosLocCalc(Ball_x); // 电机一PWM计算
M2.PWM = PID_M2_PosLocCalc(Ball_y); // 电机二PWM计算 //但是暂时并没有使用积分分离,只有积分限幅最后加
if(M1.PWM > POWER1_MAX) M1.PWM = POWER1_MAX;
if(M1.PWM < POWER1_MIN) M1.PWM = POWER1_MIN;
if(M2.PWM > POWER2_MAX) M2.PWM = POWER2_MAX;
if(M2.PWM < POWER2_MIN) M2.PWM = POWER2_MIN;
MotorMove(M1.PWM,M2.PWM);
//这里计算的就是绝对的误差大小啦
//先确定我可以很好的到达区域5,然后再从区域5跑到区域9 在区域1到区域9的途径很多 我可以随意选择的啊
cha_x=Position_BUF[8]-Ball_x;
cha_y=Position_BUF[9]-Ball_y;
if( (abs(cha_x)<4) && (abs(cha_y)<4) )
{
time_tingliu+=5;
if(time_tingliu==100)
{
item4_flag=1;
}
}
}
else
{
if( (target_BUF[16]<Position_BUF[16]) && (target_BUF[17]<Position_BUF[17]) )
{
target_BUF[16]=Position_BUF[8]+MoveTimeCnt*0.2; //这相当于是一个随动系统,但不知道那个效果好啊
target_BUF[17]=Position_BUF[9]+MoveTimeCnt*0.2; //到了调试时按照具体的现象定方案吧
}
PID_M1_SetPoint(target_BUF[16]); //X方向PID定位目标值0
PID_M1_SetKp(85);
PID_M1_SetKi(0);
PID_M1_SetKd(2000);
PID_M2_SetPoint(target_BUF[17]); //Y方向PID定位目标值0
PID_M2_SetKp(85);
PID_M2_SetKi(0);
PID_M2_SetKd(2000);
M1.PWM = PID_M1_PosLocCalc(Ball_x); // 电机一PWM计算
M2.PWM = PID_M2_PosLocCalc(Ball_y); // 电机二PWM计算 //但是暂时并没有使用积分分离,只有积分限幅最后加
if(M1.PWM > POWER1_MAX) M1.PWM = POWER1_MAX;
if(M1.PWM < POWER1_MIN) M1.PWM = POWER1_MIN;
if(M2.PWM > POWER2_MAX) M2.PWM = POWER2_MAX;
if(M2.PWM < POWER2_MIN) M2.PWM = POWER2_MIN;
MotorMove(M1.PWM,M2.PWM);
}
5 上下限 0.8-1.2
1题
PID_M1_SetKp(0.07);
PID_M1_SetKi(0);
PID_M1_SetKd(0.8);
PID_M2_SetKp(0.07);
PID_M2_SetKi(0);
PID_M2_SetKd(0.8);
PID_M1_SetPoint(Position_BUF[8]); //X方向PID定位目标值0
PID_M1_SetKp(0.111);
PID_M1_SetKi(0.005);
PID_M1_SetKd(2);
PID_M2_SetPoint(Position_BUF[9]); //Y方向PID跟踪目标值sin
PID_M2_SetKp(0.111);
PID_M2_SetKi(0.005);
PID_M2_SetKd(2);
2题 PID_M1_SetPoint(Position_BUF[8]); //X方向PID定位目标值0
PID_M1_SetKp(0.22);
PID_M1_SetKi(0.02);
PID_M1_SetKd(1.8);
PID_M2_SetPoint(Position_BUF[9]); //Y方向PID跟踪目标值sin
PID_M2_SetKp(0.22);
PID_M2_SetKi(0.02);
PID_M2_SetKd(1.8);
void item7()
{
static u8 i;
const float priod =4000; //单摆周期(毫秒) 1851
static uint32_t MoveTimeCnt = 0;
float set_x = 0.0;
float set_y = 0.0;
float Normalization = 0.0;
float Omega = 0.0;
MoveTimeCnt += 100; //每100ms运算1次,来源于100ms的定时器函数
Normalization = (float)MoveTimeCnt / priod; //对单摆周期归一化
Omega = 2.0*3.1415926*Normalization; //对2π进行归一化处理
set_x = R*sin(Omega); //计算出X方向当前摆角
set_y = R*sin(Omega+((3.0*3.141592)/2.0)); //计算出Y方向当前摆角 3*PI/2 是顺时针转圈 用正弦余弦就不用这个关系啦
set_x=set_x*4+117;
set_y=set_y*4+116;
PID_M1_SetPoint(set_x); //X方向PID跟踪目标值sin
PID_M1_SetKp(0.21);
PID_M1_SetKi(0.02);
PID_M1_SetKd(2.01);
PID_M2_SetPoint(set_y); //Y方向PID跟踪目标值cos
PID_M2_SetKp(0.21);
PID_M2_SetKi(0.02);
PID_M2_SetKd(2.01);
M1.PWM = PID_M1_PosLocCalc(Ball_x); // 电机一PWM计算
M2.PWM = PID_M2_PosLocCalc(Ball_y); // 电机二PWM计算 //但是暂时并没有使用积分分离,只有积分限幅最后加
if(M1.PWM > POWER1_MAX) M1.PWM = POWER1_MAX;
if(M1.PWM < POWER1_MIN) M1.PWM = POWER1_MIN;
if(M2.PWM > POWER2_MAX) M2.PWM = POWER2_MAX;
if(M2.PWM < POWER2_MIN) M2.PWM = POWER2_MIN; //83 95 107
MotorMove(M1.PWM,M2.PWM);
//作为一个标志,指示系统的运行
i++;
if(i==10)
{
// printf("All is well!\r\n");
// printf("count1=%d\r\n",M1.PWM);
// printf("count2=%d\r\n",M2.PWM);
i=0;
}
send_data(&set_x,&set_y); // 一三目标 二四实
}
下面是主程序:
- /**
- ** 2017全国大学生电子设计大赛
- **/
- //记得检查优先级啊,删减变量 到时候估计PID的选择也是一个问题啊
- /*
- 比赛记录:
- 整个题目全是在要求在X秒之内完成,要停留多少多少秒,可见时间到时候会成为一个很重要的判断标准
- 而且可以看出 对小球的快速性要求非常高 谁快谁就是王
- */
- #include "sys.h"
- int main(void)
- {
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置系统中断优先级分组2
- NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(5, 0, 0));
- All_init();
- while(1)
- {
-
- }
- }
复制代码
全部资料51hei下载地址:
2017国赛----最后.7z
(617.67 KB, 下载次数: 69)
|