前言:本文為手把手教學ADC采樣及各式濾波算法的教程,本教程的MCU采用STM32F103ZET6。以HAL庫的ADC采樣函數為基礎進行教學,通過各式常見濾波的實驗結果進行分析對比,搭配VOFA+工具直觀的展示濾波效果。
實驗效果圖:


一、ADC采樣
1.1 ADC簡介
單片機是數字芯片,只認識由0和1組成的邏輯序列。但實際情況下,生活中還有許多非0和1的模擬物理量存在,例如溫度,濕度等。這時候往往需要使用到AD轉換,AD轉換的英文就是Analog(模擬) to Digital(數字) ,由模擬量轉化為數字量;同理DA,則為Digital to Analog,數字量轉化為模擬量。
ADC,Analog to Digital Converter 的縮寫,中文名稱模數轉換器。它可以將外部的模擬信號轉化成數字信號。使用它去讀取IO口上的數值將不再是簡單的0或1,而是連續可變的數值。ADC采樣就是把隨時間連續變化的模擬量轉換為時間離散的模擬量。
ADC幾個比較重要的參數:
(1)測量范圍:測量范圍對于 ADC 來說就好比尺子的量程,ADC 測量范圍決定了你外接的設備其信號輸出電壓范圍,不能超過 ADC 的測量范圍(比如,STM32系列的 ADC 正常就不能超過3.3V)。
(2)分辨率:假如 ADC 的測量范圍為 0-5V,分辨率設置為12位,那么我們能測出來的最小電壓就是 5V除以 2 的 12 次方,也就是 5/4096=0.00122V。很明顯,分辨率越高,采集到的信號越精確,所以分辨率是衡量 ADC 的一個重要指標。
(3)采樣時間:當 ADC 在某時刻采集外部電壓信號的時候,此時外部的信號應該保持不變,但實際上外部的信號是不停變化的。所以在 ADC 內部有一個保持電路,保持某一時刻的外部信號,這樣 ADC 就可以穩定采集了,保持這個信號的時間就是采樣時間。
(4)采樣率:也就是在一秒的時間內采集多少次。很明顯,采樣率越高越好,當采樣率不夠的時候可能會丟失部分信息,所以 ADC 采樣率是衡量 ADC 性能的另一個重要指標(詳細參考信號處理方向書籍)
1.2 STM32的ADC
STM32 擁有 1~3 個 ADC(STM32F101/102 系列只有 1 個 ADC,STM32F103系列則有3個ADC和1個DAC),這些 ADC 可以獨立使用,也可以使用雙重模式(提高采樣率)。STM32 的 ADC 是 12 位逐次逼近型的模擬數字轉換器。它有 18 個通道,可測量 16 個外部和 2 個內部信號源。各通道的 A/D 轉換可以單次、連續、掃描或間斷模式執行。ADC 的結果可以左對齊或右對齊方式存儲在 16 位數據寄存器中。
特別說明:
ADC 是12位逐次逼近型模數轉換器,
輸出數值范圍是 0 ~ 2^12 -1(0 ~ 4095),滿量程是 3.3V ,
分辨率就是最低有效位(LSB)的對應輸入電壓值。
分辨率 =3300/4095 ≈ 0.806mV。
STM32F10X 系列將 ADC 的轉換分為 2 個通道組:規則通道組和注入通道組。規則通道相當于正常運行的程序,而注入通道呢,就相當于中斷打斷式通道選擇。在程序正常執行的時候,中斷是可以打斷程序執行的。同這個類似,注入通道的轉換可以打斷規則通道的轉換, 在注入通道被轉換完成之后,規則通道才得以繼續轉換。

二、VOFA+
2.1 VOFA+簡介
VOFA+是一款直觀、靈活、強大的插件驅動高自由度的上位機,在與電氣打交道的領域里,如自動化、嵌入式、物聯網、機器人等,都能看到VOFA+的身影。VOFA+的名字來源于:Volt/伏特、Ohm/歐姆、Fala/法拉、Ampere/安培,是電氣領域的基礎單位,與他們的發明者——4位電子物理學領域的科學巨人,分別同名。他們的首字母共同構成了VOFA+的名字。
VOFA+特點概覽:
平臺支持:Windows、Linux、MacOS;
接口支持:串口(超高波特率,穩定支持)、網口(TCP客戶端/服務端,UDP);
協議支持:協議為插件,已開源,人人可編寫。目前已支持CSV風格的字符串協議,和十六進制浮點數組形式的字節流協議;
控件支持:控件為插件,已開源,人人可編寫。目前已支持波形圖、按鈕、狀態燈、圖片、滑動條、3D立方控件(可更換模型)等;
數據維度自由化:2維度與3維,一個也不能拉下;
自主研發的波形控件:支持每通道百萬采樣點的繪制,性能強勁;
自主研發的波形控件:無縫嵌入了實時直方統計和點數可設置的傅里葉變換,可以使用VOFA+進行數據分析。
2.2 VOFA+使用方法
VOFA+的數據協議引擎有3種:FireWater,JustFloat,RawData。每種數據協議引擎都有自己特殊的使用效果,讀者朋友可以根據自己的實際需要去選擇使用。作者這里主要給大家演示一下FireWater協議下的VOFA+使用效果和方法。
FireWater協議是CSV風格的字符串流,直觀簡潔,編程像printf簡單。但由于字符串解析消耗更多的運算資源(無論在上位機還是下位機),建議僅在通道數量不多、發送頻率不高的時候使用。

