采用热量积累模型的反时限电源过流保护的思路、电路以及代码

我曾经设计过一个系统,这个系统中安装许多个分布的设备,所有设备都由一个总电源供电。

这个电源除了供电之后,还需要管理系统设计的工作状态。

因此,该电源内部集成了PIC16F1936处理器。通过该处理器进行状态管理以及故障保护。

对于电源,短路、过流、过压、过温等保护是至关重要的功能。

否则,电源非常容易被损坏。

在我设计的这个系统之前,公司的其它类似产品使用简单的阈值判断进行过流保护。

当检测到超过额定电流的1.2倍左右时,切断输出。

为什么不能用阈值判断法进行过流保护

这个做法最致命的缺点是,

1) 所有的电源都有一定的过流能力,只要散发的热量不超过其能承受的范围,短时间的过流没有任何问题。

2) 所有的设备的电源输入都连接了一些大电容,用于储能和去耦,上电瞬间,电源以比较大的电流向这些电容充电,由于系统中连接的设备数比较大,所有设备同时上电,充电电流可以超过额定电流的许多倍。

3) 设备上电时的电流并非一种非此即彼的二值曲线,而是一种动态变化的曲线,如下图:


采用热量积累模型的反时限电源过流保护的思路、电路以及代码

上电电流波形


如果按上电电流的峰值进行保护,则不能发挥电源的最大性能,使用系统中能连接的设备数减少。

如果按上电电流的中间值进行保护,有可能保护不及时,损坏电源;

什么是反时限保护

按照焦耳定律,电源所耗散的热量与负载电流的平方成正比。

如果电源允许的温升为一个固定值,则允许耗散的热量为固定值。根据下述关系式:

功率 P∝I*I,

热量Q=P*t∝I*I*t。

从而t∝Q/(I*I)。

可见,当Q固定时,I*I的数值越大,则t时间越小。

电流与保护时间的反时限关系曲线如下:


采用热量积累模型的反时限电源过流保护的思路、电路以及代码

过流的反时限保护曲线

基于上述的考虑,我在上设计了一套适合运行在ROM/RAM等都非常有限的PIC16F1936上的反时限过流保护的算法:

1)电路一如既往的简单,一个0.17R的负载电流采样电阻将电流转成电压之后,经过R/C组成的低通滤波器送入单片机AD口。


采用热量积累模型的反时限电源过流保护的思路、电路以及代码

电路原理图

2)考虑到RAM的限制,采用一个int型的变量(16bits)记录热量值,保护热量值设置为50000。

3)根据电源的过流特性,设计检测电流所得到的AD值与热量值的关系表,

已知AD值与电流关系为:0.17*I/3.3*4096。

每隔1ms采样AD并计算一次热量,

比如额定电流为1.2A的电源,当电流超过额定电流3倍,即3.6A时,立即保护。

ADC值大于760时,热量为50000。

过流2倍,ADC为506时,1.5 秒之后保护,热量为50000/1000/1.5=33。

过流1.5位, ADC为379时,2秒之后保护,热量为50000/1000/2=25。

依此类推,可以得到一个关系表。

单片机程序每隔1ms做一次AD转换,将转换到的AD做如下的逻辑处理:

如果大于760,将热量变量值置为50000。

如果在253与760之间,从上述的表中找到对应的数值加入到热量变量中。

如果小于253,则将热量变量值置为-5,使得电源能够在5秒之后尝试再次输出,同时在过流判断时,能够根据散热情况实现一些恢复的机制。

如果热量变量值大于等于50000,则断开输出,进入故障状态。

在故障状态,如果热量变量值减到0,则再次输出;

软件代码如下:

<code>osdet.adcres = convert();
	index = os_getindex(osdet.adcres);
        if(index >= TAB_NUM){
	     osdet.heatsum = HEATER_MAX;
             osdet.state =  STATE_OVER;
             
        }
        else
        {
            if(uidata < AD_OVERCURRENT)
            {
                minus = TRUE;
            }
            wtemp = pstab[index];
           
            if(flag)
            {
                if(minus)
                {
                    if( osdet.heatsum >= wtemp)
                    {
                         osdet.heatsum -= wtemp;
                    }
                    else
                    {
                         osdet.heatsum = 0;
                    }
                }
                else
                {
                    if((0xffff - wtemp) >  osdet.heatsum)
                    {
                         osdet.heatsum += wtemp;
                    }
                    else
                    {
                         osdet.heatsum = 0xffff;
                    }
                }
                
                if( osdet.heatsum >= HEATER_MAX)
                {
                     osdet.state = STATE_OVER;
                    
                }
            }
        }
/<code>


分享到:


相關文章: