濾波器開發之三:基於算數平均的階進平滑濾波器

信號採集是非常常見的需求,我們也總是希望採集到的數據是純淨而真實的,但這只是我們的希望。環境中存在太多的干擾信號,爲了讓我們得到的數據儘可能地接近實際值,我們需要降低這些干擾信號的影響,於是就有了濾波器的用武之地。這裏我們討論的主要是軟件實現的數字濾波器,這一篇我們就來討論基於遞推算術平均算法的階進平滑濾波器。

1、問題的提出

前面一篇我們討論了同時提高靈敏度和濾波效果的方法,在通常情況下,都能達到比較理想的效果。不過在有些情況下,我們的採集對象會是處於一定的區間內,並且干擾信號也主要存在於這一區間內。也就是說干擾信號的幅值並不是很大,但持續存在;而被測信號也基本處於一個穩定的被測區間內。在這種情況下,被測信號越是處於目標範圍內,干擾的影響越是不可忽略。在這一篇中我們就來設計一種濾波算法實現這樣的需求。

首先,我們來分析一下,干擾信號較小,但持續不斷對最終數據有較大影響。因爲在有些應用中,當系統穩定時,採集的數據理論上來講是不應該出現很大波動的。基於這一點我們可以考慮對比本次採集與上次輸出之間的偏差值,如果偏差值大於一定的限值則我們認爲是數據發生了較大變化,遠大於干擾造成的影響,干擾可以忽略,所以我們直接對數據進行更新。當數據偏差處於一定的變化範圍之內時,但系統並未處於穩定狀態,但干擾信號已經不能完全忽略了,我們可以進行部分濾波處理。當數據偏差小於一定的值之後,我們認爲是處於穩定的範圍內,這時干擾造成的影響於數據的變化不能忽略,我們需要採用完全濾波。具體如圖所示:

上圖中SL1和SL2是我們要設定的階進處理區間限值。當數據偏差小於SL2時,干擾信號對最終數據的影響較大,我們需要進行完全濾波。當系統變化處於上圖中的SL1和SL2之間時,數據差異變較大,干擾信號相比於數據本身的變化較小,但不可忽略,我們可以進行不完全濾波來增加系統的靈敏度。當系統處於大於SL1的區間時,干擾信號對系統的影響很小,我們可以不做濾波處理。

2、算法設計

前面描述了這種分段增加濾波作用的濾波器的特點,接下來我們來設計這種階進式濾波器的操作算法。

首先依然需要一個數據隊列,但在不同的情況下,對數據隊列的更新形式是不一樣的。在前後兩個數據的偏差小於SL2時,這個時候我們需要對這採集數據進行完全的濾波處理。這個時候我們只需要用最新的數據替換時間最久的老數據,然後取隊列的算術平均值就得到輸出數據。具體的隊列更新如下:

若是數據偏差處於SL1和SL2之間,這個時候干擾信號對採集值的影響變小但並未小到可以忽略,但數據的變化幅度已經很大,爲了提高靈敏度,我們一次更新多個老數據以增加新數據的在輸出值的比重。具體的隊列更新如下:

若是數據偏差大於SL1時,數據的變化量已經遠超干擾的影響,我們可以忽略干擾信號,爲了提高系統靈敏度,我們不需要在進行濾波處理。具體的隊列更新如下:

但是偏差落在大於SL1的範圍內時,並不預示着我們需要馬上更新數據隊列的全部數據,因爲可能是偶然性的脈衝干擾,這時我們需要作消抖處理。我們判斷如果連續多少個的採集數據均落在相應的區間,我們就認爲不是偶然的脈衝干擾。這是我們就更新隊列的全部數據。

3、代碼實現

我們已經詳細描述了階進式平滑濾波器的操作算法,但具體如何實現呢?我們依然將濾波器當作一個對象,我們在此只考慮分成三段的階進式濾波算法,即不濾波,半濾波和全濾波。

我們先來分析一下,首先濾波器對象需要獲取當前採集到的數據值;同時我們爲了實現對N個數據的遞推平均就需要有一個存儲這N個數的隊列;我們需要記錄最新的數據硬件存儲到哪個位置就需要一個位置指針;同時我們也需要知道N的大小,所以我們將它們都定義濾波器對象的屬性。平滑濾波的過程必須要計算算術平均值,而遞推算術平均則是在每次採集一個數據之時都計算平均值,可是如果N值較大時,就會存在大量的重複計算。我們考慮到上一次採樣的平均值已經得到,我們將其記錄下來的話就可以用最新採集的數據替換掉最老的數據,從而得到新的平均值,所以我們將上一時間的輸出值記錄下來作爲對象的一個屬性。除此之外,我們還需要知道濾波器的限制區間,即HL和LL,所以我們將採集數據所對應的量程範圍、上限(HL)、下限(LL)比例均作爲對象的屬性。同時爲了實現消抖,我們需要記錄數據大幅變化的持續數及確認消抖的最大數值,這兩個也作爲對象的屬性。根據以上分析我們可定義濾波器對象類型爲:

