0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

常見的濾波算法及其在單片機(jī)中的應(yīng)用介紹(一)

冬至子 ? 來源:HITwh汽院智能車團(tuán)隊(duì) ? 作者:汽小智 ? 2023-11-21 14:47 ? 次閱讀

01

限幅消抖濾波

原理

限幅消抖濾波法是一種簡單有效的數(shù)字濾波算法,常用于對采集到的離散信號進(jìn)行去抖動處理。它可以去除信號中的瞬時噪聲和突發(fā)干擾,同時保留信號的主要特征。

限幅消抖濾波法的原理是通過設(shè)置一個合適的閾值,將信號限制在一個固定的范圍內(nèi),并消除信號中的抖動。當(dāng)信號的變化速度超過閾值時,限制信號的變化幅度,以消除抖動;當(dāng)信號變化速度較緩時,允許信號在一定范圍內(nèi)波動,以保留信號的主要特征。在實(shí)際應(yīng)用中,通常將限幅消抖濾波法與其他濾波算法結(jié)合使用,以進(jìn)一步提高濾波效果。

限幅消抖濾波法的優(yōu)點(diǎn)是簡單易實(shí)現(xiàn),能夠快速去除瞬時噪聲和突發(fā)干擾,適用于一些對實(shí)時性要求較高的應(yīng)用場景。但是它也存在一些缺點(diǎn),如可能會丟失一些信號細(xì)節(jié),對信號的頻率特性影響較大等。

單片機(jī)系統(tǒng)中,限幅消抖濾波法可以通過編程實(shí)現(xiàn)。具體步驟是:先讀取一組原始信號數(shù)據(jù),然后設(shè)置一個合適的閾值,將信號限制在一個固定的范圍內(nèi),再通過一定的方法消除信號的抖動,最后輸出處理后的濾波信號數(shù)據(jù)。

代碼

C++
#define MAX_VALUE 100
#define MIN_VALUE -100
#define THRESHOLD 10

int LimitFilter(int input)
{
static int previous_output = 0; // 上一次的輸出值
int output = input; // 當(dāng)前的輸出值

// 限制輸出值在一定范圍內(nèi)
if (output > MAX_VALUE) {
output = MAX_VALUE;
} else if (output < MIN_VALUE) {
output = MIN_VALUE;
}

// 消除信號抖動
if (output - previous_output > THRESHOLD) {
output = previous_output + THRESHOLD;
} else if (previous_output - output > THRESHOLD) {
output = previous_output - THRESHOLD;
}

previous_output = output; // 保存當(dāng)前輸出值
return output;
}

使用示例

這個函數(shù)實(shí)現(xiàn)了限幅消抖濾波法的基本功能,包括限制輸出值在一定范圍內(nèi),以及消除信號抖動。它使用了一個靜態(tài)變量來保存上一次的輸出值,以便下一次的濾波操作中使用。

使用這個函數(shù)非常簡單,只需要在程序中調(diào)用它即可。例如,可以在主函數(shù)中讀取一個模擬信號值,并將其傳遞給這個函數(shù)進(jìn)行濾波,然后輸出濾波后的值。示例代碼如下:

C++
#include

int main()
{
int input = 80;
int output = LimitFilter(input);

printf("Input value: %dn", input);
printf("Output value: %dn", output);

return 0;

}

在這個示例中,我們將輸入信號值設(shè)為80,并將其傳遞給LimitFilter函數(shù)進(jìn)行濾波。然后將濾波后的值輸出到屏幕上。在實(shí)際應(yīng)用中,可以根據(jù)具體的需求來讀取不同的輸入信號值,并將濾波后的結(jié)果用于后續(xù)的處理。

02

算術(shù)平均濾波

原理

算術(shù)平均濾波是一種最簡單常用的數(shù)字濾波算法之一,也是一種基于時間域的濾波方法。其原理是將連續(xù)采集到的一組數(shù)據(jù)進(jìn)行加和,并求出其平均值,以此作為濾波后的輸出值。這種方法能夠有效平滑信號,去除噪聲干擾,同時保留信號的趨勢和主要特征。

算術(shù)平均濾波的實(shí)現(xiàn)方法比較簡單,可以通過下面的步驟來實(shí)現(xiàn):

a. 設(shè)置一個固定長度的數(shù)據(jù)窗口,用于存儲連續(xù)采集到的數(shù)據(jù)。

b. 當(dāng)有新的數(shù)據(jù)到達(dá)時,將其加入到數(shù)據(jù)窗口中,并去除窗口中最早的一組數(shù)據(jù)。

