久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 12800|回復: 22
打印 上一主題 下一主題
收起左側

STM32 pid自整定+pid控溫+pwm輸出 源程序

  [復制鏈接]
跳轉到指定樓層
樓主
  主要是利用繼電器反饋法進行pid參數自動整定。若測出了系統的一階模型,或得出了系統的臨界比例增益,則可很容易地設計出PID調節器。繼電型自整定的基本想法是,在控制系統中設置兩種模態:測試模態和調節模態。在測試模態下,調節器自動轉換成位式調節,即當測量值小于設定值時,調節器輸出為滿量程,反之為零,使系統產生振蕩,振蕩過程中調節器自動提取被控對象的特征參數;而在調節模態下由系統的特征參數首先得出PID控制器,然后,由此控制器對系統進行調節。當需要PID參數整定時,開關置于調整處,系統按繼電反饋建立起穩定的極限環振蕩后,就可以根據系系統響應特征確定PID參數。自整定計算完成后開關置于調節處,系統進入正常控制。內含STM32程序,包含DS18B20讀取溫度

STM32單片機源程序如下:
  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. }
復制代碼



  1. #include "stm32f10x.h"
  2. #include "core_cm3.h"
  3. #include "./systick/bsp_SysTick.h"
  4. #include "./led/bsp_led.h"
  5. #include "./usart/bsp_usart.h"
  6. #include "./ds18b20/bsp_ds18b20.h"
  7. #include "./pid/pid.h"
  8. #include "./timer/timer.h"
  9. #include "./AdvanceTim/bsp_AdvanceTim.h"
  10. #include "./GeneralTim/bsp_GeneralTim.h"

  11. volatile uint32_t time = 0; // ms 計時變量
  12. volatile uint32_t time2 = 0; // ms 計時變量
  13. float TM1,TM2;
  14. volatile uint8_t ucDs18b20Id[8];

  15. volatile        uint16_t Step_Auto;        
  16. volatile        uint32_t PID_cool_cnt;
  17. volatile        uint32_t PID_heat_cnt;
  18. volatile        uint16_t pid_self_first_status_flag;        //標志位
  19. volatile        uint16_t PID_Deal,PID_auto_Deal;
  20. volatile        uint16_t zero_across_counter;
  21. volatile        uint16_t k_pid_self_counter;
  22. volatile        uint16_t CCR4_Val;
  23. volatile        uint16_t kkk;
  24. //volatile         uint16_t save_buff[9000] = {0};
  25. void delay();

  26. void PID_Init()
  27. {
  28.                 pid.Sv=30;                //用戶設定溫度
  29.                 pid.OUT0=1;

  30.                 zero_across_counter=0;
  31.                 PID_cool_cnt=0;
  32.                 PID_heat_cnt=0;
  33.                 PID_Deal=0;
  34.                 PID_auto_Deal=0;
  35.                 pid_self_first_status_flag = 0;
  36.                 k_pid_self_counter=0;
  37.                 if( pid.Pv <= pid.Sv)        //設定溫度高于當前溫度
  38.                 {
  39.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  40.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  41.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  42.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  43.                         pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;        
  44.                         
  45.                 }               
  46. //                CCR4_Val=100;
  47. //                PID_auto_Deal=1;
  48. //                PID_Deal=1;
  49. //                pid.Sv=30;
  50. //                pid.Kp=38.0999985;
  51. //                pid.Ki=0.21666673;
  52. //                pid.Kd=2.8575;
  53.                
  54.         
  55. }



  56. /**
  57.   * @brief  主函數
  58.   * @param  無  
  59.   * @retval 無
  60.   */
  61. int main(void)
  62. {        
  63.                 delay();
  64.         CCR4_Val=50;
  65.         ADVANCE_TIM_Init();
  66.         GENERAL_TIM_Init();
  67.         
  68.         /* 配置SysTick 為1us中斷一次 */
  69.         SysTick_Init();
  70.         
  71.         
  72. //        /* 端口初始化 */
  73. //        LED_GPIO_Config();//初始化了PB1口
  74.         
  75.         

  76.         
  77.         USART_Config();        //初始化串口1
  78.         printf("\r\n this is a ds18b20 test demo \r\n");
  79.         while( DS18B20_Init() )        
  80.         printf("\r\n no ds18b20 exit \r\n");//初始化DS18B20,不初始化就等待這里?
  81.         printf("\r\n ds18b20 exit \r\n");
  82.         DS18B20_ReadId(ucDs18b20Id);
  83.         TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
  84.         pid.Pv=TM1;
  85.         PID_Init();  //參數初始化        
  86.         pid.Sv1=28;        
  87.         while(1)        
  88.         {        
  89.                 printf ( "\r\n%.1f",TM1);                // 打印通過 DS18B20 序列號獲取的溫度值        
  90.                 Delay_ms(10);
  91.                 TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
  92.                 pid.Pv=TM1;//當前溫度         
  93.                 pid.Pv=TM1;//當前溫度        
  94.                 PID_auto();
  95.                 PID_Calc(); //pid計算                                                               
  96. //                printf ( "\r\n%.1f",TM1);                // 打印通過 DS18B20 序列號獲取的溫度值        
  97. //                Delay_ms(1000);
  98. //                if ( time >= 10 ) /* 10 * 1 ms = 10ms 時間到 */
  99. //    {
  100. //      time = 0;  
  101. //                        TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
  102. //                        pid.Pv=TM1;//當前溫度        
  103. //    }
  104. //                if ( time2 >= 1000 ) /* 1000 * 1 ms = 1s 時間到 */
  105. //    {
  106. //      time2 = 0;  
  107. //                        pid.Pv=TM1;//當前溫度        
  108. //                        PID_auto();
  109. //                        PID_Calc(); //pid計算                                                               
  110. //                }               
  111.         }         
  112. }                                
  113. void delay(void)
  114. {
  115.         int i;
  116.         for(i=0; i<10000000; i++)
  117.                 ;
  118. }
