找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2891|回复: 1
收起左侧

2013年电赛倒立摆 STM32代码 高精度金属电位器 速度环+位置环PID控制

[复制链接]
ID:293035 发表于 2020-3-25 09:35 | 显示全部楼层 |阅读模式
2013年全国电子设计竞赛倒立摆代码  STM32 + 高精度金属电位器  速度环+位置环PID控制

制作出来的实物图如下:
A`)%0]I[A[DB0%6I}_Y9W5J.png

单片机源程序如下:
  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"
  5. #include "lcd.h"
  6. #include "remote.h"
  7. #include "motor.h"
  8. #include "pwm.h"
  9. #include "timer.h"
  10. #include "math.h"
  11. #include "key.h"
  12. #include "adc.h"


  13. void LCD_Display(void);
  14. float Volt_To_Angle(float volt);
  15. void Start_Action(void);
  16. void Q_1(void);
  17. void Q_2(void);
  18. void Q_3(void);
  19. void Q_4(void);
  20. void Q_5(void);
  21. void Q_6(void);


  22. extern u8  TIM5CH1_CAPTURE_STA;                //输入捕获状态                                                   
  23. extern u32        Frequency;        //输入捕获值  
  24. extern float Period;
  25. extern u8 Motor_Flag; //Motor_flag = 0;反转   = 1时正转
  26. extern u32 pwm_count;
  27. u32 adc1;
  28. int pwm = 1500;
  29. float Err_Angle,Angle,Angle_Last,Err_Angle_Sum,Err_Angle_Last,volt1;
  30. float Kp=30,Ki,Kd;
  31. float Aim_Angle;
  32. float R_x,adc2;
  33. u8 count; //记录第一次情况
  34. u8 mode = 1;//电机正反转标志
  35. int main(void)
  36. {
  37.         u8 key;
  38.         u8 t=0;        
  39.         u8 *str=0;
  40.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  41.         delay_init(168);  //初始化延时函数
  42.         delay_ms(1000);
  43.         delay_ms(1000);
  44.         uart_init(115200);                //初始化串口波特率为115200
  45.         KEY_Init();        
  46.         Motor_Init();           //电机初始化
  47.         Adc_Init();             //adc初始化
  48.         TIM3_Init(100-1,8400-1);         //50HZ  每20ms进入一次中断
  49.         TIM14_PWM_Init(5000-1,21-1);
  50.         TIM5_CH1_Cap_Init();
  51.         
  52.         //LED_Init();                                        //初始化LED
  53.          LCD_Init();
  54.          Remote_Init();                                //红外接收初始化               
  55.         
  56.          POINT_COLOR=RED;//设置字体为红色
  57.         LCD_ShowString(30,50,200,16,16,"Kp:");        
  58.         LCD_ShowString(30,70,200,16,16,"Ki:");        
  59.         LCD_ShowString(30,90,200,16,16,"Kd:");
  60.         LCD_ShowString(30,110,200,16,16,"PWM:");
  61.   LCD_ShowString(30,130,200,16,16,"volt1:");        
  62.   LCD_ShowString(30,150,200,16,16,"Angle:");        
  63.   LCD_ShowString(30,170,200,16,16,"Err_Angle:");        
  64.   LCD_ShowString(30,190,200,16,16,"PWM_Count:");        
  65.                                                                                                                                                                                                          
  66.         while(1)
  67.         {               
  68.                
  69.                 adc1=Get_Adc_Average(ADC_Channel_5,20);//获取通道5的转换值,20次取平均
  70.                
  71.                 adc2=(float)adc1*(3.3/4096);
  72.                
  73.                
  74.                 key = KEY_Scan(0);
  75.                 switch(key)
  76.                 {
  77.                   case 1: Kp += 5;break;
  78.                         case 2: Kp -= 5;break;
  79.                 }
  80.                 //Start_Action();
  81.     //Motor_Drive(0);
  82.                 //Q_2();
  83.                
  84.                 TIM_SetCompare1(TIM14,pwm);
  85.                
  86.                 Angle_Last = Angle;
  87.                 //printf("%d\t%5d\r\n",pwm_count,mode);
  88.                 /*
  89.                   if(Motor_Flag == 1)
  90.                         {
  91.                           printf("正转\r\n");
  92.                         }else
  93.                         printf("反转\r\n");
  94.                         //TIM5CH1_CAPTURE_STA=0;                             //开启下一次捕获
  95.                 */
  96.                         LCD_Display();  //显示参数
  97.                         delay_ms(1);
  98.                
  99.         }
  100. }
  101. u8 count1 = 0;

  102. void TIM3_IRQHandler()
  103. {
  104.     if (TIM_GetITStatus(TIM3, TIM_IT_Update)!=RESET)//判断是否是溢出中断
  105.                 {
  106.                         
  107.       /* 计算实际电压值(近似估算的),如需准确,请进行校准 */
  108.                         Aim_Angle = 276.0;
  109.                         //Kp = 30;
  110.                         Ki = 0;
  111.                         Kd = 800;
  112.                         printf("adc1 = %d\tadc2 = %f\r\n",adc1,adc2);
  113.                         
  114.                         Err_Angle = Aim_Angle-Angle;
  115.                         
  116.                         Err_Angle_Sum += Err_Angle;
  117.                         
  118.                         if(Err_Angle_Sum > 3000)  Err_Angle_Sum = 3000;
  119.                         if(Err_Angle_Sum <-3000)  Err_Angle_Sum =-3000;
  120.                         
  121.                         if(Angle >= 230 && Angle <= 340)
  122.                         {
  123.                                 if(Err_Angle > 0)
  124.                                 {
  125.                             pwm = 300 + Kp*Err_Angle + Ki*Err_Angle_Sum + Kd*(Err_Angle-Err_Angle_Last);
  126.                                 }else
  127.                                   pwm = -300 + Kp*Err_Angle + Ki*Err_Angle_Sum + Kd*(Err_Angle-Err_Angle_Last);
  128.                                 if(pwm > 4000)  pwm = 4000;
  129.                                 if(pwm <-4000)  pwm =-4000;
  130.                                 if(pwm > 0)     Motor_Drive(0);
  131.                                 if(pwm < 0)     Motor_Drive(1);
  132.                         
  133.                           pwm = abs(pwm);
  134.                         }
  135.                         else
  136.                         
  137.                                 Q_1();
  138.                         
  139.                         
  140.                         
  141.                         Err_Angle_Last = Err_Angle;
  142.                         
  143.       TIM_SetCompare1(TIM14,pwm);
  144.     }
  145.      TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除溢出中断标志位
  146. }

  147. void Start_Action()
  148. {
  149.         if(count == 0)
  150.         {
  151.                 mode = 0;
  152.           Motor_Drive(mode);
  153.                 pwm = 1300;
  154.                 pwm_count = 0;
  155.         }
  156.         else
  157.         {
  158.           if(pwm_count >= 10)
  159.                 {
  160.                   pwm_count = 0;
  161.                         mode = ~mode;
  162.                         pwm = 1300 - 130*pwm_count;
  163.                         Motor_Drive(mode);
  164.                 }
  165.                 count = 1;
  166.         }
  167.         count++;
  168. }

  169. void Q_1()
  170. {
  171.   if(count == 0)
  172.         {
  173.           pwm = 1500;
  174.                 TIM_SetCompare1(TIM14,pwm);
  175.                 delay_ms(500);
  176.         }else
  177.         {
  178.           pwm = 2000;
  179.                 if(Angle >= 90)
  180.                 {
  181.                   if(Angle > Angle_Last)
  182.                         {
  183.                           Motor_Drive(1);
  184.                                 TIM_SetCompare1(TIM14,pwm);
  185.                         }
  186.                         else
  187.                         {
  188.                           Motor_Drive(0);
  189.                                 TIM_SetCompare1(TIM14,pwm);
  190.                         }
  191.                 }else
  192.                 {
  193.                   if(Angle > Angle_Last)
  194.                         {
  195.                           Motor_Drive(0);
  196.                                 TIM_SetCompare1(TIM14,pwm);
  197.                         }
  198.                         else
  199.                         {
  200.                           Motor_Drive(1);
  201.                                 TIM_SetCompare1(TIM14,pwm);
  202.                         }
  203.                 }
  204.                
  205.                 count = 1;
  206.         }
  207.   count++;
  208. }

  209. void Q_2()
  210. {
  211.   if(count == 0)
  212.         {
  213.           pwm = 4000;
  214.                 Motor_Drive(1);
  215.                 TIM_SetCompare1(TIM14,pwm);
  216.                 delay_ms(400);
  217.                 count = 1;
  218.         }
  219.         else if(count == 1)
  220.         {
  221.            pwm = 3000;
  222.                  count = 2;
  223.                  Motor_Drive(0);
  224.                  //Motor_Stop();
  225.                  TIM_SetCompare1(TIM14,pwm);
  226.                  delay_ms(200);
  227.         }
  228.         else
  229.         {
  230.           pwm = 0;
  231.                 count = 3;
  232.                 Motor_Stop();
  233.                 //delay_ms(1000);
  234.         }
  235.         
  236. }
  237. void LCD_Display(void)
  238. {
  239.   LCD_Showfloat(86,50,Kp,4,16);
  240.   LCD_Showfloat(86,70,Ki,4,16);
  241.         LCD_Showfloat(86,90,Kd,4,16);
  242.         LCD_ShowNum(86,110,pwm,4,16);        
  243.         LCD_Showfloat(86,130,volt1,4,16);
  244.         LCD_Showfloat(86,150,Angle,5,16);
  245.         LCD_Showfloat(86,170,Err_Angle,5,16);
  246.         LCD_ShowNum(86,190,pwm,3,16);
  247. }

  248. float Volt_To_Angle(float volt)
  249. {
  250.    R_x = 5100*volt / (4.10 - volt);
  251.          Angle = (R_x / 4860) * 360;
  252.         
  253.          return Angle;
  254. }
  255. /*
  256. key=Remote_Scan();        
  257.                 if(key)
  258.                 {         
  259.                         LCD_ShowNum(86,130,key,3,16);                //显示键值
  260.                         LCD_ShowNum(86,150,RmtCnt,3,16);        //显示按键次数                  
  261.                         switch(key)
  262.                         {
  263.                                 case 0:str="ERROR";break;                           
  264.                                 case 162:str="POWER";break;            
  265.                                 case 98:str="UP";break;            
  266.                                 case 2:str="PLAY";break;                 
  267.                                 case 226:str="ALIENTEK";break;                  
  268.                                 case 194:str="RIGHT";break;           
  269.                                 case 34:str="LEFT";break;                  
  270.                                 case 224:str="VOL-";break;                  
  271.                                 case 168:str="DOWN";break;                  
  272.                                 case 144:str="VOL+";break;                    
  273.                                 case 104:str="1";break;                  
  274.                                 case 152:str="2";break;           
  275.                                 case 176:str="3";break;            
  276.                                 case 48:str="4";break;                    
  277.                                 case 24:str="5";break;                    
  278.                                 case 122:str="6";break;                  
  279.                                 case 16:str="7";break;                                                                  
  280.                                 case 56:str="8";break;         
  281.                                 case 90:str="9";break;
  282.                                 case 66:str="0";break;
  283.                                 case 82:str="DELETE";break;                 
  284.                         }
  285.                         LCD_Fill(86,170,116+8*8,170+16,WHITE);        //清楚之前的显示
  286.                         LCD_ShowString(86,170,200,16,16,str);        //显示SYMBOL
  287.                 }else delay_ms(10);         
  288.                 t++;
  289.                 if(t==20)
  290.                 {
  291.                         t=0;
  292.                         LED0=!LED0;
  293.                 }
  294.                 */
  295.                
  296.                
复制代码

所有资料51hei提供下载:
倒立摆.7z (356.13 KB, 下载次数: 87)
回复

使用道具 举报

ID:758611 发表于 2020-8-11 19:40 | 显示全部楼层
这个感觉速度环没有加吧
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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