/*定義平滑濾波對象類型*/
typedef struct FilterObject{
  float newValue;       //最新測量值
  float lastValue;      //上一個輸出值
  float *buffer;        //數據緩存區
  int16_t position;    //寫操作位置指針
  uint16_t bufCount;    //濾波的數量
  uint16_t delayCount;  //延遲計數
  uint16_t delayLimit;  //延遲限值
  float rangeLimit;     //量程範圍
  float upperRario;     //比例下限
  float lowerRatio;     //比例下限
}FilterObjectType;

我們已經獲得了濾波器對象,接下來將基於這一對象實現相應的濾波器功能。我們要對比當前的採集值與上一個輸出值的比較,根據它們的偏差絕對值來決定採取怎樣的處理方式。處理流程如下:

在偏差值小於SL2時,進行全濾波處理;在偏差值大於SL2而小於SL1時,進行半濾波處理;而在偏差值大於SL1時,不進行濾波處理。根據以上的分析及流程圖我們可以設計階進平滑濾波器的代碼爲:

/* 階梯平滑濾波處理函數,返回濾波後的值*/
float StepSmoothingFilter(FilterObjectType *filter)
{
  float result=filter->lastValue;
 
  if(filter->position<0)
  {
    for(int i=0;i<filter->bufCount;i++)
    {
      filter->buffer[i]=filter->newValue;
    }
    filter->position=0;
    filter->lastValue=filter->newValue;
  }
 
  if(filter->position>=filter->bufCount)
  {
    filter->position=0;
  }
 
  if(fabs(filter->newValue-filter->lastValue)>(filter->rangeLimit*filter->upperRario/100))
  {
    filter->delayCount+=1;
    if(filter->delayCount>=filter->delayLimit)
    {
      for(int i=0;i<filter->bufCount;i++)
      {
        filter->buffer[i]=filter->newValue;
      }
      filter->position++;
      result=filter->newValue;
      filter->delayCount=0;
    }
  }
  else if(fabs(filter->newValue-filter->lastValue)>=(filter->rangeLimit*filter->lowerRatio/100))
  {
    result=filter->lastValue-filter->buffer[filter->position]/filter->bufCount;
   
    result=result+filter->newValue/filter->bufCount;
   
    filter->buffer[filter->position++]=filter->newValue;
    if(filter->position>=filter->bufCount)
    {
      filter->position=0;
    }
   
    result=result-filter->buffer[filter->position]/filter->bufCount;
    result=result+filter->newValue/filter->bufCount;
    filter->buffer[filter->position++]=filter->newValue;
   
    filter->delayCount=0;
  }
  else
  {
    result=filter->lastValue-filter->buffer[filter->position]/filter->bufCount;
   
    result=result+filter->newValue/filter->bufCount;
   
    filter->buffer[filter->position++]=filter->newValue;
   
    filter->delayCount=0;
  }
 
  filter->lastValue=result;
  filter->newValue=0.0;
  return result;
}

4、應用總結

我們實現了基於算術平均的階進平滑濾波器。該濾波器對週期性干擾和小幅的噪聲干擾均有較好的效果。而且通過不同偏差值區間進行不同的濾波處理,在數據快速變化時,能很好的提高系統的靈敏度。對於系統處於平穩狀態時,也能收到很好的濾波效果。

這一濾波器有效的前提是基於干擾的幅度並不是很大而且系統的採集值基本能穩定在一定範圍內的前提而實現的。如果系統存在較大幅度的脈衝干擾,在這種脈衝干擾的出現頻率較低時,消抖操作能夠很好的去除這種偶然性干擾。但如果出現持續性的高頻大幅脈衝干擾,這一濾波器將變得無能爲力。

對於限值區間SL1和SL2的取值一般只能根據採集系統的特點或者工程師的經驗來判斷,但並非是盲目的,因爲很多情況下我們是能夠判斷出干擾信號的大致判斷範圍的。在這些系統中絕大部分的干擾變化會落在SL2的範圍內,其概率可能會超過60%,而落在SL1範圍內的概率可能會超過90%,所以選擇合適的SL1和SL2值會取得良好的濾波效果。

歡迎關注:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章