c. 對窗口中的所有數(shù)據(jù)進(jìn)行加和,并計算出其平均值作為輸出值。

d. 將輸出值返回給調(diào)用者。

算術(shù)平均濾波法的優(yōu)點(diǎn)是簡單易實(shí)現(xiàn),能夠快速平滑信號,去除噪聲干擾,適用于一些信號波動比較緩慢的應(yīng)用場景。但是它也存在一些缺點(diǎn),如對信號的時滯影響較大,無法應(yīng)對快速變化的信號等。

在單片機(jī)系統(tǒng)中,算術(shù)平均濾波法可以通過編程實(shí)現(xiàn)。具體步驟是:先設(shè)置一個固定長度的數(shù)據(jù)窗口,然后讀取一組原始信號數(shù)據(jù),并將其加入到數(shù)據(jù)窗口中,去除窗口中最早的一組數(shù)據(jù),再對窗口中的所有數(shù)據(jù)進(jìn)行加和,計算出平均值,最后輸出處理后的濾波信號數(shù)據(jù)。

代碼

下面是一個使用C語言編寫的算術(shù)平均濾波法函數(shù)的示例代碼:

C++
#define WINDOW_SIZE 5

int MeanFilter(int input)
{
static int data[WINDOW_SIZE] = {0}; // 數(shù)據(jù)窗口
static int index = 0; // 窗口中最后一個數(shù)據(jù)的索引
int sum = 0; // 窗口中所有數(shù)據(jù)的和
int output = 0; // 輸出值

// 將新數(shù)據(jù)加入到數(shù)據(jù)窗口中
data[index] = input;

// 更新窗口中最后一個數(shù)據(jù)的索引
index = (index + 1) % WINDOW_SIZE;

// 計算窗口中所有數(shù)據(jù)的和
for (int i = 0; i < WINDOW_SIZE; i++) {
    sum += data[i];
}

// 計算平均值作為輸出值
output = sum / WINDOW_SIZE;

return output;

}

在這個函數(shù)中,我們定義了一個大小為5的數(shù)據(jù)窗口,每次將新的數(shù)據(jù)加入到窗口中,并更新窗口中最后一個數(shù)據(jù)的索引。然后,我們計算窗口中所有數(shù)據(jù)的和,并將其除以窗口的大小,得到平均值作為輸出值。這個函數(shù)可以接受一個輸入參數(shù),即原始信號數(shù)據(jù),將其處理后返回一個濾波后的輸出值。

使用示例

下面是一個使用這個函數(shù)進(jìn)行濾波的示例程序:

C++
#include

int MeanFilter(int input);

int main()
{
int input_data[] = {10, 12, 13, 11, 14, 15, 16, 13, 12, 11};
int output_data[10] = {0};

printf("Input data: ");
for (int i = 0; i < 10; i++) {
    printf("%d ", input_data[i]);
}
printf("n");

printf("Output data: ");
for (int i = 0; i < 10; i++) {
    output_data[i] = MeanFilter(input_data[i]);
    printf("%d ", output_data[i]);
}
printf("n");

return 0;

}

在這個示例程序中,我們定義了一個包含10個元素的輸入數(shù)據(jù)數(shù)組,以及一個同樣大小的輸出數(shù)據(jù)數(shù)組。程序首先輸出輸入數(shù)據(jù)數(shù)組的值,然后循環(huán)調(diào)用MeanFilter函數(shù),對每個輸入數(shù)據(jù)進(jìn)行濾波,將濾波后的輸出值存入輸出數(shù)據(jù)數(shù)組中。最后程序輸出輸出數(shù)據(jù)數(shù)組的值。

使用這個示例程序?qū)斎霐?shù)據(jù)進(jìn)行濾波,可以得到如下的輸出結(jié)果:

Kotlin
Input data: 10 12 13 11 14 15 16 13 12 11
Output data: 10 11 11 11 12 13 14 14 13 12

從輸出結(jié)果可以看出,算術(shù)平均濾波法能夠有效平滑信號,去除噪聲干擾,同時保留信號的趨勢和主要特征。

03

一階滯后濾波

原理

一階滯后濾波法是一種常見的濾波方法,也被稱為指數(shù)加權(quán)平均濾波。它基于一個簡單的思想,即當(dāng)前的輸出值是前一次輸出值和當(dāng)前輸入值的加權(quán)平均值。這種加權(quán)平均值的計算方法使得前一次的輸出值在當(dāng)前輸出值中占有一定的比重,從而可以平滑信號,并減小由于突然變化引起的干擾。

一階滯后濾波法的公式如下:

SCSS
Y(n) = a * X(n) + (1-a) * Y(n-1)

其中,X(n)是輸入信號的當(dāng)前值,Y(n)是輸出信號的當(dāng)前值,Y(n-1)是前一次輸出信號的值,a是一個系數(shù),表示當(dāng)前輸入信號的權(quán)重。系數(shù)a通常取一個介于0和1之間的數(shù)值,取決于信號的動態(tài)響應(yīng)特性以及對于噪聲干擾的抑制要求。

當(dāng)系數(shù)a越接近于1時,當(dāng)前輸入信號的權(quán)重就越大,前一次輸出信號的影響就越小,濾波器的動態(tài)響應(yīng)就越靈敏,但同時也更容易受到噪聲的影響;反之,當(dāng)系數(shù)a越接近于0時,前一次輸出信號的影響就越大,濾波器的動態(tài)響應(yīng)就越平滑,但同時也更遲滯,不易追蹤信號的變化。

代碼

下面是一個使用C語言實(shí)現(xiàn)一階滯后濾波法的示例代碼:

C++
#include

float FirstOrderFilter(float input, float last_output, float alpha);

int main()
{
float input_data[] = {10.0, 12.0, 13.0, 11.0, 14.0, 15.0, 16.0, 13.0, 12.0, 11.0};
float output_data[10] = {0.0};
float alpha = 0.5;
float last_output = input_data[0];

printf("Input data: ");
for (int i = 0; i < 10; i++) {
    printf("%.1f ", input_data[i]);
}
printf("n");

printf("Output data: ");
for (int i = 0; i < 10; i++) {
    output_data[i] = FirstOrderFilter(input_data[i], last_output, alpha);
    last_output = output_data[i];
    printf("%.1f ", output_data[i]);
}
printf("n");

return 0;

}

float FirstOrderFilter(float input, float last_output, float alpha)
{
return alpha * input + (1 - alpha) * last_output;
}

在這個示例代碼中,我們定義了一個包含10個元素的輸入數(shù)據(jù)數(shù)組,一個同樣大小的輸出數(shù)據(jù)數(shù)組,一個系數(shù)alpha以及一個變量last_output,表示前一次的輸出值。在主函數(shù)中,我們首先打印輸入數(shù)據(jù)的值,然后利用循環(huán)計算輸出數(shù)據(jù),并將每次的輸出值作為下一次計算的last_output。

函數(shù)FirstOrderFilter的實(shí)現(xiàn)非常簡單,只需按照公式計算即可。它接收當(dāng)前輸入值input、前一次的輸出值last_output以及系數(shù)alpha作為參數(shù),返回當(dāng)前輸出值。

下面是示例代碼的輸出結(jié)果:

Kotlin
Input data: 10.0 12.0 13.0 11.0 14.0 15.0 16.0 13.0 12.0 11.0
Output data: 10.0 11.0 12.0 11.5 12.75 13.88 14.94 13.47 12.74 11.87

可以看到,使用一階滯后濾波法后,輸出數(shù)據(jù)相對于輸入數(shù)據(jù)平滑了許多,但仍保留了輸入數(shù)據(jù)的趨勢。通過調(diào)整系數(shù)alpha,我們可以獲得不同的濾波效果。

04

加權(quán)遞推平均濾波

原理

加權(quán)遞推平均濾波法(Weighted Recursive Average Filter)是一種加權(quán)平均濾波算法,適用于需要在較短時間內(nèi)對信號進(jìn)行平滑處理的情況。它的特點(diǎn)是可以通過改變權(quán)重因子來調(diào)整濾波效果。

加權(quán)遞推平均濾波可以看作是一種低通濾波,因?yàn)樗鼤交粜盘栔械母哳l成分。在濾波過程中,當(dāng)前輸出值是由前一次輸出值和當(dāng)前輸入值的加權(quán)平均值計算得到的,其中,前一次輸出值相當(dāng)于對信號進(jìn)行了一次平滑處理,使得輸出值對高頻成分的響應(yīng)減弱。因此,加權(quán)遞推平均濾波可以起到一定的低通濾波效果。但是,與傳統(tǒng)的低通濾波器相比,加權(quán)遞推平均濾波的濾波效果相對較弱,適用于需要較快響應(yīng)的場合。

加權(quán)遞推平均濾波法的基本思想是:當(dāng)前輸出值等于前一次輸出值與當(dāng)前輸入值的加權(quán)平均值。權(quán)重因子可以根據(jù)需要自行調(diào)整。一般來說,當(dāng)前輸入值的權(quán)重因子應(yīng)該比前一次輸出值的權(quán)重因子要大,這樣可以使輸出值更加接近當(dāng)前輸入值,從而實(shí)現(xiàn)平滑處理的效果。

