搜索
bottom↓
回复: 15
打印 上一主题 下一主题

求温度控制PID自整定解决方案,欢迎大家一起讨论

[复制链接]

出0入0汤圆

跳转到指定楼层
1
发表于 2023-5-29 22:25:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在研究继电反馈PID自整定算法,发现算出来的PID值还没有硬件调出来的值准确,还有温度控制能用增量式PID算法么?求求大家为小白答疑解惑

出0入0汤圆

2
 楼主| 发表于 2023-5-29 22:26:44 | 只看该作者
/***********************************************************************/
//*******函数名:void PID_Auto(void)
//*******用途:PID自整定
//*******说明:构建闭环回路 确定稳定极限   确定两个参数  极限值KP和震荡周期·
//*******参数:无
//*******返回值:无  
/***********************************************************************/
void PID_Auto(void)
{
        u8 save_buff[6] = {0}; //保存数据缓存
        u8 i = 0;
        float KC = 0;
        float TC = 0;
        float sum_temp = 0,min_temp = 0,max_temp = 0,aver_temp = 0;
        //第一步进入比较初始温度 确定此时温度处于哪种情况
        if(PID_read == 0)
        {
                if(PID.SetSpeed >=  PID.ActualSpeed)        //        如果初始温度小于设定值
                {
                        pid_self_first_status_flag = 1;
                        Step_Auto = 0;
                }
                else//        如果初始温度大于设定值
                {
                        pid_self_first_status_flag = 0;
                        Step_Auto = 1;
                }
                PID_read = 1;
        }
        if(PID_Auto_Deal == 1)        //自整定过程  修改成500ms 计算一次  如果需要精度很高 计算周期必须短
        {
                PID_Auto_Deal = 0;        //清除标识
                PID_Auto_Time++;        //整定时间计数
                if(PID_Auto_Time >= 6000)//整定时间超过50分钟 整定失败数据回滚
                {
                        PID_Auto_Time = 0;        //计数清零
                }
                //程序第一次进入 查看对比当前温度和设定温度
                //0 设定温度 低于 当前温度  //1设定温度 高于 或者 等于  当前温度  启动加热
                if(( pid_self_first_status_flag == 1) || ( pid_self_first_status_flag == 0))//0 设定温度 低于 当前温度  //1设定温度 高于 或者 等于  当前温度  启动加热
                {
                        if(PID.SetSpeed >=  PID.ActualSpeed)//启动加热
                        {
                                PID_cool_cnt = 0;
                                PID_heat_cnt++;
                                if(PID_heat_cnt >= 3)//连续3次结果都大于大于实际温度
                                {
                                        PID.voltage = 100;//全速加热
                                        percent_lv = Ar_Set;
                                        if(Step_Auto == 0)
                                        {
                                                Step_Auto = 1;
                                                zero_across_counter++;
                                                if(zero_across_counter == 3)
                                                {
                                                        time_low = PID_Auto_Time - 3;//此时的时间不是最低温度对应的时间
                                                }
                                        }
                                }
                        }
                        else//当前温度 大于 设定温度 停止加热
                        {
                                PID_cool_cnt++;
                                PID_heat_cnt = 0;
                                if(PID_cool_cnt > 3)
                                {
                                        PID.voltage = 950;//不加热
                                        percent_lv = 0;
                                        if(Step_Auto == 1)
                                        {
                                                Step_Auto = 0;
                                                zero_across_counter++;
                                                if(zero_across_counter == 3)
                                                {
                                                        time_low = PID_Auto_Time - 3;//此时的时间不是最低温度对应的时间
                                                }
                                        }
                                }
                        }
                        //最低温度 出现在 zero_across_counter = 3 的阶段
                        //最高温度 出现在 zero_across_counter = 4 的阶段
                        if((zero_across_counter == 3 ) || (zero_across_counter == 4 ))
                        {
                                pid_self_calc_buffer[k_pid_self_counter] = PID.ActualSpeed;
                                k_pid_self_counter++;
                                if(k_pid_self_counter > 3)//0--3 共4个元素
                                {
                                        k_pid_self_counter = 0;
                                        enable_calc_min_max_flag = 1;
                                }
                                if(enable_calc_min_max_flag == 1)//只要有4个值,就可以计算了 后面来的值覆盖了前面的值
                                {
                                        //去掉最小值 最大值 取剩下2个值的平均值
                                        sum_temp = 0;  //先清0
                                        min_temp = 300.0;
                                        max_temp = -80.0;
                                        for(i = 0;i < 4;i++)
                                        {
                                                if(pid_self_calc_buffer[i] <= min_temp)
                                                {
                                                        min_temp = pid_self_calc_buffer[i];
                                                }
                                                if(pid_self_calc_buffer[i] >= max_temp)
                                                {
                                                        max_temp = pid_self_calc_buffer[i];
                                                }
                                                sum_temp += pid_self_calc_buffer[i];
                                        }
                                        sum_temp =  sum_temp - min_temp - max_temp ;
                                        //pid_self_first_status_flag = 1 时 最低温度出现在3阶段
                                        //pid_self_first_status_flag = 0 时 最低温度出现在4阶段
                                        if(pid_self_first_status_flag == 1)
                                        {
                                                if(zero_across_counter == 3 )//最低温度
                                                {
                                                        aver_temp = (sum_temp/2.0);                                       
                                                        if( aver_temp <= temp_low )
                                                        {
                                                                temp_low = aver_temp;
                                                        }                               
                                                }
                                                else if(zero_across_counter == 4 )//最高温度
                                                {
                                                        aver_temp = (sum_temp/2.0);
                                                        if( aver_temp >= temp_high )
                                                        {
                                                                temp_high = aver_temp;
                                                        }
                                                }
                                        }
                                        else if(pid_self_first_status_flag == 0)
                                        {
                                                if(zero_across_counter == 4 )//最低温度
                                                {
                                                        aver_temp = (sum_temp/2.0);                                       
                                                        if( aver_temp <= temp_low )
                                                        {
                                                                temp_low = aver_temp;
                                                        }                               
                                                }
                                                else if(zero_across_counter == 3 )//最高温度
                                                {
                                                        aver_temp = (sum_temp/2.0);
                                                        if( aver_temp >= temp_high )
                                                        {
                                                                temp_high = aver_temp;
                                                        }
                                                }
                                        }
                                }
                        }
                        else if(zero_across_counter == 5 )//4次过0 则说明出现了振荡 整定成功
                        {
                                zero_across_counter = 0;                               
                                PID_Auto_Deal = 0;//退出pid阶段
                                time_high = PID_Auto_Time - 3;//此时的时间不是最高温度对应的时间
                                KC = 127/(temp_high - temp_low);
                                TC = 1 * (time_high - time_low);//如果记录了 最低温度 与 最高温度对应的时间 那么沿用这个公式: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;
                                if(dp_Set == 0)
                                {
                                        if(PID.Ki < 0.1)
                                        {
                                                PID.Ki = 0.1;
                                        }
                                }
                                else
                                {
                                        if(PID.Ki < 0.01)
                                        {
                                                PID.Ki = 0.01;
                                        }
                                }
                                if(dp_Set == 1)
                                {
                                        P_Set[cool_open_flag] = PID.Kp*100;
                                        I_Set[cool_open_flag] = PID.Ki*100;
                                }
                                else
                                {
                                        P_Set[cool_open_flag] = PID.Kp*10;
                                        I_Set[cool_open_flag] = PID.Ki*10;
                                }
                                D_Set[cool_open_flag] = PID.Kd;
                                save_buff[0] = P_Set[cool_open_flag]>>8;
                                save_buff[1] = P_Set[cool_open_flag];
                                save_buff[2] = I_Set[cool_open_flag]>>8;
                                save_buff[3] = I_Set[cool_open_flag];
                                save_buff[4] = D_Set[cool_open_flag]>>8;
                                save_buff[5] = D_Set[cool_open_flag];
                                W25QXX_Write(save_buff,4 + 12*cool_open_flag,6);
                                PID_Auto_flag = 0;
                                temp_high = -80.0;                 //得到最高温度
                                temp_low = 300;                          //得到最低温度
                                time_high = 0;                 //得到最高温度
                                time_low = 0;                          //得到最低温度
                                PID_Auto_Time = 0;
                                Status_show(3,0);//符号不显示
                        }
                }               
        }
}       

