[STM32F1] STM32 pid自整定+pid控温+pwm输出

[复制链接]
512|0
 楼主| louliana 发表于 2025-3-22 07:53 | 显示全部楼层 |阅读模式
  1. #include "./pid/pid.h"   
  2. #include "./led/bsp_led.h"   
  3. #include "./GeneralTim/bsp_GeneralTim.h"

  4. PID pid; //存放PID算法所需要的数据

  5. uint16_t pw;
  6. uint16_t save_buff[9000] = {0}; //保存数据缓存
  7. extern volatile        uint16_t Step_Auto;      
  8. extern volatile        uint32_t PID_cool_cnt;
  9. extern volatile        uint32_t PID_heat_cnt;
  10. extern volatile        uint16_t pid_self_first_status_flag;        //标志位
  11. extern volatile        uint16_t PID_Deal,PID_auto_Deal;
  12. extern volatile        uint16_t zero_across_counter;
  13. extern volatile        uint16_t k_pid_self_counter;
  14. extern volatile        uint16_t CCR4_Val;
  15. extern volatile        uint16_t kkk;
  16. void PID_Calc()  //pid计算
  17. {
  18.         float DelEk;      
  19.         float out;
  20.         if (PID_Deal == 1)
  21.         {
  22.                 pid.Ek=pid.Sv-pid.Pv;   //得到当前的偏差值
  23.                 pid.SEk+=pid.Ek;        //历史偏差总和
  24.                 DelEk=pid.Ek-pid.Ek_1;  //最近两次偏差之差

  25.                 pid.Pout=pid.Kp*pid.Ek;     //比例输出
  26.                 pid.Iout=pid.Ki*pid.SEk;                          //积分输出
  27.                 pid.Dout=pid.Kd*DelEk;                            //微分输出
  28.                 out= pid.Pout+ pid.Iout+ pid.Dout;
  29.                 kkk++;
  30.                 if(out>255)
  31.                 {
  32.                         kkk=0;
  33.                         pid.SEk=0;
  34.                 }
  35.                 if(out>255)
  36.                 {
  37.                         pid.OUT=255;
  38.                 }
  39.                 else if(out<0)
  40.                 {
  41.                         pid.OUT=0;
  42.                 }
  43.                 else
  44.                 {
  45.                         pid.OUT=out;
  46.                 }
  47.                 pid.Ek_1=pid.Ek;  //更新偏差
  48. //                printf ( "\r\n%.1f\r\n",out);      
  49.                 PID_out();
  50.                
  51.         }
  52. }
  53. void PID_out()  //输出PID运算结果到负载---每1ms被调用1次
  54. {
  55.         uint16_t kk;
  56.         if (pid.Pv>pid.Sv)//当前温度大于用户设定温度
  57.         {
  58.                 CCR4_Val=100;
  59.                 GENERAL_TIM_Init();
  60.         }
  61.                 else
  62.                 {
  63.                 kk=100-pid.OUT*100/255;
  64.                 CCR4_Val=kk;
  65.                 GENERAL_TIM_Init();
  66. //        printf ( "\r\n%3d\r\n",kk);
  67.                 }
  68. }
  69. void PID_auto()//继电器反馈法自整定pid参数
  70. {

  71.         uint8_t i = 0;
  72.         float KC = 0;
  73.         float TC = 0;
  74.         float V_temp = 0,min_temp = 0,max_temp = 0;
  75.         float TIME_Hight=0,TIME_LOW=0;
  76.       
  77.       
  78.         //第一步进入比较初始温度 确定此时温度处于哪种情况

  79. if (PID_auto_Deal== 0)
  80. {
  81. /******************************************************************************************************/
  82.                
  83.                 PID_Deal = 0;//退出pid
  84.                
  85.                 //程序第一次进入 查看对比当前温度和设定温度

  86.                 if(pid.Pv < pid.Sv1)//当前温度低于设定温度
  87.                 {
  88.                         PID_heat_cnt++;                //热
  89.                         PID_cool_cnt = 0;
  90.                         if(PID_heat_cnt >= 3)//连续3次结果
  91.                         {
  92.                                 CCR4_Val=0;//加热
  93.                                 GENERAL_TIM_Init();

  94.                                 if(Step_Auto == 0)               
  95.                                 {
  96.                                         Step_Auto = 1;
  97.                                         zero_across_counter++;
  98. //                                        printf ( "\r\n1");      
  99.                                 }
  100.                         }
  101.                 }
  102.                 else//当前温度 大于 设定温度 停止加热
  103.                 {
  104.                         PID_cool_cnt++;
  105.                         PID_heat_cnt = 0;
  106.                         if(PID_cool_cnt > 3)
  107.                         {
  108.                                 CCR4_Val=100;                //不加热
  109.                                 GENERAL_TIM_Init();
  110.                                 if(Step_Auto == 1)                //设定温度高于当前温度
  111.                                 {
  112.                                         Step_Auto = 0;
  113.                                         zero_across_counter++;
  114.                                 }
  115.                         }
  116.                 }
  117.                 if(PID_heat_cnt >= 65535)//连续3次结果
  118.                 {
  119.                         PID_heat_cnt=65535;
  120.                 }
  121.                 if(PID_cool_cnt >= 65534)//连续3次结果
  122.                 {
  123.                         PID_cool_cnt=65534;
  124.                 }
  125.                
  126.                
  127.                
  128.                 /*****************开始计算强行振荡的周期和幅值****************************/                       

  129.                 if((zero_across_counter == 3 ) || (zero_across_counter == 4 ))
  130.                 {
  131.                         save_buff[k_pid_self_counter] = pid.Pv;
  132.                        
  133.                         k_pid_self_counter++;
  134.                        
  135.                         if(k_pid_self_counter >=9000)
  136.                         {
  137.                                 k_pid_self_counter = 0;                                       
  138.                         }
  139.                 }
  140.                 else if(zero_across_counter == 5 )//5次过0 则说明出现了振荡 整定成功
  141.                 {
  142.                                 PID_Deal = 1;
  143.                                 PID_auto_Deal = 1;
  144.                                 zero_across_counter = 0;

  145.                                         max_temp=save_buff[0];
  146.                                         min_temp=save_buff[0];
  147.                                         for(i = 0;i < k_pid_self_counter;i++)
  148.                                         {
  149.                                                 if(save_buff[i] >= max_temp)
  150.                                                 {
  151.                                                         max_temp = save_buff[i];
  152.                                                         TIME_LOW=i;
  153.                                                 }
  154.                                                 if(save_buff[i] <= min_temp)
  155.                                                 {
  156.                                                         min_temp = save_buff[i];
  157.                                                         TIME_Hight=i;
  158.                                                 }
  159.                                         }
  160.                                         V_temp =  max_temp - min_temp;                                        //最大减最小就是幅值
  161.                                        
  162.                                        
  163.                                 KC = 127/V_temp;
  164. //如果记录了 最低温度 与 最高温度对应的时间 那么沿用这个公式:TC = 2 * (TIME_Hight - TIME_LOW);      
  165.                                 TC = k_pid_self_counter;        //TC =2 * (TIME_Hight - TIME_LOW);
  166.                        
  167.                                 pid.Kp = 0.6*KC;               
  168.                                 pid.Ki = (0.6*KC)/(0.5*TC)/10;
  169.                                 pid.Kd = (0.6*KC)*(0.125*TC)/60;
  170.                                 printf ( "\r\n整定成功");               
  171.                         }
  172.         }      
  173. }




  174. #include "stm32f10x.h"
  175. #include "core_cm3.h"
  176. #include "./systick/bsp_SysTick.h"
  177. #include "./led/bsp_led.h"
  178. #include "./usart/bsp_usart.h"
  179. #include "./ds18b20/bsp_ds18b20.h"
  180. #include "./pid/pid.h"
  181. #include "./timer/timer.h"
  182. #include "./AdvanceTim/bsp_AdvanceTim.h"
  183. #include "./GeneralTim/bsp_GeneralTim.h"

  184. volatile uint32_t time = 0; // ms 计时变量
  185. volatile uint32_t time2 = 0; // ms 计时变量
  186. float TM1,TM2;
  187. volatile uint8_t ucDs18b20Id[8];

  188. volatile        uint16_t Step_Auto;        
  189. volatile        uint32_t PID_cool_cnt;
  190. volatile        uint32_t PID_heat_cnt;
  191. volatile        uint16_t pid_self_first_status_flag;        //标志位
  192. volatile        uint16_t PID_Deal,PID_auto_Deal;
  193. volatile        uint16_t zero_across_counter;
  194. volatile        uint16_t k_pid_self_counter;
  195. volatile        uint16_t CCR4_Val;
  196. volatile        uint16_t kkk;
  197. //volatile         uint16_t save_buff[9000] = {0};
  198. void delay();

  199. void PID_Init()
  200. {
  201.                 pid.Sv=30;                //用户设定温度
  202.                 pid.OUT0=1;

  203.                 zero_across_counter=0;
  204.                 PID_cool_cnt=0;
  205.                 PID_heat_cnt=0;
  206.                 PID_Deal=0;
  207.                 PID_auto_Deal=0;
  208.                 pid_self_first_status_flag = 0;
  209.                 k_pid_self_counter=0;
  210.                 if( pid.Pv <= pid.Sv)        //设定温度高于当前温度
  211.                 {
  212.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  213.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  214.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  215.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  216.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  217.                         
  218.                 }               
  219. //                CCR4_Val=100;
  220. //                PID_auto_Deal=1;
  221. //                PID_Deal=1;
  222. //                pid.Sv=30;
  223. //                pid.Kp=38.0999985;
  224. //                pid.Ki=0.21666673;
  225. //                pid.Kd=2.8575;
  226.                
  227.         
  228. }



  229. /**
  230.   * [url=home.php?mod=space&uid=247401]@brief[/url]  主函数
  231.   * @param  无  
  232.   * @retval 无
  233.   */
  234. int main(void)
  235. {        
  236.                 delay();
  237.         CCR4_Val=50;
  238.         ADVANCE_TIM_Init();
  239.         GENERAL_TIM_Init();
  240.         
  241.         /* 配置SysTick 为1us中断一次 */
  242.         SysTick_Init();
  243.         
  244.         
  245. //        /* 端口初始化 */
  246. //        LED_GPIO_Config();//初始化了PB1口
  247.         
  248.         

  249.         
  250.         USART_Config();        //初始化串口1
  251.         printf("\r\n this is a ds18b20 test demo \r\n");
  252.         while( DS18B20_Init() )        
  253.         printf("\r\n no ds18b20 exit \r\n");//初始化DS18B20,不初始化就等待这里?
  254.         printf("\r\n ds18b20 exit \r\n");
  255.         DS18B20_ReadId(ucDs18b20Id);
  256.         TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
  257.         pid.Pv=TM1;
  258.         PID_Init();  //参数初始化        
  259.         pid.Sv1=28;        
  260.         while(1)        
  261.         {        
  262.                 printf ( "\r\n%.1f",TM1);                // 打印通过 DS18B20 序列号获取的温度值        
  263.                 Delay_ms(10);
  264.                 TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
  265.                 pid.Pv=TM1;//当前温度         
  266.                 pid.Pv=TM1;//当前温度        
  267.                 PID_auto();
  268.                 PID_Calc(); //pid计算                                                               
  269. //                printf ( "\r\n%.1f",TM1);                // 打印通过 DS18B20 序列号获取的温度值        
  270. //                Delay_ms(1000);
  271. //                if ( time >= 10 ) /* 10 * 1 ms = 10ms 时间到 */
  272. //    {
  273. //      time = 0;  
  274. //                        TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
  275. //                        pid.Pv=TM1;//当前温度        
  276. //    }
  277. //                if ( time2 >= 1000 ) /* 1000 * 1 ms = 1s 时间到 */
  278. //    {
  279. //      time2 = 0;  
  280. //                        pid.Pv=TM1;//当前温度        
  281. //                        PID_auto();
  282. //                        PID_Calc(); //pid计算                                                               
  283. //                }               
  284.         }         
  285. }                                
  286. void delay(void)
  287. {
  288.         int i;
  289.         for(i=0; i<10000000; i++)
  290.                 ;
  291. }


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

本版积分规则

50

主题

1627

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部