復制代碼

代碼工程文件51hei附件下載:
代碼.7z (197.13 KB, 下載次數: 515)

評分

參與人數 3黑幣 +60 收起 理由
gzhdssj + 5 很給力!
fjc321x + 5
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏47 分享淘帖 頂8 踩
回復

使用道具 舉報

沙發
ID:275041 發表于 2021-8-14 09:17 | 只看該作者
最近正在學這PID呢,謝謝了
回復

使用道具 舉報

板凳
ID:748535 發表于 2021-8-22 10:15 | 只看該作者

最近正在學這PID呢,謝謝了
回復

使用道具 舉報

地板
ID:966468 發表于 2021-9-16 11:40 | 只看該作者
最近正在學這PID呢,謝謝了
回復

使用道具 舉報

5#
ID:856642 發表于 2021-9-22 19:51 | 只看該作者
最近正在學這PID呢,謝謝了
回復

使用道具 舉報

6#
ID:967413 發表于 2021-9-23 08:57 | 只看該作者
正在做一個PID溫控器的項目,學習了!謝謝!
回復

使用道具 舉報

7#
ID:936528 發表于 2021-9-24 10:38 | 只看該作者
樓主你好,請問下這里為什么當前溫度大于設定溫度,占空比卻還要調到最大

捕獲.PNG (61.39 KB, 下載次數: 258)

捕獲.PNG
回復

使用道具 舉報

8#
ID:462629 發表于 2021-12-28 10:18 | 只看該作者
有原理圖嗎
回復

使用道具 舉報

9#
ID:334781 發表于 2021-12-31 09:29 | 只看該作者
樓主,有原理圖嗎,PID控制是不是要用可控硅呢,用繼電器的話,會不會影響使用壽命呢?
回復

使用道具 舉報

10#
ID:41543 發表于 2023-2-1 10:53 | 只看該作者
學習中 溫控,pid ,感謝
回復

使用道具 舉報

11#
ID:385620 發表于 2023-8-24 09:12 | 只看該作者
您好,您代碼中自整定這塊好像沒有運行,KI,KD,PD這3個參數一直為初值0
回復

使用道具 舉報

12#
ID:385620 發表于 2023-8-24 09:13 | 只看該作者
您好,你代碼里的自整定部分沒有運行,其中KI,KD,KP3個參數一直為0
回復

使用道具 舉報

