低压降频的处理逻辑
1:ADC判断临界物理值是否达到---多次检测滤波->设定状态
2:进入状态后进行阶梯递减或者差值递减,使用一个系数作为PWM的阶梯值接口
3:计算出降额系数,应用到PWM

设一灯板小于7.5V进入低压保护灭灯,大于8.5V退出保护重新亮灯
大于19V进行过压保护灭灯
检测电压低于10V,持续时间大于1000ms开始进行电压降额,100ms调整一次,每次不超过3%

需要注意

1:灯亮时会分压,实际的阀值电压可能需要实测调整

 2:万一灯碰到临界值后开始降额后,电流下降,检测电压上升,恢复到临界值以上,是否会导致暗--亮--暗持续闪烁,可以考虑加入类似噪声桶的区间放大这个闪烁临界值的两端

3:不同的动画分压不同,检测电压的实际补偿值不同,需要实测修改

4:当前的降额步幅是否会导致降额时看起来闪烁

#define POWER_DIAG_TICK (50)
#define POWER_DIAG_TIME (500)

#define MAX_UP_PART_FROM_VOLT		 50       // 低压降额的最大次数
#define ONCE_UP_VAL_FROM_VOLT		 1.0      // 单次电压降额比例
// ------此部分临界值由灯板外接电压表调试得出
//#define OVER_MAX_POWER 17.8f   // 19.0补偿为18.5   过压保护值,过压19.0持续时间大于100ms 关闭格栅灯
#define HIGH_POWER_RECOVER 17.0f   // 18补偿为17.5 过压恢复值,恢复格栅灯
#define OVER_LOW_POWER 7.5f	   // 欠压保护值 小于后关闭格栅灯
#define LOW_POWER_RECOVER 8.55f // 欠压后恢复到大于8.5V时,恢复欠压保护,格栅灯开启
#define TO_DOWN_POWER 9.85f	   // 小于10V电压开始降额

static int up_part_from_Volt = 0;
float up_pwm_From_Volt = 0;
float up_pwm_From_Volt_and_Temp = 1;
 
static uint8_t power_check_counter = 0;

static char BOR_Adc_Low_Count_Off = 0;
static char BOR_Adc_Low_Count_On = 0;
static char BOR_Adc_High_Count_Off = 0;
static char BOR_Adc_High_Count_On = 0;
static char Voltage_Derating_Count = 0;

char POWER_IS_LESS_than_10V = 0;

extern float up_pwm_From_Temp;
typedef enum
{
	POWER_IS_DEFAULT = 0,				// 默认
	POWER_IS_LOW_PROTECT ,				// 低压保护状态	
	POWER_IS_LOW_RECOVER,				// 低压恢复状态
	POWER_IS_HIGH_PROTECT,				// 高压保护状态
	POWER_IS_HIGH_RECOVER,				// 高压恢复状态
	POWER_STATE_MAX ,
}Power_state_e;
Power_state_e POWER_state = POWER_IS_DEFAULT;

typedef enum
{
	VOLT_IS_DEFAULT = 0,				// 电压默认状态,不降额,如果已经降额开始恢复
	VOLT_IS_LESS_than_10V 				// 电压小于10V,开始降额
}Voltage_Derating_state_e;
Voltage_Derating_state_e Volt_state = VOLT_IS_DEFAULT;




