找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3891|回复: 0
收起左侧

STM32单片机板球系统设计与程序调试 2017国赛资料

[复制链接]
ID:342305 发表于 2019-1-5 15:37 | 显示全部楼层 |阅读模式
在大一参加了2017年的全国大学生电子设计大赛,并且拿到了省赛二等奖,虽然效果不是特别的完美,但是实现了全部的功能。
    因为每个点的位置差异,从点到点函数并不只有一种的情况啊
    其实总共只有三种点的存在啊
0.png
0.png

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);     //  一三目标   二四实
}

下面是主程序:
  1. /**
  2. **          2017全国大学生电子设计大赛
  3. **/

  4. //记得检查优先级啊,删减变量   到时候估计PID的选择也是一个问题啊
  5. /*
  6.                 比赛记录:
  7.                 整个题目全是在要求在X秒之内完成,要停留多少多少秒,可见时间到时候会成为一个很重要的判断标准
  8.                 而且可以看出     对小球的快速性要求非常高     谁快谁就是王
  9. */

  10. #include "sys.h"

  11. int main(void)
  12. {

  13.        
  14.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //设置系统中断优先级分组2       
  15.         NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(5, 0, 0));
  16.   All_init();

  17.                 while(1)
  18.                 {               
  19.                        
  20.                 }

  21. }
复制代码

全部资料51hei下载地址:
2017国赛----最后.7z (617.67 KB, 下载次数: 69)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表