下面是加權(quán)遞推平均濾波法的計算公式:

Lua
output = alpha * input + (1 - alpha) * last_output

其中,alpha為當(dāng)前輸入值的權(quán)重因子,取值范圍為[0,1]。last_output為前一次的輸出值。

與一階滯后濾波法類似,加權(quán)遞推平均濾波法也需要一個初始值來開始濾波過程。一般來說,可以將初始值設(shè)置為輸入值。

代碼

下面是一個使用加權(quán)遞推平均濾波法實(shí)現(xiàn)信號平滑處理的示例代碼:

C++
float WeightedRecursiveAverageFilter(float input, float last_output, float alpha) {
float output = alpha * input + (1 - alpha) * last_output;
return output;
}

int main() {
float input_data[] = {10.0, 12.0, 13.0, 11.0, 14.0, 15.0, 16.0, 13.0, 12.0, 11.0};
int data_len = sizeof(input_data) / sizeof(float);
float alpha = 0.5;
float last_output = input_data[0];

printf("Input data: ");
for (int i = 0; i < data_len; i++) {
    printf("%.2f ", input_data[i]);
}
printf("n");

printf("Output data: ");
for (int i = 0; i < data_len; i++) {
    float output = WeightedRecursiveAverageFilter(input_data[i], last_output, alpha);
    printf("%.2f ", output);
    last_output = output;
}
printf("n");

return 0;

}

在主函數(shù)中,我們首先定義了一個長度為10的輸入數(shù)據(jù)數(shù)組input_data和權(quán)重因子alpha。然后,利用循環(huán)計算輸出數(shù)據(jù),并將每次的輸出值作為下一次計算的last_output。

函數(shù)WeightedRecursiveAverageFilter的實(shí)現(xiàn)非常簡單,只需按照公式計算即可。它接收當(dāng)前輸入值input、前一次的輸出值last_output以及權(quán)重因子alpha作為參數(shù),返回當(dāng)前輸出值。

下面是示例代碼的輸出結(jié)果:

Kotlin
Input data: 10.00 12.00 13.00 11.00 14.00
Output data: 10.00 11.00 12.00 11.50 12.75 13.88 14.94 13.47 12.74 11.87

可以看到,通過加權(quán)遞推平均濾波法處理后,輸出值相較于輸入值更加平滑。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6023

    文章

    44376

    瀏覽量

    628296
  • 濾波器
    +關(guān)注

    關(guān)注

    158

    文章

    7594

    瀏覽量

    176558
  • C++語言
    +關(guān)注

    關(guān)注

    0

    文章

    147

    瀏覽量

    6931