將鼠標放到FireWater協議上,可以很貼心的得到使用格式幫助。如上圖所示,我們使用printf("simples:%f, %f ", sin(t1), sin(t2)")函數進行打印測試。
#include "math.h"
#include "stdio.h"
....
int main(void)
{
/* USER CODE BEGIN 1 */
float t1 = 0;
float t2 = 0;
/* USER CODE END 1 */
.......
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
t1 += 0.1;
t2 += 0.5;
printf("simples:%f, %f
", sin(t1), sin(t2));
HAL_Delay(100);
}
/* USER CODE END 3 */
}
1、選擇串口通訊、端口號、波特率等參數設置;

2、去控件中選擇波形圖,拉入tab中,右鍵選擇Y軸將2個輸入I0與I1都選中,之后開啟串口連接;

3、運行上位機,使用波形圖控件讀取下位機參數;

三、濾波算法與效果
受限于MCU自身的ADC外設缺陷,其精度和穩定性通常較差,很多場景下需要采取濾波補償。
濾波的作用就是減少噪聲與干擾對數據測量的影響。
3.1、不添加濾波算法采樣
直接采集3.3V的電壓:
VOFA+讀取到的數據:

上圖借助VOFA+上位機可以清楚看出未使用濾波的ADC采樣波動還是比較明顯的,但是作者主觀干啥F1系列的ADC確實好像比F4系列的ADC穩定些。(之所以不是4096可能是因為電源未達到3.3v)
四、濾波算法
4.1、一階互補濾波
方法:取a=0~1,本次濾波結果=(1-a)本次采樣值+a上次濾波結果
優點:對周期性干擾具有良好的抑制作用適用于波動頻率較高的場合
缺點:相位滯后,靈敏度低滯后程度取決于a值大小不能消除濾波頻率高于采樣頻率的1/2的干擾信號
代碼如下:
//一階互補濾波 int firstOrderFilter(int newValue, int oldValue, float a) { return a * newValue + (1-a) * oldValue; } ADC_value=HAL_ADC_GetValue(&hadc1);//獲取ADC1的數值 //主函數 while(1){ HAL_ADC_Start(&hadc1); //開啟ADC1,放置在while循環中 Filtering_Value = firstOrderFilter(HAL_ADC_GetValue(&hadc1),ADC_value,0.3); //濾波算法 HAL_Delay(10); //延遲函數,防止采樣失效 printf("ADC_value:%d ", ADC_value); }
VOFA+軟件的效果圖:

結論:
一階互補濾波的局限性還是很大的,效果非常一般。
4.2、中位值濾波
方法:連續采樣N次(N取奇數)把N次采樣值按大小排列取中間值為本次有效值
優點:能有效克服因偶然因素引起的波動干擾;對溫度、液位等變化緩慢的被測參數有良好的濾波效果
缺點:對流量,速度等快速變化的參數不宜
代碼如下:
//中值濾波算法
int middleValueFilter(int N)
{
int value_buf[N];
int i,j,k,temp;
for( i = 0; i < N; ++i)
{
value_buf[i] = HAL_ADC_GetValue(&hadc1);
}
for(j?=?0?;?j? value_buf[k+1])
{
temp = value_buf[k];
value_buf[k] = value_buf[k+1];
value_buf[k+1] = temp;
}
}
}
return value_buf[(N-1)/2];
}
VOFA+軟件的效果圖:

結論如下:
中值濾波對消除異常值和平穩化AD采樣都具有十分有效的結果。
4.3、算術平均濾波
方法:連續取N個采樣值進行算術平均運算;
N值較大時:信號平滑度較高,但靈敏度較低
N值較小時:信號平滑度較低,但靈敏度較高
N值的選取:一般流量,N=12;壓力:N=4
優點:試用于對一般具有隨機干擾的信號進行濾波。這種信號的特點是有一個平均值,信號在某一數值范圍附近上下波動。
缺點:測量速度較慢或要求數據計算較快的實時控制不適用。
代碼:
//算術平均值濾波
int averageFilter(int N)
{
int sum = 0;
short i;
for(i = 0; i < N; ++i)
{
sum += HAL_ADC_GetValue(&hadc1);
}
return sum/N;
}
VOFA+軟件的效果圖:

結論:
算術平均濾波表現出了一定的平穩性,同時具有波動的伴隨性(合理選擇N值可能達到很好的效果)。
4.4、滑動平均濾波
方法:把連續取N個采樣值看成一個隊列,隊列的長度固定為N。每次采樣到一個新數據放入隊尾,并扔掉原來隊首的一次數據(先進先出原則)。把隊列中的N個數據進行算術平均運算,就可獲得新的濾波結果。
N值的選取:流量,N=12;壓力:N=4;液面,N=4~12;溫度,N=1~4
優點:對周期性干擾有良好的抑制作用,平滑度高;試用于高頻振蕩的系統
缺點:靈敏度低;對偶然出現的脈沖性干擾的抑制作用較差,不適于脈沖干擾較嚴重的場合
比較浪費RAM(改進方法,減去的不是隊首的值,而是上一次得到的平均值)
代碼:
//平滑均值濾波
#define N 10
int value_buf[N];
int sum=0;
int curNum=0;
intmoveAverageFilter()
{
if(curNum < N)
{
value_buf[curNum] = HAL_ADC_GetValue(&hadc1);
sum += value_buf[curNum];
curNum++;
return sum/curNum;
}
else
{
sum -= sum/N;
sum += HAL_ADC_GetValue(&hadc1);
return sum/N;
}
}
VOFA+軟件的效果圖:

結論:
平滑均值濾波相較于普通的算術平均濾波,突出一個平滑特性。
可以從上述VOFA+的波形圖看出,平滑濾波可以有效抵消AD采樣的刺噪并穩定化采集(據作者同門實戰反應平滑濾波的效果還是非常好的,尤其在控制方面)。
4.5、限幅平均濾波
方法:相當于“限幅濾波法”+“遞推平均濾波法”
每次采樣到的新數據先進行限幅處理再送入隊列進行遞推平均濾波處理
優點:對于偶然出現的脈沖性干擾,可消除有其引起的采樣值偏差。
缺點:比較浪費RAM
代碼如下:
//限幅平均濾波
#define A 50 //限制幅度閾值
#define M 12
int data[M];
int First_flag=0;
intLAverageFilter()
{
int i;
int temp,sum,flag=0;
data[0] = HAL_ADC_GetValue(&hadc1);
for(i=1;iA || ((data[i-1]-temp)>A))
{
i--;
flag++;
}
else
{
data[i]=temp;
}
}
for(i=0;i
VOFA+軟件的效果圖:

結論:
限幅平均濾波類似于縫合怪,但是效果是非常顯著的,它有效的解決了實際場景下突變噪聲對AD采樣的影響,但是消耗內存。
4.6、卡爾曼濾波
核心思想:根據當前的儀器"測量值" 和上一刻的 “預測量” 和 “誤差”,計算得到當前的最優量,再預測下一刻的量。里面比較突出的是觀點是:把誤差納入計算,而且分為預測誤差和測量誤差兩種,通稱為噪聲。還有一個非常大的特點是:誤差獨立存在,始終不受測量數據的影響。
優點:巧妙的融合了觀測數據與估計數據,對誤差進行閉環管理,將誤差限定在一定范圍。適用性范圍很廣,時效性和效果都很優秀。
缺點:需要調參,參數的大小對濾波的效果影響較大。
代碼如下:
//卡爾曼濾波
int KalmanFilter(int inData)
{
static float prevData = 0; //先前數值
static float p = 10, q = 0.001, r = 0.001, kGain = 0; // q控制誤差 r控制響應速度
p = p + q;
kGain = p / ( p + r ); //計算卡爾曼增益
inData = prevData + ( kGain * ( inData - prevData ) ); //計算本次濾波估計值
p = ( 1 - kGain ) * p; //更新測量方差
prevData = inData;
return inData; //返回濾波值
}
VOFA+軟件的效果圖:

結論:
VOFA+顯示的波形圖開源看出卡爾曼濾波有一定的去噪穩定特性的,雖然效果不是特別優秀。
卡爾曼濾波的普適性很強,尤其在控制與多傳感器融合方向,只要參數調整的好,效果出奇優秀。
五、實驗總結
ADC作為嵌入式開發過程中必須掌握的外設,往往項目中是需要設置濾波器的。RC硬件濾波效果一般的話,可以用軟件來湊。同時濾波算法各式各樣,原理也各不相同,希望讀者朋友在實際的工程項目中,不要盲目的追求各種牛逼的濾波算法,其實適合該工程的濾波就是好濾波。
來源:https://blog.csdn.net/black_sneak/article/details/129629485
-
單片機
+關注
關注
6076文章
45495瀏覽量
670281 -
adc
+關注
關注
100文章
7511瀏覽量
555931 -
STM32
+關注
關注
2309文章
11162瀏覽量
373415 -
模數轉換器
+關注
關注
26文章
4013瀏覽量
130100 -
濾波算法
+關注
關注
2文章
96瀏覽量
14384
原文標題:STM32的ADC采樣及各式濾波實現(HAL庫,含VOFA+教程)
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
STM32的ADC項目應用,用什么算法濾波和穩定數據抖動?
ADC的采樣濾波算法利用卡爾曼濾波算法
單片機ADC采樣算法-中位值平均濾波法
STM32F30x 的ADC 采樣的傅立葉變換
解決STM32單片機的ADC采樣不準確偏移的問題
STM32自帶AD采樣濾波方法
STM32的ADC多通道采樣
STM32的ADC采樣及各式濾波算法實現
評論