/* * usr_gpio.c * * Created on: 2022年4月11日 * Author: amos */ #include "onechip_include_header.h" extern uint32_t conter100ms; extern uint32_t conter10ms; #define MIN_TEMPERATUARE 5 #define MAX_TEMPERATUARE 120 #define COOL_WORK_THD 5 #define HEAT_WORK_THD 2.5 #define COOL_TEST_TIME 30 #define HEAT_TEST_TIME 6000 #define COOL_TEST_PWR -50 #define HEAT_TEST_PWR 50 #define THERM_ADC_CHN 5 #define OVER_HEAT_EDGE 0.5 #define HEAT_STABLE_TIME 300 #define MAX_REMOVE_GAP 100 #define EER_NOEXIST_TIME_GAP 500 #define HEAT_ARRIVE_EDGE 0.5 #define GOTO_IDLE_GAP 3000 typedef enum Heat_state { PID_IDLE, PID_OVERHEAT, PID_OVERHEATLAST, PID_OVERCOOL, PID_OVERCOOLLAST, PID_ADJ, PID_STAB, PID_ERROR, } pid_state_def; typedef enum { THERMOSTAT_NOR, // 正常 THERMOSTAT_COOL_EER, //制冷坏 THERMOSTAT_HEAT_EER, // 加热坏 THERMOSTAT_SENSER_EER, // 传感器坏 THERMOSTAT_TUBEEXIST_EER, //存在试管 THERMOSTAT_TUBENOEXIST_EER, //不存在试管 } THERMOSTAT_ERR_State; typedef enum THERMO_state { THERMOSTAT_PWRON, THERMOSTAT_CHECK, THERMOSTAT_WARM, THERMOSTAT_IDLE, THERMOSTAT_INSERT, THERMOSTAT_NOTICE, THERMOSTAT_WORK, THERMOSTAT_END, THERMOSTAT_ERROR, } thermostat_state_def; typedef struct { float realtemp; float goal; float offset; float overHeat; float overHeatTime; float overCool; float overCoolTime; float idletemp; float worktime; float err; float err_last; float Kp,Ki,Kd; float variate; float integral; float cabinTem; pid_state_def pid_st; unsigned int pid_stable; unsigned int pid_stable_time; thermostat_state_def thermostat_st; THERMOSTAT_ERR_State eerst; }PID_def; int32_t tupeExist = 0; int32_t ylsis_stFistin; PID_def therm; extern void light_band_set(uint8_t mode_select, uint16_t speed_ms, uint32_t rgb_color); volatile uint32_t g_u32AdcIntFlag; //adc simple finish flag int32_t recGoalFlag = 0; uint32_t Read_Tupe(void) { return (HAL_GPIO_ReadPin(MINI7_V2_TUBE_SW_GPIO_Port,MINI7_V2_TUBE_SW_Pin)) ? 1 : 0; // 检查PF5引脚值 } /** * @brief SetMotorPwm * * @param value between 0-100 * * @return None * * @details */ void SetThermPwm( int32_t value) { /* Start PWM counter */ } void updatParm_therm(void) { therm.offset = sysinf.lysis_offset; therm.overHeat = sysinf.lysis_overHeat; therm.overHeatTime = sysinf.lysis_overHeatTime; therm.Kp = sysinf.lysis_Kp; therm.Ki = sysinf.lysis_Ki ; therm.Kd = sysinf.lysis_Kd; } void NTCGetVoltage(float *ActualTemp) { int32_t i32ConversionData; float NTCVoltage; float Rt=0; //NTC电阻 float R=10000; //10K固定阻值电阻 float T0=273.15+25; //转换为开尔文温度 //float B=3950; //B值 25° float B=3980; //B值 >50° float Ka=273.15; //K值 float temp; float VR=0; //电压值 /* Get the conversion result */ // i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, THERM_ADC_CHN); NTCVoltage=(i32ConversionData*3300/4096); VR=NTCVoltage/1000.00; Rt=8.05664*i32ConversionData; temp=1/(1/T0+log(Rt/R)/B)-Ka+0.3; //计算温度 *ActualTemp=temp; } float PIDRealize(PID_def *pid) { pid->err=pid->goal-pid->realtemp; pid->variate=pid->Kp*pid->err+pid->Ki*pid->integral+pid->Kd*(pid->err-pid->err_last); pid->err_last=pid->err; if(pid->variate>100) { pid->variate=100; }else{ pid->integral+=pid->err; } if(pid->variate<0) { pid->variate=0; } return pid->variate; } /** * @brief Motor_Init * * @param init key and optic input * * @return 0正常,1不能加热,2,不能制冷,3 传感器异常 * * @details 上电,通过设置加热制冷,判断温度变化。 */ uint32_t Therm_Check(void) { float firstTemp,heattemp; NTCGetVoltage(&firstTemp); if(firstTemp < MIN_TEMPERATUARE || firstTemp > MAX_TEMPERATUARE){ SetThermPwm(0); return THERMOSTAT_SENSER_EER; } SetThermPwm(HEAT_TEST_PWR); HAL_Delay(HEAT_TEST_TIME); NTCGetVoltage(&heattemp); SetThermPwm(0); if((heattemp - firstTemp) < HEAT_WORK_THD){ return THERMOSTAT_HEAT_EER; } return THERMOSTAT_NOR; } /** * @brief Set_therm * * @param goal 目标温度 * * @return 无 * * @details 设置目标温度。 */ void Set_therm(float goal) { therm.goal = goal; if(goal > (therm.overHeat + therm.realtemp )){ therm.pid_st = PID_OVERHEAT; therm.goal += therm.overHeat; }else{ therm.pid_st = PID_ADJ; } therm.integral = 0; therm.pid_stable = 0; } void Close_therm(float goal) { therm.pid_st = PID_IDLE; therm.integral = 0; therm.pid_stable = 0; SetThermPwm(0); } /** * @brief Therm_work * * @param adjflag 调节标记 * * * * @details 温控器调节。 */ uint32_t Pid_work(void) { static uint32_t chrConter = 0; float temp; PID_def *ptherm = &therm; NTCGetVoltage(&temp); ptherm->realtemp = temp + ptherm->offset; switch(ptherm->pid_st){ case PID_OVERHEAT:{ PIDRealize(ptherm); if (ptherm->realtemp > (ptherm->goal - OVER_HEAT_EDGE)){ ptherm->pid_st = PID_OVERHEATLAST; chrConter = 0; } }break; case PID_OVERHEATLAST:{ chrConter ++; if (chrConter > ptherm->overHeatTime){ ptherm->pid_st = PID_ADJ; /*PID功率值维持不变*/ ptherm->integral = (ptherm->overHeat*ptherm->Kp)/ptherm->Ki; ptherm->integral += (ptherm->variate)/ptherm->Ki; therm.goal -= therm.overHeat; chrConter = 0; } }break; case PID_ADJ:{ PIDRealize(ptherm); if ((ptherm->realtemp > (ptherm->goal - OVER_HEAT_EDGE)) && (ptherm->realtemp < (ptherm->goal + OVER_HEAT_EDGE))){ if(chrConter < HEAT_STABLE_TIME){ chrConter ++; } else{ /*上报加热稳定*/ ptherm->pid_stable = 1; } }else{ if(chrConter){chrConter--;} else{ptherm->pid_stable = 0;} } }break; default: ptherm->pid_st = PID_IDLE; ptherm->variate = 0; break; } SetThermPwm(ptherm->variate); // char data[20]; // *(int *)(data+0) = ptherm->thermostat_st; // *(float *)(data+4) = ptherm->realtemp; // *(float *)(data+8) = ptherm->variate; // *(float *)(data+12) = ptherm->integral; // *(float *)(data+16) = ptherm->err; // b2b_send_to_pc(PC_CMD_DATASCOPE, data, sizeof(data)); return 0; } uint32_t Therm_updat_work(void) { PID_def *ptherm = &therm; char data[20]; *(int *)(data+0) = (ptherm->pid_st + (ptherm->thermostat_st << 8)); *(float *)(data+4) = ptherm->realtemp; *(float *)(data+8) = ptherm->variate; *(float *)(data+12) = ptherm->integral; *(float *)(data+16) = ptherm->err; // b2b_send_device(B2B_CMD_DATASCOPE, data, sizeof(data),0); return 0; } uint32_t Therm_work(void) { float temp; static uint32_t last10ms; PID_def *ptherm = &therm; NTCGetVoltage(&temp); ptherm->realtemp = temp + ptherm->offset; switch(ptherm->thermostat_st){ case THERMOSTAT_PWRON:{ static float firstTemp; if(ylsis_stFistin){ ylsis_stFistin = false; sysinf.lysisState = SYS_STATE_PREPARE; NTCGetVoltage(&firstTemp); if(firstTemp < MIN_TEMPERATUARE || firstTemp > MAX_TEMPERATUARE){ error_set(ERROR_TEMPSENSOR_EER); ptherm->thermostat_st = THERMOSTAT_ERROR; ylsis_stFistin = true; }else{ Set_therm(firstTemp+30); last10ms = conter10ms; } }else{ float heattemp; NTCGetVoltage(&heattemp); if((heattemp - firstTemp) > HEAT_WORK_THD){ ptherm->thermostat_st = THERMOSTAT_WARM; ylsis_stFistin = true; ptherm->pid_st = PID_IDLE; } if((conter10ms-last10ms)> HEAT_TEST_TIME){ /*超时判断*/ ptherm->thermostat_st = THERMOSTAT_ERROR; sysinf.lysisState = SYS_STATE_ERROR_HW; error_set(ERROR_HEATFUC_EER); ylsis_stFistin = true; } } }break; case THERMOSTAT_NOTICE:{ if(ylsis_stFistin){ /*上电或者预热状态存在管管,停止加热*/ sysinf.lysisState = SYS_STATE_ERROR_HW; error_set(ERROR_TUPE_EXIST); Set_therm( 0); ylsis_stFistin = false; }else{ if(Read_Tupe() == 0){ /*管管移除,进入到预热状态*/ ptherm->thermostat_st = THERMOSTAT_WARM; error_clear(); ylsis_stFistin = true; } } }break; case THERMOSTAT_WARM:{ if(ylsis_stFistin){ sysinf.lysisState = SYS_STATE_PREPARE; ylsis_stFistin = false; if(ptherm->idletemp < 0.1){ /*预热参数配置为0,无需要预热*/ ptherm->thermostat_st = THERMOSTAT_IDLE; ylsis_stFistin = true; }else{ Set_therm(ptherm->idletemp); } }else{ /*预热到位,进入空闲状态*/ if(ptherm->realtemp > (ptherm->idletemp - HEAT_ARRIVE_EDGE)){ ptherm->thermostat_st = THERMOSTAT_IDLE; ylsis_stFistin = true; } // if(Read_Tupe()){ // /*预热插管管,进入提示状态*/ // ptherm->thermostat_st = THERMOSTAT_NOTICE; // ylsis_stFistin = TRUE; // } } }break; case THERMOSTAT_IDLE:{ if(ylsis_stFistin){ sysinf.lysisState = SYS_STATE_READY; ylsis_stFistin = false; Close_therm(0); recGoalFlag = 0; }else{ if(recGoalFlag){ Set_therm(ptherm->goal); recGoalFlag = 0; } if(ptherm->pid_stable){ ptherm->thermostat_st = THERMOSTAT_INSERT; ylsis_stFistin = true; } // if(Read_Tupe()){ // /*预热插管管,进入提示状态*/ // ptherm->thermostat_st = THERMOSTAT_NOTICE; // ylsis_stFistin = TRUE; // } } }break; case THERMOSTAT_INSERT:{ if(ylsis_stFistin){ sysinf.lysisState = SYS_STATE_CHECK; ylsis_stFistin = false; }else{ if(Read_Tupe()){ ptherm->thermostat_st = THERMOSTAT_WORK; ylsis_stFistin = true; } } }break; case THERMOSTAT_WORK:{ if(ylsis_stFistin){ sysinf.lysisState = SYS_STATE_RUNING; ylsis_stFistin = false; ptherm->pid_stable_time = 0; }else{ // if(Read_Tupe()){ // last10ms = conter10ms; // }else{ // if((conter10ms-last10ms)> MAX_REMOVE_GAP){ // Close_therm(0); // ptherm->eerst = THERMOSTAT_TUBENOEXIST_EER; // ptherm->thermostat_st = THERMOSTAT_ERROR; // error_set(ERROR_TUPE_MOVE); // last10ms = conter10ms; // ylsis_stFistin = TRUE; // } // } // if(ptherm->pid_stable) { ptherm->pid_stable_time ++; if(ptherm->pid_stable_time > ptherm->worktime){ ptherm->thermostat_st = THERMOSTAT_END; ylsis_stFistin = true; } } } }break; case THERMOSTAT_END:{ if(ylsis_stFistin){ sysinf.lysisState = SYS_STATE_WORKEND; ylsis_stFistin = false; Close_therm(0); last10ms = conter10ms; }else{ if((conter10ms-last10ms)> GOTO_IDLE_GAP){ // if(Read_Tupe() == 0){ /*管管移除,进入到预热状态*/ ptherm->thermostat_st = THERMOSTAT_WARM; ylsis_stFistin = true; } } }break; case THERMOSTAT_ERROR:{ if(ylsis_stFistin){ ylsis_stFistin = false; Close_therm(0); }else{ if(ptherm->eerst == THERMOSTAT_TUBENOEXIST_EER){ if((conter10ms-last10ms)> EER_NOEXIST_TIME_GAP){ ptherm->thermostat_st = THERMOSTAT_IDLE; error_clear(); ylsis_stFistin = true; } } } }break; } Pid_work(); return 0; } uint32_t Close_Therm_work(void) { PID_def *ptherm = &therm; ptherm->thermostat_st = THERMOSTAT_END; ylsis_stFistin = true; return 0; }