EE olmayan, yazılım API'si bağlamlarında “düşük geçiş filtresi”


12

Deneyimli bir yazılım mühendisiyim ve akıllı telefon sensörleri üzerinde çalışıyorum. DSP'de temel Enerji Verimliliği dersleri aldım ve bilgimi uygulamaya çalışıyorum. Evrişimi, transfer fonksiyonlarını, z-dönüşümünü vb. Anladığımı düşünüyorum. FIR ve IIR filtreleri hakkında biraz bilgim var.

Şimdi, yazılım API'lerini ve belgelerini okurken, insanların zaman alanındaki sensör verilerine bir LPF uyguladıklarını görüyorum. Bunu fark denklemleri kullanarak yaptığınızı biliyorum (örn. Y [i] = y [i-1] + 2 * x [i]), ama EE sınıfımda LPF'nin genellikle evrişim işlemiyle uygulandığını öğrendim burada zaman sinyalini bir iç dalga (örneğin) katsayıları ve belirli bir kesme frekansı ile birleştirirsiniz. Yani "alçak geçiren filtre" nin konuşma dili kullanımı benim için yeterli değil.

Örneğin, Google Android API'sında şu belgeler bulunur: http://developer.android.com/reference/android/hardware/SensorEvent.html#values

 public void onSensorChanged(SensorEvent event)
 {
      // alpha is calculated as t / (t + dT)
      // with t, the low-pass filter's time-constant
      // and dT, the event delivery rate

      final float alpha = 0.8;

      gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
      gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
      gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

      linear_acceleration[0] = event.values[0] - gravity[0];
      linear_acceleration[1] = event.values[1] - gravity[1];
      linear_acceleration[2] = event.values[2] - gravity[2];
 }

Bu alçak geçiren filtreyi nasıl yorumlayabilirim? Kesme frekansı nedir? Geçiş bant genişliği nedir? Bu LPF'yi sadece ortalama yapmak için mi kullanıyorlar?


iyi de beni rahatsız ediyor
Sibbs Gambling

Yanıtlar:


11

Örneğinizdeki filtre, birinci dereceden sonsuz dürtü yanıtı (IIR) filtresidir. Transfer fonksiyonu:

H(z)=1α1αz1

ki bu bir fark denklemine karşılık gelir:

y[n]=αy[n1]+(1α)x[n]

burada filtre girişi ve y [ n ] filtre çıkışıdır.x[n]y[n]

αα[0,1)α=0αα=1

α1α

α=0.8resim açıklamasını buraya girin

Örnekte, bu filtrenin, nispeten düşük frekanslı bir ilgi sinyalini açığa çıkarmaya çalışan, bir sensörden gelen bir dizi ölçümden yüksek frekanslı gürültüyü düzeltmek için kullanıldığını tahmin ediyorum. Bu, bu tür bir filtre için çok tipik bir uygulama olacaktır.

Diğer alt sorunuzda, filtrelemenin genellikle giriş sinyalinin filtrenin dürtü yanıtıyla konveksiyonu yoluyla uygulandığından emin olursunuz. Çoğu durumda, bu sadece sonlu dürtü yanıtı (FIR) filtreleri ile yapılır. Bunun gibi IIR filtreleri tipik olarak filtrenin fark denklemi kullanılarak uygulanır; bir IIR sisteminin dürtü yanıtı sonsuz uzun olduğu için, filtre ile artık kıvamı izlenebilir hale getirmek için bir miktar sonlu uzunlukta kısaltmanız gerekir, bu noktada filtre artık IIR değildir. Fark denklemi formatı, hesaplamada uygulanması neredeyse her zaman daha ucuzdur, ancak bu yapıdaki geri besleme, ele alınması gereken sayısal sorunlara yol açabilir (dahili taşma ve yuvarlama hatası birikimi gibi).


Teşekkürler! Bazı takip soruları: (1) H (z) = ... denkleminizin bir fark denklemi olduğunu söylediniz; bu gerçekten bir aktarım işlevi, değil mi? Fark denkleminin kesinlikle zaman alanı için olduğunu düşündüm. (2) Sızdıran entegratörünüzde 1.0, sampling_frequency / 2'ye (Matlab'daki gibi) karşılık geliyor mu? (3) FIR vs IIR ile ilgili olarak, benim anlayışım IIR fark denkleminin O (N) olarak uygulanabileceği, ancak evrişimin FFT tabanlı evrişim ile O (N ^ 2) veya O (NlgN) olduğu doğru mu? (4) Yazılım programcılarının bu DSP fikirlerini uygulaması için bir kitap önerebilir misiniz? Android kod örneğinin yaptığı gibi.
stackoverflowuser2010

π+πO(N)NN

(İ) Fark denkleminin uygulanmasının O (N) olduğunu biliyorum. Ama (ii) çarpma ve ekleme (songho.ca/dsp/convolution/convolution.html) üzerinde toplamı kullanan evrişim işleminin FFT tabanlı bir uygulama ile O (N ^ 2) veya O (N lgN) olduğunu düşündüm. . Her durumda, N filtre sırasıdır - burada filtre sırasının ve zaman sinyali uzunluğunun aynı büyüklük sırası olduğunu varsayıyorum (örneğin her ikisi de 256). Yani (i) ve (ii) farklı değil mi? Ayrıca, Lyons.com'un Amazon.com'daki kitabını gördüm, ancak C / Java yazılım programcıları için daha fazla yazılmış bir şey umuyordum.
stackoverflowuser2010

1
O(N) NO(N2)MNO(MN)MN
Jason R

O(M×(N+M))iNO(N2)O(NM)
stackoverflowuser2010

2

Özetlemek gerekirse, RC filtresi gibi basit idealize edilmiş fiziksel modellere dayanan IIR filtrelerinde az sayıda kutup ve sıfır bulunur ve bu nedenle az sayıda kutup veya sıfır çok az aritmetik işlem anlamına geldiğinden genellikle bir fark denklemi olarak uygulanır. fark denklemi kullanarak numune başına.

Bir IIR sonsuz uzunlukta bir dürtü yanıtı gerektirdiğinden, evrişim sonsuza kadar hesaplanmayı ya da bir yaklaşımın kullanılmasını gerektirir.

FIR filtreleri genellikle sonlu uzunluktaki dürtü yanıtı ile evrişim (ya da eğer filtre hesaplama açısından verimli olacak kadar uzunsa FFT hızlı evrişim) ile uygulanır. Bu tür filtreler, Z-düzlem kutuplarının ve sıfırlarının nerede olabileceğini bilmek yerine, bir sonlu uzunluk dürtü yanıtı ile istenen bir frekans yanıtı spesifikasyonuna yaklaşabildiği zaman daha sık kullanılır.

Bununla birlikte, keskin bir spesifikasyona sahip bir filtre uzun bir FIR kıvrımını gerektirdiğinden, FIR filtrelerinin uygulanması çok daha yavaş olabilir ve kurulum daha fazla kod satırı içerebilir, bu nedenle FIR filtreleri basit yazılımlarda sıklıkla kullanılmayabilir örnekleri.


0

Kendimi bu gönderiye tekrar tekrar gelirken buldum. Soruyu sorduğunuz için teşekkür ederim. Burada, C'deki (mikrodenetleyici için tasarlanmış) sızdıran entegratörün büyük, hesaplama dostu bir uygulaması.

İlk olarak, bazı yeniden düzenleme: y = α * x + (1 - α) * y_last = α * (x - y_last) + y_last

α'yı yaklaşık% 12,% 25,% 50, (1/8, 1/4, 1/2, ...) ile sınırlarsak. Bazı verimli bit kaydırma özelliklerinden yararlanabiliriz. 1/8, 8 => 2 ^ 3 => (3 kez vites küçültme)

= (x - y_last) / 8 + y_last

#define SMOOTHING_FACTOR       (3)

int16_t FilterSample(int16_t new_sample)
{
  static int16_t last_result = 0;

  // Each bit shift down is equivalent to dividing-by-two
  last_result = (new_sample - last_result) >> SMOOTHING_FACTOR) + last_result;

  return last_result;
}

Umarım yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.