出235入235汤圆

3
发表于 2023-5-30 01:17:08 | 只看该作者
这头像。。

出0入0汤圆

4
发表于 2023-5-30 04:42:57 来自手机 | 只看该作者
这头像……

出0入18汤圆

5
发表于 2023-5-30 05:58:26 来自手机 | 只看该作者
这头像……

出100入90汤圆

6
发表于 2023-5-30 07:02:46 来自手机 | 只看该作者
最近也在弄PID,大部分都是控制继电器的,现在主要想找到温度值附近就输出一个恒定的PWM,不要一下高一下低的PWM.

出0入0汤圆

7
发表于 2023-5-30 08:14:19 | 只看该作者
继电器的寿命 得考虑呀

出0入0汤圆

8
发表于 2023-5-30 08:37:00 | 只看该作者
还以为阿莫搞嵌入式,原来。。。。。

出0入0汤圆

9
发表于 2023-5-30 08:45:06 | 只看该作者
以为阿莫搞嵌入式,原来。。。。。

出140入115汤圆

10
发表于 2023-5-30 09:07:19 | 只看该作者
以为阿莫搞嵌入式,原来。。。。。

出0入0汤圆

11
 楼主| 发表于 2023-5-30 09:48:32 | 只看该作者
有大哥帮忙指点一下迷津么?这个整定过程是不是有问题,整定出来的P:4.751   I:0.007   D:1.227

出0入0汤圆

12
 楼主| 发表于 2023-5-30 09:49:00 | 只看该作者
lyping1987 发表于 2023-5-30 01:17
这头像。。
(引用自3楼)

这头像怎么了

出0入0汤圆

13
发表于 2023-5-30 22:00:58 | 只看该作者
哈哈,竟然不知是老大的头像,还是...

出0入0汤圆

14
发表于 2023-5-30 23:06:58 来自手机 | 只看该作者
封号警告,,,,

出0入0汤圆

15
发表于 2023-5-31 06:12:08 来自手机 | 只看该作者
这是坛主小号??

出16170入6148汤圆

16
发表于 2023-5-31 06:43:38 来自手机 | 只看该作者
spring152 发表于 2023-5-31 06:12
这是坛主小号??
(引用自15楼)

当然不是。

已经后台警告楼主。封锁ID到今晚23:59
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-5 16:52

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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