/*
==================================================================
*函 数 名:Power_MainFunc
*功能描述:电源ADC检测
           50ms检测一次,10次放到数组里,后续进行滤波算法后给出电压值
		   其间100ms和500ms分别执行降额动作和更新温度值
		   如果当前在执行动画,给出电压值会加上不同动画的补偿值
*输入参数: 
*返 回 值: 
*日    期:2024/3/12
*修改记录:
==================================================================
*/ 
#define N 10
uint16_t power_adc_val[N];
float powerVolt=0;
void Power_MainFunc(void)
{
	float pop;
//	float powerVolt;
	uint16_t adc_v = 0;	
	power_adc_val[power_check_counter] = ADC_GetArray(POWER_CHECK_SEQ);		//每50ms采样填充数据到数组里面
	
	power_check_counter++;
	
	if(power_check_counter %2 == 0 && (power_check_counter!=0)) // 每100ms降额一次
	{
		do_Voltage_Derating();
	}
	
//  累加值10次后求均值,相当于每500ms才做后面的判断
	if (power_check_counter >= (POWER_DIAG_TIME / POWER_DIAG_TICK)) // 500ms执行一次
	{
		power_check_counter = 0;
		
		adc_v = middleAverageFilter(&power_adc_val[0]);
		
		pop = (float)adc_v * 5.0f / 4096;  // 采样参考电压

		powerVolt = pop * 5.70f ;
		
		if(!light_mode_is_idle() )
		{
			switch(light_curr_mode())
			{	
				case AAA:  powerVolt += 0.2f;	break;			// 动画A   		
				case BBB: powerVolt += 0.2f;	break; 			// 动画B
	
			}
		}			
		Voltage_H_L_Protection(powerVolt);  // 高低压保护设置状态以及灭灯	
		Voltage_Derating_state(powerVolt);	// 判断是否满足降额条件设置状态
	}
	else
	{
		return;
	}
}
/*
==================================================================
*函 数 名:Voltage_H_L_Protection
*功能描述:判断传入电压条件 是否进行执行过欠压保护动作     
*输入参数:滤波后的电压值 
*返 回 值: 
*日    期:2024/3/12
*修改记录:
==================================================================
*/ 
float over_max_power = 18.5f;
void Voltage_H_L_Protection(float powerVolt)
{
	
// <7.5低压保护
	if(powerVolt < OVER_LOW_POWER)
	{
		BOR_Adc_Low_Count_Off++;
		if(BOR_Adc_Low_Count_Off >= 1)						// 进来直接设置为低压状态
		{
			 BOR_Adc_Low_Count_Off = 0;
			if(POWER_state != POWER_IS_LOW_PROTECT)		
			{
				POWER_state = POWER_IS_LOW_PROTECT;				// 设置为低压保护状态
				light_mode_stop();                               // 直接使能灭灯
				light_ctrl_on(0);
			}
		}	
	}
	else
    {
        BOR_Adc_Low_Count_Off = 0;							// 正常电压就清除计数器 去抖动
    }
// 7.5低压保护 ----> 8.5恢复	
	if(powerVolt >= LOW_POWER_RECOVER)
	{
		BOR_Adc_Low_Count_On++;
		if(BOR_Adc_Low_Count_On >= 1)			 						
		{
			 BOR_Adc_Low_Count_On = 0;
			if(POWER_state == POWER_IS_LOW_PROTECT)			// 如果之前是低压保护状态,设置为低压恢复状态
			{
				POWER_state = POWER_IS_LOW_RECOVER;
			}	
		}	
	}	
	else
    {
        BOR_Adc_Low_Count_On = 0;									 	
    }	
	
	

// 不同动画模式的过压保护值	
	if (powerVolt > 15) 	//电压大于15才判断过压							 
	{
		if(!light_mode_is_idle() )
		{	
			switch(light_curr_mode())
			{	
				case AAA :  over_max_power = 17.7f;	break;			    		 
				case BBB: over_max_power = 17.8f;	break;		 
 
			}	
		}
	}
// >19高压保护	
	if (powerVolt > over_max_power) 								 
	{
		BOR_Adc_High_Count_Off++;
		if(BOR_Adc_High_Count_Off >= 1)						// 高压直接进来				
		{
			 BOR_Adc_High_Count_Off = 0;
			if(POWER_state != POWER_IS_HIGH_PROTECT)		
			{
				POWER_state = POWER_IS_HIGH_PROTECT;
				light_mode_stop();
				light_ctrl_on(0);				
			}
		}	
	}
	else
    {
        BOR_Adc_High_Count_Off = 0;									 
    }
	
	
	
// 高压保护--->恢复
	if(powerVolt <= HIGH_POWER_RECOVER)
	{
		BOR_Adc_High_Count_On++;
		if(BOR_Adc_High_Count_On >= 1)			 						
		{
			 BOR_Adc_High_Count_On = 0;
			if(POWER_state == POWER_IS_HIGH_PROTECT)					
			{
				POWER_state = POWER_IS_HIGH_RECOVER;
			}	
		}	
	}	
	else
    {
        BOR_Adc_High_Count_On = 0;									 	
    }	
	
 
}

