TEC 高精度控温算法

您所在的位置:网站首页 恒温机怎么调温度几位数 TEC 高精度控温算法

TEC 高精度控温算法

2024-07-14 13:21| 来源: 网络整理| 查看: 265

主要实现TEC的指定时间的升温与指定时间的降温,指定温度的恒温,给合硬件的优化可实现高精度温度控制

void temp_tec_pid(uint8_t chn) { uint8_t i; float mid_fTem1; float mid_fTem2; float mid_fTem3; //参数计算临时值 float mid_fPWM = 0; //最终输出的PWM值 temperation_control_t *temp_ctrl_ptr = &temperation_tec_control[chn]; temp_pid_t *temp_pid_ptr = &temp_ctrl_ptr->temp_pid; if(temp_ctrl_ptr->u8EnFlag == 1 ){ //如果标志位使能,则PID温控, temp_pid_ptr->ActTemperature = tec_temp.fTemp[chn]; } temp_pid_ptr->SetTemperature = temp_ctrl_ptr->fTargeter; switch(temp_ctrl_ptr->state) { case 0X00 ://state-0:空闲状态 { //如果有触发PID状态跳转而且使能了该通道PID温控 if(temp_ctrl_ptr->u8PidStateFlag == 1 && temp_ctrl_ptr->u8Channel_En==1){ temp_ctrl_ptr->state = 0X01;//跳转至状态1 temp_ctrl_ptr->u8PidStateFlag = 0 ;//跳转状态标志清0 temp_pid_ptr->integral = 0; //通道积分清0 temp_ctrl_ptr->u8Channel_Done = 0 ;//通道到达目标温度标志清0/小于0.1摄氏度时置位 temp_pid_ptr->SetTemperature = temp_ctrl_ptr->fTargeter;//设置目标温度 temp_ctrl_ptr->u8PwmDir =0; //制冷方向降温标志 temp_ctrl_ptr->u8PwmAdj =0; //占空比计数 // voltage_enable(chn, 1); } else if(temp_ctrl_ptr->u8PidStateFlag == 1 && temp_ctrl_ptr->u8Channel_En==0){ temp_ctrl_ptr->u8PidStateFlag = 0 ;//跳转状态标志清0 tec_drv_pwm(chn, TEC_CLOSE, 0); //序号,关闭标志,占空比; // voltage_enable(chn, 0); float temp = tec_temp.fTemp[chn]; if( temp>=0 ){ temppid_segger_log("CHN%d %d %d %d.%d \r" ,chn+1, temp_ctrl_ptr->state , tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } else{ temp *= -1; temppid_segger_log("CHN%d %d %d -%d.%d \r" ,chn+1, temp_ctrl_ptr->state ,tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } } break; } case 0X01 ://state-1:进行比例升降温 { temp_pid_ptr->Err = temp_pid_ptr->SetTemperature - temp_pid_ptr->ActTemperature;//当前目标温度与实际温度差 /*---------------速度自动调节 ----------------------------------------------*/ mid_fTem1 = ( temp_pid_ptr->Err_Last - temp_pid_ptr->Err ) * PID_PRE ;//计算变温速度/50MS计算1次/单位:℃/S / 此值为正则实际在加热中 mid_fTem2 = (float)fabs(mid_fTem1);//求出速度绝对值 float temp2; temp2 = mid_fTem2; temppid_segger_log("CHN%d %d.%d %d\n" ,chn+1, (int)temp2, (int)((temp2-(int)temp2)*100),temp_ctrl_ptr->u8PwmAdj ); /*--------------如果在升温控制进行PID-----------------------*/ if(temp_ctrl_ptr->u8HotCool_En == 0X01 ){ if(mid_fTem2 > temp_ctrl_ptr->fSpeed ){//如果变温速度太快 /*--------------如果是降温太快,则需要自加1----------------*/ if(mid_fTem1 u8PwmAdj u8PwmAdj+=5; } /*--------------如果是升温太快,则需要自减1----------------*/ if(mid_fTem1 > 0){ if(temp_ctrl_ptr->u8PwmAdj > 5) temp_ctrl_ptr->u8PwmAdj-=5; } } else if( mid_fTem2 fSpeed ){//如果变温速度太慢,占空比自加1 if(temp_ctrl_ptr->u8PwmAdj u8PwmAdj+=5; } } /*--------------如果在降温控制进行PID-----------------------*/ else if(temp_ctrl_ptr->u8HotCool_En == 0X02 ){ if(mid_fTem2 > temp_ctrl_ptr->fSpeed ){//如果变温速度太快,占空比自+1 if(temp_ctrl_ptr->u8PwmAdj u8PwmAdj+=5; } else if( mid_fTem2 fSpeed ){//如果变温速度太慢,占空比自-1 if(temp_ctrl_ptr->u8PwmAdj > 0) temp_ctrl_ptr->u8PwmAdj--; } } /*--------------如果加热方向降温无法到达目标速度,则需要制冷加速降温 -------------*/ if(temp_ctrl_ptr->u8PwmAdj == 0){//如果PWM已经减至0 if( temp_pid_ptr->Err u8PwmDir ++ ; if(temp_ctrl_ptr->u8PwmDir >= 20){ temp_ctrl_ptr->state = 0X02;//跳转至状态2,进行制冷降温 break; } } } else temp_ctrl_ptr->u8PwmDir =0; /*--------------如果温差小于2℃,则进入PID控制 case 0X03 -----------------------*/ //mid_fTem3 = (float)fabs(temp_pid_ptr->Err[chn]);//求出温差绝对值 /*--------------如果在升温控制中-----------------------*/ if(temp_ctrl_ptr->u8HotCool_En == 0X01 ){ /*--------------如果实际温度超过目标温度,则进入PID控制 case 0X03 -----------------------*/ if( temp_pid_ptr->Err state = 0X03;//跳转至状态3,进行PID控制 // pwm_save = temp_ctrl_ptr->u8PwmAdj; temp_pid_ptr->integral = pwm_96_save; break; } } /*--------------如果在降温控制中-----------------------*/ else if(temp_ctrl_ptr->u8HotCool_En == 0X02 ){ /*--------------如果实际温度低于目标温度,则进入PID控制 case 0X03 -----------------------*/ if( temp_pid_ptr->Err >= 0.5 ){ temp_ctrl_ptr->state = 0X03;//跳转至状态3,进行PID控制 temp_pid_ptr->integral = pwm_57_save; // pwm_save = temp_ctrl_ptr->u8PwmAdj; break; } } tec_drv_pwm(chn, TEC_HEAT,temp_ctrl_ptr->u8PwmAdj); //序号,加热标志,占空比; temp_pid_ptr->Err_Last = temp_pid_ptr->Err; //上一次的偏差值 float temp = tec_temp.fTemp[chn];; if( temp>=0 ){ temppid_segger_log("CHN%d %d %d %d.%d \r" ,chn+1, temp_ctrl_ptr->state , tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } else{ temp *= -1; temppid_segger_log("CHN%d %d %d -%d.%d \r" ,chn+1, temp_ctrl_ptr->state ,tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } /*--------------如果有触发PID状态跳转 -----------------------*/ // if(temp_ctrl_ptr->u8PidStateFlag == 1){ // temp_ctrl_ptr->state = 0X00;//跳转至状态0 // tec_drv_pwm(chn, TEC_CLOSE, 0); //序号,关闭标志,占空比; // temp_ctrl_ptr->u8PidStateFlag = 1 ; // } break; } case 0X02 ://state-2:制冷降温状态 { temp_pid_ptr->Err = temp_pid_ptr->SetTemperature - temp_pid_ptr->ActTemperature;//当前目标温度与实际温度差 /*---------------速度自动调节 ----------------------------------------------*/ mid_fTem1 = ( temp_pid_ptr->Err_Last - temp_pid_ptr->Err ) * (PID_PRE) ;//计算变温速度/50MS计算1次/单位:℃/S mid_fTem1 = (float)fabs(mid_fTem1);//求出速度绝对值 if(mid_fTem1 > temp_ctrl_ptr->fSpeed ){//如果变温速度太快,占空比自减1 if(temp_ctrl_ptr->u8PwmAdj > 0) temp_ctrl_ptr->u8PwmAdj--; } else if( mid_fTem1 fSpeed ){//如果变温速度太慢,占空比自加1 if(temp_ctrl_ptr->u8PwmAdj u8PwmAdj++; } /*--------------如果温差小于2℃,则进入PID控制 case 0X03 -----------------------*/ mid_fTem2 = (float)fabs(temp_pid_ptr->Err);//求出温差绝对值 if(mid_fTem2 state = 0X03;//跳转至状态3,进行PID控制 temp_pid_ptr->integral = pwm_57_save; break; } tec_drv_pwm(chn, TEC_COOL, temp_ctrl_ptr->u8PwmAdj); //序号,制冷标志,占空比; temp_pid_ptr->Err_Last = temp_pid_ptr->Err; //上一次的偏差值 float temp = tec_temp.fTemp[chn];; if( temp>=0 ){ temppid_segger_log("CHN%d %d %d %d.%d \r" ,chn+1, temp_ctrl_ptr->state , tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } else{ temp *= -1; temppid_segger_log("CHN%d %d %d -%d.%d \r" ,chn+1, temp_ctrl_ptr->state ,tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } /*--------------如果有触发PID状态跳转 -----------------------*/ // if(temp_ctrl_ptr->u8PidStateFlag == 1){ // temp_ctrl_ptr->state = 0X00;//跳转至状态0 // tec_drv_pwm(chn, TEC_CLOSE, 0); //序号,关闭标志,占空比; // temp_ctrl_ptr->u8PidStateFlag = 1 ; // } break; } case 0X03 ://state-3:PID温控状态 { temp_pid_ptr->Err = temp_pid_ptr->SetTemperature - temp_pid_ptr->ActTemperature;//当前目标温度与实际温度差 /*--------------判断通道是否到达目标温度,偏差为0.1℃-----------------------*/ if(temp_pid_ptr->Err Err >= -0.1){ temp_ctrl_ptr->u8Channel_Done = 1; } /*--------------如果在升温控制进行PID-----------------------*/ if(temp_ctrl_ptr->u8HotCool_En == 0X01 ){ temp_pid_ptr->integral += temp_pid_ptr->Err; //积分偏差累加,刚开始为正数 mid_fTem1 = temp_pid_ptr->Err - temp_pid_ptr->Err_Last;//差分变化值,当前值减上次值,刚开始为负数 if(mid_fTem1>=0 && temp_pid_ptr->Err>=0)//出现降温且还没有达到目标温度 mid_fTem2=60.0; else if(mid_fTem1u8PwmCoe = temp_adj_factor(temp_pid_ptr->SetTemperature );//获取调整系数 mid_fPWM = syscfg_ptr()->temp_pid_para.kpid_warm.kp*temp_pid_ptr->Err + \ syscfg_ptr()->temp_pid_para.kpid_warm.ki*temp_pid_ptr->integral + \ mid_fTem2* mid_fTem1 + temp_ctrl_ptr->u8PwmCoe; if(mid_fPWM >= PWM_RANG) mid_fPWM = PWM_RANG; if(mid_fPWM u8PwmAdj = (uint16_t)mid_fPWM;//赋值PWM占空比 // if( mid_fPWM < pwm_save-50 ){ // tec_drv_pwm(chn, TEC_HEAT, pwm_save); //序号,加热标志,占空比; // } // else{ tec_drv_pwm(chn, TEC_HEAT, temp_ctrl_ptr->u8PwmAdj); //序号,加热标志,占空比; // pwm_save = 0; // } temp_pid_ptr->Err_Last = temp_pid_ptr->Err; //上一次的偏差值 temppid_segger_log("CHN%d %d %d\r" ,chn+1, temp_ctrl_ptr->u8PwmAdj,temp_ctrl_ptr->u8PwmCoe ); float temp = tec_temp.fTemp[chn];; if( temp>=0 ){ temppid_segger_log("CHN%d %d %d %d.%d \r" ,chn+1, temp_ctrl_ptr->state , tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } else{ temp *= -1; temppid_segger_log("CHN%d %d %d -%d.%d \r" ,chn+1, temp_ctrl_ptr->state ,tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } } /*--------------如果在降温控制进行PID-----------------------*/ else if(temp_ctrl_ptr->u8HotCool_En == 0X02 ){ /*--------------如果环境温度大于目标温度需要进行制冷-----------------------*/ if( TEMP_ENV >= temp_pid_ptr->SetTemperature){ temp_pid_ptr->integral += temp_pid_ptr->Err; //积分偏差累加 mid_fPWM = syscfg_ptr()->temp_pid_para.kpid_cool_below_env.kp*( -temp_pid_ptr->Err) + \ syscfg_ptr()->temp_pid_para.kpid_cool_below_env.kp * ( -temp_pid_ptr->integral) ; temp_ctrl_ptr->u8PwmAdj = (uint16_t)mid_fPWM;//赋值PWM占空比 tec_drv_pwm(chn, TEC_COOL, temp_ctrl_ptr->u8PwmAdj); //序号,制冷标志,占空比; temp_pid_ptr->Err_Last = temp_pid_ptr->Err; //上一次的偏差值 float temp = tec_temp.fTemp[chn];; if( temp>=0 ){ temppid_segger_log("CHN%d %d %d %d.%d \r" ,chn+1, temp_ctrl_ptr->state , tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } else{ temp *= -1; temppid_segger_log("CHN%d %d %d -%d.%d \r" ,chn+1, temp_ctrl_ptr->state ,tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } } /*--------------如果环境温度小于目标温度需要进行加热-----------------------*/ else{ temp_pid_ptr->integral += temp_pid_ptr->Err; //积分偏差累加 temp_ctrl_ptr->u8PwmCoe = temp_adj_factor(temp_pid_ptr->SetTemperature );//获取调整系数 mid_fPWM = syscfg_ptr()->temp_pid_para.kpid_cool_above_env.kp*(temp_pid_ptr->Err) + \ syscfg_ptr()->temp_pid_para.kpid_cool_above_env.ki * (temp_pid_ptr->integral) + \ temp_ctrl_ptr->u8PwmCoe; if(mid_fPWM >=PWM_RANG) mid_fPWM=PWM_RANG; if(mid_fPWM u8PwmAdj = (uint16_t)mid_fPWM;//赋值PWM占空比 tec_drv_pwm(chn, TEC_HEAT, temp_ctrl_ptr->u8PwmAdj); //序号,加热标志,占空比; temp_pid_ptr->Err_Last = temp_pid_ptr->Err; //上一次的偏差值 float temp = tec_temp.fTemp[chn];; if( temp>=0 ){ temppid_segger_log("CHN%d %d %d %d.%d \r" ,chn+1, temp_ctrl_ptr->state , tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } else{ temp *= -1; temppid_segger_log("CHN%d %d %d -%d.%d \r" ,chn+1, temp_ctrl_ptr->state ,tec_driver_pwm(chn)->u8StepH_Cnt , (int)temp, (int)((temp-(int)temp)*100) ); } } } //如果有触发PID状态跳转 // if(temp_ctrl_ptr->u8PidStateFlag == 1){ // temp_ctrl_ptr->state = 0X00;//跳转至状态0 // tec_drv_pwm(chn, TEC_CLOSE, 0); //序号,关闭标志,占空比; // temp_ctrl_ptr->u8PidStateFlag = 0 ; // } break; } default : break; } }

算法分三部分,主要实现定时匀速升温,定时匀速降温,指定温度降,升温与降温不能产生太大过冲,恒温精度高

以下为实验实测视频,目标温度不要求精准可通过校准实现偏差修正,主要实现温度稳定

95度恒温

升降温曲线实现



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3