

/*
 * 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;
}