13#
ID:958310 發表于 2024-1-4 10:32 | 只看該作者
請問“                                KC = 127/V_temp; //如果記錄了 最低溫度 與 最高溫度對應的時間 那么沿用這個公式:TC = 2 * (TIME_Hight - TIME_LOW);                                        TC = k_pid_self_counter;        //TC =2 * (TIME_Hight - TIME_LOW);                                                         pid.Kp = 0.6*KC;                                                pid.Ki = (0.6*KC)/(0.5*TC)/10;                                 pid.Kd = (0.6*KC)*(0.125*TC)/60;”這一段計算是根據什么得到的?
回復

使用道具 舉報

14#
ID:52749 發表于 2024-2-1 16:07 | 只看該作者
CCR4_VAL=100  out=0%            CCR4_VAL=0  out=100%   

請問TC    得出后,PID運算周期 ,輸出周期沒有更改,這個應該很重要,關系到系統的滯后
回復

使用道具 舉報

15#
ID:52749 發表于 2024-2-1 16:08 | 只看該作者

請問“                                KC = 127/V_temp; //如果記錄了 最低溫度 與 最高溫度對應的時間 那么沿用這個公式:TC = 2 * (TIME_Hight - TIME_LOW);                                        TC = k_pid_self_counter;        //TC =2 * (TIME_Hight - TIME_LOW);                                                         pid.Kp = 0.6*KC;                                                pid.Ki = (0.6*KC)/(0.5*TC)/10;                                 pid.Kd = (0.6*KC)*(0.125*TC)/60;”這一段計算是根據什么得到的?


這個應該是繼電整定法,網上能找到公式

回復

使用道具 舉報

16#
ID:164385 發表于 2024-2-4 09:28 | 只看該作者
很好的代碼,學習了
回復

使用道具 舉報

17#
ID:592857 發表于 2024-2-28 14:39 | 只看該作者
  最近正在學這PID呢,謝謝了
回復

使用道具 舉報

18#
ID:346648 發表于 2024-3-7 22:21 | 只看該作者
最近正在學這PID呢,謝謝了
回復

使用道具 舉報

19#
ID:419063 發表于 2024-9-30 17:08 | 只看該作者
沒玩過自整定,謝謝分享!學習一下。
回復

使用道具 舉報

20#
ID:1134628 發表于 2024-11-7 11:09 | 只看該作者

最近正在學這PID呢,謝謝了
回復

使用道具 舉報

21#
ID:704812 發表于 2024-11-12 16:41 | 只看該作者
感謝,想您學習。
回復

使用道具 舉報

22#
ID:294886 發表于 2024-12-2 13:43 | 只看該作者
謝謝分享,PID挺好用的,學習學習
回復

使用道具 舉報

23#
ID:1143650 發表于 2025-2-9 21:36 | 只看該作者
最近正在學這PID呢,謝謝了
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩在线观看网站 | 欧美日产国产成人免费图片 | 国产欧美在线视频 | 一区二区日本 | 午夜视频在线观看网址 | 在线色网| 精品亚洲一区二区三区四区五区高 | 亚洲狠狠 | 蜜臀久久99精品久久久久久宅男 | 盗摄精品av一区二区三区 | 免费福利视频一区二区三区 | 天天干视频网 | a视频在线观看 | 日韩在线一区二区三区 | 久久久久久美女 | 四虎成人av | 99精品一区二区三区 | 亚洲午夜精品 | 水蜜桃亚洲一二三四在线 | 日一区二区 | 欧美日韩成人在线观看 | 久久综合九色综合欧美狠狠 | 成人精品国产一区二区4080 | av在线成人 | 亚洲欧美激情精品一区二区 | 日本不卡一区 | 亚洲一区二区久久 | 91精品国产91久久久久久密臀 | 97视频在线观看免费 | 日韩精品一区二区三区免费视频 | 国产日韩欧美电影 | 欧美黄色片 | 日韩区 | 亚洲看片网站 | 91精品一区二区三区久久久久久 | 夜夜骑首页 | 在线视频一区二区三区 | 亚州综合一区 | 99视频免费 | 亚洲 欧美 激情 另类 校园 | 亚洲导航深夜福利涩涩屋 |