採用熱量積累模型的反時限電源過流保護的思路、電路以及代碼

我曾經設計過一個系統,這個系統中安裝許多個分佈的設備,所有設備都由一個總電源供電。

這個電源除了供電之後,還需要管理系統設計的工作狀態。

因此,該電源內部集成了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>


分享到:


相關文章: