chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

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

信號處理:指數(shù)移動平均 (EMA) 濾波器

海闊天空的專欄 ? 來源: Mustahsin Zarif ? 作者: Mustahsin Zarif ? 2025-10-04 18:35 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

作者: Mustahsin Zarif

之前我們在《信號處理簡介》一文中已經(jīng)見過了兩類濾波器:有限脈沖響應 (FIR) 濾波器和無限脈沖響應 (IIR) 濾波器。我們看到了移動平均濾波器如何同時以 FIR 和 IIR 形式表示,但如果它們相互比較又各具哪些優(yōu)勢呢?

回顧我之前博客中的例子,我們可以將 FIR 濾波器展開為如下形式:

y[5] = (x[5]+x[4]+x[3]+x[2]+x[1]+x[0])/5,

在這里,我們看到我們需要:

  1. 5 次乘法和
  2. 4 次求和運算。

乘法運算的計算成本特別高。因此,如果我們再次查看 IIR 形式,我們會發(fā)現(xiàn)它只需要:

  1. 3 次乘法和
  2. 2 次求和運算

y[6]=(x[6]+y[5]-x[1])/5

這大大降低了計算成本!這對于單片機嵌入式設備來說非常好,因為它們在每個離散時間步驟上執(zhí)行計算所消耗的資源更少。

例如,當我對采用 FIR 和 IIR 形式的 11 點移動平均濾波器使用 Python 函數(shù) ‘time.time’ 時,所有參數(shù)(窗口大小、采樣率、樣本大小等)相同,我分別得到以下運行時間結果:51 ms、27 ms。

離散時間IIR 濾波器示例

現(xiàn)在我們已經(jīng)了解了為什么 IIR 濾波器在單片機上表現(xiàn)更好了,讓我們看一個使用 Arduino UNO 和 DFRobot MPU6050 慣性測量單元 (IMU) 的示例項目(圖 1)。我們將對 IMU 數(shù)據(jù)應用指數(shù)移動平均 (EMA) 濾波器,以查看原始數(shù)據(jù)和平滑數(shù)據(jù)之間的差異。

圖 1:MPU6050 與 Arduino Uno 之間的連接框圖。(圖片來源:Mustahsin Zarif)

圖 2:MPU6050 與 Arduino Uno 之間的連接。(圖片來源:Mustahsin Zarif)

指數(shù)移動平均濾波器具有遞歸形式:

y[n] = α*x[n] + (1- α)*y[n-1]

它之所以是遞歸,是因為我們測量的任何當前輸出也取決于先前的輸出;即系統(tǒng)具有記憶。

常數(shù) alpha () 決定了我們想要賦予當前輸入相對于先前輸出多大的權重。為了清楚起見,讓我們展開方程得到:

y[n] = α x[n] + (1- α ) (α*x[n?1]+(1?α)*y[n?2])

y[n] = αx[n] + (1- α ) x[n?1]+α (1?α)2x[n?2])+ ...

y[n] = k=0nα*(1?α)k*x[n?k]

我們看到,alpha 越大,當前輸入對當前輸出的影響就越大。這是好事,因為如果系統(tǒng)在不斷演進,過去的值不能代表當前的系統(tǒng)。另一方面,如果系統(tǒng)突然發(fā)生瞬間異常變化,情況就會變得很糟糕;在這種情況下,我們希望我們的輸出能夠遵循之前輸出所遵循的趨勢。

事不宜遲,現(xiàn)在讓我們看看 EMA 濾波器的代碼是如何用于 MPU6050 的。

EMA 濾波器代碼:

副本#include < wire.h >
#include < mpu6050.h >

MPU6050 mpu;

#define BUFFER_SIZE 11  // Window size

float accelXBuffer[BUFFER_SIZE];
float accelYBuffer[BUFFER_SIZE];
float accelZBuffer[BUFFER_SIZE];
int bufferCount = 0;  

void setup() {
  Serial.begin(115200);
  Wire.begin();

  mpu.initialize();

  if (!mpu.testConnection()) {
    Serial.println("MPU6050 connection failed!");
    while (1);
  }

  int16_t ax, ay, az;
  for (int i = 0; i < BUFFER_SIZE; i++) {
    mpu.getMotion6(&ax, &ay, &az, NULL, NULL, NULL);
    accelXBuffer[i] = ax / 16384.0;
    accelYBuffer[i] = ay / 16384.0;
    accelZBuffer[i] = az / 16384.0;
  }
  bufferCount = BUFFER_SIZE;
}

void loop() {
  int16_t accelX, accelY, accelZ;

  mpu.getMotion6(&accelX, &accelY, &accelZ, NULL, NULL, NULL);

  float accelX_float = accelX / 16384.0;
  float accelY_float = accelY / 16384.0;
  float accelZ_float = accelZ / 16384.0;

  if (bufferCount < BUFFER_SIZE) {
    accelXBuffer[bufferCount] = accelX_float;
    accelYBuffer[bufferCount] = accelY_float;
    accelZBuffer[bufferCount] = accelZ_float;
    bufferCount++;
  } else {
    for (int i = 1; i < BUFFER_SIZE; i++) {
      accelXBuffer[i - 1] = accelXBuffer[i];
      accelYBuffer[i - 1] = accelYBuffer[i];
      accelZBuffer[i - 1] = accelZBuffer[i];
    }
    accelXBuffer[BUFFER_SIZE - 1] = accelX_float;
    accelYBuffer[BUFFER_SIZE - 1] = accelY_float;
    accelZBuffer[BUFFER_SIZE - 1] = accelZ_float;
  }

//calculate EMA using acceleration values stored in buffer
  float emaAccelX = accelXBuffer[0];
  float emaAccelY = accelYBuffer[0];
  float emaAccelZ = accelZBuffer[0];
  float alpha = 0.2;

  for (int i = 1; i < bufferCount; i++) {
    emaAccelX = alpha * accelXBuffer[i] + (1 - alpha) * emaAccelX;
    emaAccelY = alpha * accelYBuffer[i] + (1 - alpha) * emaAccelY;
    emaAccelZ = alpha * accelZBuffer[i] + (1 - alpha) * emaAccelZ;
  }

  Serial.print(accelX_float); Serial.print(",");
  Serial.print(accelY_float); Serial.print(",");
  Serial.print(accelZ_float); Serial.print(",");
  Serial.print(emaAccelX); Serial.print(",");
  Serial.print(emaAccelY); Serial.print(",");
  Serial.println(emaAccelZ);

  delay(100);
}
< /mpu6050.h >< /wire.h >

當我們運行此代碼并檢查串口繪圖儀時,我們可以看到 x、y 和 z 軸方向加速度的成對粗糙和平滑線條,其中窗口大小為 11 和 alpha 值為 0.2(圖 3 至 5)。

圖 3:x 方向的原始加速度值和濾波后的加速度值。(圖片來源:Mustahsin Zarif)

圖 4:y 方向的原始加速度值和濾波后的加速度值。(圖片來源:Mustahsin Zarif)

圖 5:z 方向的原始加速度值和濾波后的加速度值。(圖片來源:Mustahsin Zarif)

讓代碼的智能化更進一步

我們現(xiàn)在知道,與 FIR 濾波器相比,IIR 濾波器更適合用作控制器,因為所需的求和和乘法計算明顯較少。然而,當我們實現(xiàn)這段代碼時,執(zhí)行的計算并不只有求和和乘法:每當有新的時間樣本進入時,我們都必須移動樣本,而這個過程在后臺需要計算能力。因此,我們可以借助循環(huán)緩沖區(qū),而不是在每個采樣時間間隔移動所有樣本。

我們的做法是:用一個指針來記住傳入的數(shù)據(jù)樣本的索引。然后,每次指針指向緩沖區(qū)中的最后一個元素時,它接下來都會指向緩沖區(qū)的第一個元素,新數(shù)據(jù)將替換之前存儲在這里的數(shù)據(jù),因為這是現(xiàn)在我們不再需要的最舊數(shù)據(jù)(圖 6)。因此,這種方法允許我們跟蹤緩沖區(qū)中最舊的樣本并替換該樣本,而不必每次都移動樣本以將新數(shù)據(jù)放入數(shù)組的最后一個元素中。

圖 6:循環(huán)緩沖區(qū)示例圖。(圖片來源:Mustasin Zafir)

這是使用循環(huán)緩沖區(qū)的 EMA 濾波器實現(xiàn)的代碼。您能嘗試對陀螺儀而不是對加速計運行這段代碼嗎?也可以嘗試使用不同的系數(shù)!

使用循環(huán)緩沖區(qū)代碼的 EMA 濾波器:

副本#include < wire.h >

#include < mpu6050.h >

MPU6050 mpu;

#define BUFFER_SIZE 11  // Window size

float accelXBuffer[BUFFER_SIZE];

float accelYBuffer[BUFFER_SIZE];

float accelZBuffer[BUFFER_SIZE];

int bufferIndex = 0;  

void setup() {

  Serial.begin(115200);

  Wire.begin();
 

  mpu.initialize();


  if (!mpu.testConnection()) {

    Serial.println("MPU6050 connection failed!");

    while (1);

  }

  int16_t ax, ay, az;

  for (int i = 0; i < BUFFER_SIZE; i++) {

    mpu.getMotion6(&ax, &ay, &az, NULL, NULL, NULL);

    accelXBuffer[i] = ax / 16384.0;

    accelYBuffer[i] = ay / 16384.0;

    accelZBuffer[i] = az / 16384.0;

  }

}

void loop() {

  int16_t accelX, accelY, accelZ;

  mpu.getMotion6(&accelX, &accelY, &accelZ, NULL, NULL, NULL);

  float accelX_float = accelX / 16384.0;

  float accelY_float = accelY / 16384.0;

  float accelZ_float = accelZ / 16384.0;

  accelXBuffer[bufferIndex] = accelX_float;

  accelYBuffer[bufferIndex] = accelY_float;

  accelZBuffer[bufferIndex] = accelZ_float;

  bufferIndex = (bufferIndex + 1) % BUFFER_SIZE; //circular buffer implementation 

  float emaAccelX = accelXBuffer[bufferIndex];

  float emaAccelY = accelYBuffer[bufferIndex];

  float emaAccelZ = accelZBuffer[bufferIndex];

  float alpha = 0.2;

  for (int i = 1; i < BUFFER_SIZE; i++) {

    int index = (bufferIndex + i) % BUFFER_SIZE;

    emaAccelX = alpha  accelXBuffer[index] + (1 - alpha)  emaAccelX;

    emaAccelY = alpha  accelYBuffer[index] + (1 - alpha)  emaAccelY;

    emaAccelZ = alpha  accelZBuffer[index] + (1 - alpha)  emaAccelZ;

  }

  Serial.print(accelX_float); Serial.print(",");

  Serial.print(emaAccelX); Serial.print(",");

  Serial.print(accelY_float); Serial.print(",");

  Serial.print(emaAccelY); Serial.print(",");

  Serial.print(accelZ_float); Serial.print(",");

  Serial.println(emaAccelZ);

  delay(100);

}
< /mpu6050.h >< /wire.h >

結語

在這篇博客中,我們討論了 IIR 和 FIR 濾波器之間的區(qū)別,重點討論了它們的計算效率。通過從 FIR 到 IIR 所需運算次數(shù)減少這一小例子,我們可以想象當應用規(guī)?;瘯r IIR 濾波器的效率會有多高,這對于硬件能力有限的實時應用非常重要。

我們還研究了一個使用 Arduino Uno 和 MPU6050 IMU 的示例項目,其中我們部署了一個指數(shù)移動平均濾波器來降低傳感器數(shù)據(jù)中的噪聲,同時仍然捕捉底層信號行為。最后,為了提高效率,我們提供了一個更智能的示例代碼,即采用循環(huán)緩沖區(qū)而不是在每個時間間隔移動數(shù)據(jù)。

在下一篇博客中,我們將利用 [Red Pitaya] 的 FPGA 功能來實現(xiàn)一個 4 抽頭 FIR 濾波器數(shù)字電路!

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

    關注

    162

    文章

    8205

    瀏覽量

    183981
  • 信號處理
    +關注

    關注

    49

    文章

    1076

    瀏覽量

    104615
  • ema
    ema
    +關注

    關注

    0

    文章

    4

    瀏覽量

    2482
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    信號處理簡介:移動平均濾波器

    設計電路,以任何我們想要的方式控制信號。我們竟然能夠使用電阻、電容器和運算放大器 (op-amps) 等電子元器件組合來模擬積分和微分等數(shù)學工具,這著實令人驚嘆。 例如以下電路(圖1): 圖 1:簡單的積分電路。(圖片來源:Mustahsin Zarif) 進入拉普拉斯
    的頭像 發(fā)表于 10-04 18:21 ?1230次閱讀
    <b class='flag-5'>信號</b><b class='flag-5'>處理</b>簡介:<b class='flag-5'>移動</b><b class='flag-5'>平均</b><b class='flag-5'>濾波器</b>

    橫河WT5000如何區(qū)別運用指數(shù)平均移動平均功能?

    橫河功率分析儀都有平均功能,這個功能包含兩種平均化方法,分別是指數(shù)平均移動平均(也叫線性
    的頭像 發(fā)表于 08-19 19:16 ?534次閱讀
    橫河WT5000如何區(qū)別運用<b class='flag-5'>指數(shù)</b><b class='flag-5'>平均</b>跟<b class='flag-5'>移動</b><b class='flag-5'>平均</b>功能?

    高帶通TSIF集成濾波器

    低通濾波器 高通濾波器 帶通濾波器 帶阻濾波器 全通濾波器 濾波器類型 作用 頻率特性 應用場景
    的頭像 發(fā)表于 03-20 15:42 ?593次閱讀
    高帶通TSIF集成<b class='flag-5'>濾波器</b>

    帶通濾波器的種類與技術架構

    帶通濾波器(Band-Pass Filter,BPF)是一種重要的信號處理元件,它允許特定頻率范圍內(nèi)的信號通過,同時衰減或抑制其他頻率的信號
    的頭像 發(fā)表于 02-05 16:41 ?1293次閱讀

    低通濾波器的工作原理 低通濾波器在音頻處理中的應用

    一、低通濾波器的工作原理 低通濾波器(Low Pass Filter,LPF)是一種電子濾波裝置,其主要功能是允許低頻信號通過,同時抑制高于特定截止頻率的
    的頭像 發(fā)表于 02-01 10:24 ?2112次閱讀

    低通和高通濾波器的基礎知識

    作者:Aiden Warne 低通和高通濾波器簡介 低通和高通濾波器廣泛應用于電氣工程領域。例如,這些低通和高通濾波器可用于音頻處理、圖像處理
    的頭像 發(fā)表于 01-25 16:55 ?2245次閱讀
    低通和高通<b class='flag-5'>濾波器</b>的基礎知識

    低通濾波器的常見誤區(qū)

    在電子工程和信號處理領域,低通濾波器(Low Pass Filter, LPF)扮演著至關重要的角色。它們用于去除信號中的高頻噪聲,平滑數(shù)據(jù),或者在通信系統(tǒng)中限制
    的頭像 發(fā)表于 01-21 10:02 ?967次閱讀

    常見低通濾波器類型分析

    低通濾波器(Low-pass filter, LPF)是一種允許低頻信號通過,同時阻止或減弱高頻信號的電子濾波器。在信號
    的頭像 發(fā)表于 01-21 09:50 ?2253次閱讀

    濾波器的一些常識

    濾波器簡介:濾波器是一種用于信號處理的設備或系統(tǒng),用于改變信號的頻率特性,以實現(xiàn)信號
    的頭像 發(fā)表于 12-18 17:05 ?1250次閱讀
    <b class='flag-5'>濾波器</b>的一些常識

    雙層濾波器的優(yōu)勢與劣勢

    雙層濾波器的優(yōu)勢 增強的信號分離能力 雙層濾波器通過兩個不同的濾波器通道處理信號,可以更有效地分
    的頭像 發(fā)表于 11-27 16:10 ?1052次閱讀

    分析濾波器信號處理中應用

    濾波器信號處理中的應用十分廣泛,其主要功能是從信號中去除不需要的頻率成分,保留所需的頻率成分,從而實現(xiàn)對信號的有效
    的頭像 發(fā)表于 11-27 15:56 ?2396次閱讀

    模擬濾波器到數(shù)字濾波器的轉換步驟

    將模擬濾波器轉換為數(shù)字濾波器是一個涉及多個步驟的過程,旨在保持濾波器性能的同時,適應數(shù)字信號處理的需求。以下是將模擬
    的頭像 發(fā)表于 11-26 10:03 ?2264次閱讀

    PWM信號濾波處理方法

    低通濾波器 : RC低通濾波器 :這是最常用的PWM濾波方法。通過選擇合適的電阻R和電容C值,可以設定濾波器的截止頻率,使得高于該頻率的信號
    的頭像 發(fā)表于 11-18 17:41 ?6997次閱讀

    emc濾波器原理及作用是什么

    不對其他設備造成干擾。 一、EMC濾波器的原理 EMC濾波器的原理主要基于電磁感應和電容耦合原理,通過電感、電容等元件組成的電路,對電磁信號進行濾波
    的頭像 發(fā)表于 10-22 14:29 ?3053次閱讀

    有源濾波器工作原理,以及結構

    :輸入信號通過電阻或電容耦合進入濾波器。 信號處理信號在有源濾波器內(nèi)部被
    的頭像 發(fā)表于 10-18 14:59 ?4529次閱讀