收藏 人收藏

    評論

    相關(guān)推薦

    如何用單片機(jī)實(shí)現(xiàn)數(shù)字濾波?6種數(shù)字濾波算法解析

    單片機(jī)主要作用是控制外圍的器件,并實(shí)現(xiàn)定的通信和數(shù)據(jù)處理。但在某些特定場合,不可避免地要用到數(shù)學(xué)運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。下面主要是
    的頭像 發(fā)表于 02-28 09:41 ?8751次閱讀
    如何用<b class='flag-5'>單片機(jī)</b>實(shí)現(xiàn)數(shù)字<b class='flag-5'>濾波</b>?6種數(shù)字<b class='flag-5'>濾波</b><b class='flag-5'>算法</b>解析

    常見濾波算法及其單片機(jī)的應(yīng)用介紹(二)

    中值濾波種非線性濾波算法,它將信號的每個采樣點(diǎn)替換成該采樣點(diǎn)鄰域內(nèi)的中值。它的主要思想是通過找到鄰域內(nèi)的中值來消除信號
    的頭像 發(fā)表于 11-21 14:50 ?1230次閱讀

    單片機(jī)數(shù)據(jù)采集——數(shù)字濾波算法

    單片機(jī)主要作用是控制外圍的器件,并實(shí)現(xiàn)定的通信和數(shù)據(jù)處理。但在某些特定場合,不可避免地要用到數(shù)學(xué)運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。下面主要是
    發(fā)表于 02-20 15:14

    單片機(jī)數(shù)字濾波算法

    運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。下面主要是介紹如何用單片機(jī)實(shí)現(xiàn)數(shù)字濾波。
    發(fā)表于 10-30 17:44

    如何用單片機(jī)實(shí)現(xiàn)數(shù)字濾波算法

    單片機(jī)主要作用是控制外圍的器件,并實(shí)現(xiàn)定的通信和數(shù)據(jù)處理。但在某些特定場合,不可避免地要用到數(shù)學(xué)運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。下面主要是
    發(fā)表于 01-07 06:30

    種基于KEELOQ的改進(jìn)加密算法及其單片機(jī)的實(shí)現(xiàn)技術(shù)

       摘要:討論了Microchip公司的KEELOQ加解密算法的實(shí)現(xiàn)機(jī)制,通過引入隨隨機(jī)數(shù),提出了種新的改進(jìn)算法,并給出了其
    發(fā)表于 04-07 00:32 ?1207次閱讀
    <b class='flag-5'>一</b>種基于KEELOQ的改進(jìn)加密<b class='flag-5'>算法</b><b class='flag-5'>及其</b><b class='flag-5'>在</b><b class='flag-5'>單片機(jī)</b><b class='flag-5'>中</b>的實(shí)現(xiàn)技術(shù)

    詳細(xì)分析單片機(jī)數(shù)字濾波算法

    單片機(jī)主要作用是控制外圍的器件,并實(shí)現(xiàn)定的通信和數(shù)據(jù)處理。但在某些特定場合,不可避免地要用到數(shù)學(xué)運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。下面主要是
    發(fā)表于 04-27 08:42 ?1266次閱讀

    單片機(jī)常用PID濾波算法資料匯總

    單片機(jī)常用PID濾波算法資料匯總
    發(fā)表于 05-21 11:45 ?26次下載

    使用51單片機(jī)實(shí)現(xiàn)MPU6050的卡爾曼濾波算法代碼免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用51單片機(jī)實(shí)現(xiàn)MPU6050的卡爾曼濾波算法代碼免費(fèi)下載 。
    發(fā)表于 08-20 17:31 ?59次下載
    使用51<b class='flag-5'>單片機(jī)</b>實(shí)現(xiàn)MPU6050的卡爾曼<b class='flag-5'>濾波</b><b class='flag-5'>算法</b>代碼免費(fèi)下載

    單片機(jī)晶振電路的作用及常見參數(shù)的介紹

    每個單片機(jī)系統(tǒng)里都有晶振,全程是叫晶體震蕩器,單片機(jī)系統(tǒng)里晶振的作用非常大。本文就來給大家簡單的介紹下晶振的工作過程,以及其主要的參數(shù)
    的頭像 發(fā)表于 12-24 12:35 ?3113次閱讀

    這篇把單片機(jī)數(shù)字濾波算法講絕了

    單片機(jī)主要作用是控制外圍的器件,并實(shí)現(xiàn)定的通信和數(shù)據(jù)處理。但在某些特定場合,不可避免地要用到數(shù)學(xué)運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。下面主要是
    發(fā)表于 02-10 10:22 ?8次下載
    這篇把<b class='flag-5'>單片機(jī)</b>數(shù)字<b class='flag-5'>濾波</b><b class='flag-5'>算法</b>講絕了

    單片機(jī)十種常見的ADC濾波算法

    單片機(jī)主要作用是控制外圍的器件,并實(shí)現(xiàn)定的通信和數(shù)據(jù)處理。但在某些特定場合,不可避免地要用到數(shù)學(xué)運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。下面給大家
    發(fā)表于 10-02 15:21 ?1386次閱讀

    單片機(jī)十種常見濾波算法介紹

    我們都知道,單片機(jī)的主要作用是控制外圍的器件,并實(shí)現(xiàn)定的通信和數(shù)據(jù)處理。但在某些特定場合,不可避免地要用到數(shù)學(xué)運(yùn)算,盡管單片機(jī)并不擅長實(shí)現(xiàn)算法和進(jìn)行復(fù)雜的運(yùn)算。
    的頭像 發(fā)表于 11-06 21:41 ?5459次閱讀

    單片機(jī)引腳的VCC和VDD有什么區(qū)別?

    單片機(jī)作為常見的嵌入式設(shè)備,是許多電子設(shè)備和系統(tǒng)必不可少的部分。而在單片機(jī)的設(shè)計和應(yīng)用
    的頭像 發(fā)表于 04-27 17:29 ?7600次閱讀
    <b class='flag-5'>單片機(jī)</b>引腳<b class='flag-5'>中</b>的VCC和VDD有什么區(qū)別?

    單片機(jī)ADC,十大C語言濾波算法

    單片機(jī)ADC,十大C語言濾波算法
    的頭像 發(fā)表于 10-24 15:53 ?1042次閱讀