/*
==================================================================
*函 数 名:Voltage_Derating_state
*功能描述:判断传入电压条件 是否满足电压降额条件       
		   Volt_state全局变量    给出电压是否小于10V的判断,后续通过此标志做降额动作
*输入参数:滤波后的电压值  
*返 回 值: 
*日    期:2024/3/12
*修改记录:
==================================================================
*/ 
void Voltage_Derating_state(float adcVolt)
{
//	powerVolt = (powerVolt * 5.0f / 4096) * 5.7; 
	if(adcVolt < TO_DOWN_POWER)							// 根据ADC判断是否 <10V  这里500ms进来一次
	{
		Voltage_Derating_Count++;
		if(Voltage_Derating_Count >= 2)					// 次数持续2次=1000ms进来					 
		{
			 Voltage_Derating_Count = 0;
			if(Volt_state != VOLT_IS_LESS_than_10V)		
			{
				Volt_state = VOLT_IS_LESS_than_10V;			 // 改状态为 降额状态
			}
		}	
	}
	else if(adcVolt >TO_DOWN_POWER +0.6f)					// 正常电压回复条件__大于抖动筒上部分==0.6V
    {
		Volt_state = VOLT_IS_DEFAULT;						// 改状态为 正常状态
        Voltage_Derating_Count = 0;							 
    }
}
/*
==================================================================
*函 数 名:do_Voltage_Derating
*功能描述:进行电压降额具体动作,并限制最终范围符合标准  
		   
		   最终系数up_pwm_From_Volt_and_Temp累乘 温度和电压的合计值
*输入参数:
*返 回 值: 
*日    期:2024/3/12
*修改记录:
==================================================================
*/ 
void do_Voltage_Derating(void)
{
// 确定<10 执行降压降额策略	
	if (Volt_state == VOLT_IS_LESS_than_10V)
	{
		up_part_from_Volt++;
		if (up_part_from_Volt > MAX_UP_PART_FROM_VOLT)		
			up_part_from_Volt = MAX_UP_PART_FROM_VOLT; // 电压降额最大降 50%  即比例为设定值的1-50%
		up_pwm_From_Volt = 1.0f - (up_part_from_Volt * ONCE_UP_VAL_FROM_VOLT / 100.00);			//printf("电压低压,降额比例 %2.2f\r\n", up_pwm_From_Volt);
					
	}
	else
	{
		if(up_part_from_Volt >=1 )		up_part_from_Volt--;
		if(up_part_from_Volt < 0 )		up_part_from_Volt = 0;

		up_pwm_From_Volt = 1.0f - (up_part_from_Volt * ONCE_UP_VAL_FROM_VOLT / 100.00);			//printf("正常电压\r\n");
	}
	if (up_pwm_From_Volt < 0.50f)   up_pwm_From_Volt = 0.50f;
	if (up_pwm_From_Volt > 1.0f)	up_pwm_From_Volt = 1.0f;
	

	up_pwm_From_Volt_and_Temp = up_pwm_From_Volt * up_pwm_From_Temp;
//	up_pwm_From_Volt_and_Temp = up_pwm_From_Volt  ;
//	up_pwm_From_Volt_and_Temp = up_pwm_From_Temp  ;
	if (up_pwm_From_Volt_and_Temp <= 0.30f)				// 合计降额度系数最低不能低于30%
		up_pwm_From_Volt_and_Temp = 0.30f;

}



/*
==================================================================
*函 数 名:middleAverageFilter
*功能描述:中位平均值滤波   连续采样N个数据,去掉2个最大值和2个最小值然后计算N-4个数据的算术平均值
*输入参数:10空间数组的首地址
*返 回 值:滤波后的值    
*日    期:2024/3/12
*修改记录:
==================================================================
*/ 
uint16_t middleAverageFilter(uint16_t power_adc_val[])
{
   uint16_t i,j,k;
   uint16_t temp,sum = 0;
// 冒泡排序
   for(j = 0; j < N-1; ++j)
   {
	   for(k = 0; k < N-j-1; ++k)	
	   {
		   if(power_adc_val[k] > power_adc_val[k+1])
		   {
			   temp = power_adc_val[k];
			   power_adc_val[k] = power_adc_val[k+1];
			   power_adc_val[k+1] = temp;
							
		   }
	   }
   }
// 去2个最大 2个最小值
   for(i = 2; i < N-2; ++i)			
   {
	   sum += power_adc_val[i];
   }
   
// 返回去最大最小后的 平均值   
	return sum/(N-4);	   
	   
}


/*
==================================================================
*函 数 名:get_downed_PWM
*功能描述:把默认的PWM值*温度*电压降额系数
*输入参数:动画抠图时预设的PWM标准值 
*返 回 值:标准值*降额系数后的 PWM值
*日    期:2024/3/12
*修改记录:
==================================================================
*/
// 动画预设的PWM值 * 温度和电压降频后的系数
uint8_t get_downed_PWM(uint8_t cartoon_pwm)
{	
	if(up_pwm_From_Volt_and_Temp==1.0f)
	{
		return cartoon_pwm;
	}	
	return cartoon_pwm * up_pwm_From_Volt_and_Temp;
}