- #include "./pid/pid.h"
- #include "./led/bsp_led.h"
- #include "./GeneralTim/bsp_GeneralTim.h"
- PID pid; //存放PID算法所需要的数据
- uint16_t pw;
- uint16_t save_buff[9000] = {0}; //保存数据缓存
- extern volatile uint16_t Step_Auto;
- extern volatile uint32_t PID_cool_cnt;
- extern volatile uint32_t PID_heat_cnt;
- extern volatile uint16_t pid_self_first_status_flag; //标志位
- extern volatile uint16_t PID_Deal,PID_auto_Deal;
- extern volatile uint16_t zero_across_counter;
- extern volatile uint16_t k_pid_self_counter;
- extern volatile uint16_t CCR4_Val;
- extern volatile uint16_t kkk;
- void PID_Calc() //pid计算
- {
- float DelEk;
- float out;
- if (PID_Deal == 1)
- {
- pid.Ek=pid.Sv-pid.Pv; //得到当前的偏差值
- pid.SEk+=pid.Ek; //历史偏差总和
- DelEk=pid.Ek-pid.Ek_1; //最近两次偏差之差
- pid.Pout=pid.Kp*pid.Ek; //比例输出
- pid.Iout=pid.Ki*pid.SEk; //积分输出
- pid.Dout=pid.Kd*DelEk; //微分输出
- out= pid.Pout+ pid.Iout+ pid.Dout;
- kkk++;
- if(out>255)
- {
- kkk=0;
- pid.SEk=0;
- }
- if(out>255)
- {
- pid.OUT=255;
- }
- else if(out<0)
- {
- pid.OUT=0;
- }
- else
- {
- pid.OUT=out;
- }
- pid.Ek_1=pid.Ek; //更新偏差
- // printf ( "\r\n%.1f\r\n",out);
- PID_out();
-
- }
- }
- void PID_out() //输出PID运算结果到负载---每1ms被调用1次
- {
- uint16_t kk;
- if (pid.Pv>pid.Sv)//当前温度大于用户设定温度
- {
- CCR4_Val=100;
- GENERAL_TIM_Init();
- }
- else
- {
- kk=100-pid.OUT*100/255;
- CCR4_Val=kk;
- GENERAL_TIM_Init();
- // printf ( "\r\n%3d\r\n",kk);
- }
- }
- void PID_auto()//继电器反馈法自整定pid参数
- {
- uint8_t i = 0;
- float KC = 0;
- float TC = 0;
- float V_temp = 0,min_temp = 0,max_temp = 0;
- float TIME_Hight=0,TIME_LOW=0;
-
-
- //第一步进入比较初始温度 确定此时温度处于哪种情况
- if (PID_auto_Deal== 0)
- {
- /******************************************************************************************************/
-
- PID_Deal = 0;//退出pid
-
- //程序第一次进入 查看对比当前温度和设定温度
- if(pid.Pv < pid.Sv1)//当前温度低于设定温度
- {
- PID_heat_cnt++; //热
- PID_cool_cnt = 0;
- if(PID_heat_cnt >= 3)//连续3次结果
- {
- CCR4_Val=0;//加热
- GENERAL_TIM_Init();
- if(Step_Auto == 0)
- {
- Step_Auto = 1;
- zero_across_counter++;
- // printf ( "\r\n1");
- }
- }
- }
- else//当前温度 大于 设定温度 停止加热
- {
- PID_cool_cnt++;
- PID_heat_cnt = 0;
- if(PID_cool_cnt > 3)
- {
- CCR4_Val=100; //不加热
- GENERAL_TIM_Init();
- if(Step_Auto == 1) //设定温度高于当前温度
- {
- Step_Auto = 0;
- zero_across_counter++;
- }
- }
- }
- if(PID_heat_cnt >= 65535)//连续3次结果
- {
- PID_heat_cnt=65535;
- }
- if(PID_cool_cnt >= 65534)//连续3次结果
- {
- PID_cool_cnt=65534;
- }
-
-
-
- /*****************开始计算强行振荡的周期和幅值****************************/
- if((zero_across_counter == 3 ) || (zero_across_counter == 4 ))
- {
- save_buff[k_pid_self_counter] = pid.Pv;
-
- k_pid_self_counter++;
-
- if(k_pid_self_counter >=9000)
- {
- k_pid_self_counter = 0;
- }
- }
- else if(zero_across_counter == 5 )//5次过0 则说明出现了振荡 整定成功
- {
- PID_Deal = 1;
- PID_auto_Deal = 1;
- zero_across_counter = 0;
- max_temp=save_buff[0];
- min_temp=save_buff[0];
- for(i = 0;i < k_pid_self_counter;i++)
- {
- if(save_buff[i] >= max_temp)
- {
- max_temp = save_buff[i];
- TIME_LOW=i;
- }
- if(save_buff[i] <= min_temp)
- {
- min_temp = save_buff[i];
- TIME_Hight=i;
- }
- }
- V_temp = max_temp - min_temp; //最大减最小就是幅值
-
-
- 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;
- printf ( "\r\n整定成功");
- }
- }
- }
- #include "stm32f10x.h"
- #include "core_cm3.h"
- #include "./systick/bsp_SysTick.h"
- #include "./led/bsp_led.h"
- #include "./usart/bsp_usart.h"
- #include "./ds18b20/bsp_ds18b20.h"
- #include "./pid/pid.h"
- #include "./timer/timer.h"
- #include "./AdvanceTim/bsp_AdvanceTim.h"
- #include "./GeneralTim/bsp_GeneralTim.h"
- volatile uint32_t time = 0; // ms 计时变量
- volatile uint32_t time2 = 0; // ms 计时变量
- float TM1,TM2;
- volatile uint8_t ucDs18b20Id[8];
- volatile uint16_t Step_Auto;
- volatile uint32_t PID_cool_cnt;
- volatile uint32_t PID_heat_cnt;
- volatile uint16_t pid_self_first_status_flag; //标志位
- volatile uint16_t PID_Deal,PID_auto_Deal;
- volatile uint16_t zero_across_counter;
- volatile uint16_t k_pid_self_counter;
- volatile uint16_t CCR4_Val;
- volatile uint16_t kkk;
- //volatile uint16_t save_buff[9000] = {0};
- void delay();
- void PID_Init()
- {
- pid.Sv=30; //用户设定温度
- pid.OUT0=1;
- zero_across_counter=0;
- PID_cool_cnt=0;
- PID_heat_cnt=0;
- PID_Deal=0;
- PID_auto_Deal=0;
- pid_self_first_status_flag = 0;
- k_pid_self_counter=0;
- if( pid.Pv <= pid.Sv) //设定温度高于当前温度
- {
- pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;
- pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;
- pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;
- pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;
- pid.Sv1=(pid.Sv-pid.Pv)/2+pid.Pv;
-
- }
- // CCR4_Val=100;
- // PID_auto_Deal=1;
- // PID_Deal=1;
- // pid.Sv=30;
- // pid.Kp=38.0999985;
- // pid.Ki=0.21666673;
- // pid.Kd=2.8575;
-
-
- }
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] 主函数
- * @param 无
- * @retval 无
- */
- int main(void)
- {
- delay();
- CCR4_Val=50;
- ADVANCE_TIM_Init();
- GENERAL_TIM_Init();
-
- /* 配置SysTick 为1us中断一次 */
- SysTick_Init();
-
-
- // /* 端口初始化 */
- // LED_GPIO_Config();//初始化了PB1口
-
-
-
- USART_Config(); //初始化串口1
- printf("\r\n this is a ds18b20 test demo \r\n");
- while( DS18B20_Init() )
- printf("\r\n no ds18b20 exit \r\n");//初始化DS18B20,不初始化就等待这里?
- printf("\r\n ds18b20 exit \r\n");
- DS18B20_ReadId(ucDs18b20Id);
- TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
- pid.Pv=TM1;
- PID_Init(); //参数初始化
- pid.Sv1=28;
- while(1)
- {
- printf ( "\r\n%.1f",TM1); // 打印通过 DS18B20 序列号获取的温度值
- Delay_ms(10);
- TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
- pid.Pv=TM1;//当前温度
- pid.Pv=TM1;//当前温度
- PID_auto();
- PID_Calc(); //pid计算
- // printf ( "\r\n%.1f",TM1); // 打印通过 DS18B20 序列号获取的温度值
- // Delay_ms(1000);
- // if ( time >= 10 ) /* 10 * 1 ms = 10ms 时间到 */
- // {
- // time = 0;
- // TM1=DS18B20_GetTemp_MatchRom ( ucDs18b20Id );
- // pid.Pv=TM1;//当前温度
- // }
- // if ( time2 >= 1000 ) /* 1000 * 1 ms = 1s 时间到 */
- // {
- // time2 = 0;
- // pid.Pv=TM1;//当前温度
- // PID_auto();
- // PID_Calc(); //pid计算
- // }
- }
- }
- void delay(void)
- {
- int i;
- for(i=0; i<10000000; i++)
- ;
- }
|