最近做了一个数字电源,本意是使用单片机控制PFC。这个问题的现象引起我对软件程序容错性的思考。
软件的容错性:当硬件故障的时候,程序不跑飞的能力。
目前就有这样的一个案例,它的逻辑代码是这样的:
通过检测输入电压的过零点,然后每检测到一个过零点,计数值重置为零,否则再定时器中断里面递增。
硬件电路:
分析:
交流电是50Hz,也就是100个过零点。每两个周期是10ms。受电网供电质量与硬件电路的延时的影响,送到单片机的过零检测波形会有一点点的不对称。
理想情况下,Vac2_AD处的波形应该是占空比为50%的方波。
现实情况下,受电网供电质量的影响、Q5的影响,Vac2_AD的波形不是50%。
程序实现:
//Calculate the input current reference for (i = 0 ; i < 1000; i++){ I_ref[i] = (32767*sin(pi/1000.0f*i)+0.5f); } //每次检测到Vac2_AD波形的边沿,计数值Count置零。 void __attribute__ ((__interrupt__,__no_auto_psv__)) _CNInterrupt(void){ IFS1bits.CNIF = 0; //Clear the interrupt flag Count = 0; ADCPC0bits.SWTRG1 = 1; } //定时器10us,递增一次。 Count++; IL1_Err = I_ref[Count] - IL1_Real;
上面程序是在理想的情况下,Count是在小于1000的情况下,每次计数到1000,也就是10ms,外部刚好检测到过零点,Count又被置零。
那么,当检测外部过零点延时到来的时候,Count>1000,那么数组溢出,I_ref[1500]是一个随机数,程序跑飞。
下面的程序将Count取余,并且在20ms,才置零一次。提高了程序的容错性。
//Calculate the input current reference for (i = 0 ; i < 1000; i++){ I_ref[i] = (32767*sin(pi/1000.0f*i)+0.5f); } //每次检测到Vac2_AD波形的边沿,计数值Count置零。 void __attribute__ ((__interrupt__,__no_auto_psv__)) _CNInterrupt(void){ IFS1bits.CNIF = 0; //Clear the interrupt flag if(Count > 1980)Count = 0; ADCPC0bits.SWTRG1 = 1; } //定时器10us,递增一次。 Count++; IL1_Err = I_ref[Count%1000] - IL1_Real;
实验验证:
分别将上述代码,在 Boost PFC程序中验证。
代码一:存在输入电流正负半周不对称的情况。(负半周期的I_ref不正常,错位和溢出)
代码二:正负半周对称。
数字电源,控制不仅仅要考虑到程序逻辑的正确性,程序的容错性也是在设计需要考虑的问题。