Diğerlerinin de belirttiği gibi, şu anda kullandığınız FIR (sonlu dürtü yanıtı) filtresinden ziyade bir IIR (sonsuz dürtü yanıtı) filtresi düşünmelisiniz. Dahası var, ama ilk bakışta FIR filtreleri açık dönüşümler ve denklemli IIR filtreleri olarak uygulandı.
Mikrodenetleyicilerde çok kullandığım IIR filtresi tek kutuplu düşük geçişli bir filtredir. Bu, basit bir RC analog filtrenin dijital eşdeğeridir. Çoğu uygulama için, bunlar kullandığınız kutu filtresinden daha iyi özelliklere sahip olacaktır. Karşılaştığım bir kutu filtresinin çoğu, dijital sinyal işleme sınıfında özel özelliklerine ihtiyaç duyulmasının bir sonucu olarak dikkat etmeyen birinin sonucudur. Yalnızca gürültü olduğunu bildiğiniz yüksek frekansları azaltmak istiyorsanız, tek kutuplu düşük geçiş filtresi daha iyidir. Mikrodenetleyicide birini dijital olarak uygulamanın en iyi yolu genellikle:
FİLT <- FİLT + FF (YENİ - FİLT)
FILT kalıcı bir durumdur. Bu, bu filtreyi hesaplamanız için gereken tek değişkendir. YENİ, filtrenin bu yinelemeyle güncellenmekte olduğu yeni değerdir. FF, filtrenin "ağırlığını" ayarlayan filtre kısmıdır. Bu algoritmaya bakın ve FF = 0 için çıkışın hiç değişmediğinden filtrenin sonsuz ağır olduğunu görün. FF = 1 için, çıktı sadece girişi takip ettiğinden dolayı aslında hiçbir filtre yoktur. Faydalı değerler arasındadır. Küçük sistemlerde FF'yi 1/2 N olacak şekilde seçersiniz.Böylece FF ile çarpma N bitiyle sağa kayma olarak gerçekleştirilebilir. Örneğin, FF 1/16 olabilir ve bu nedenle FF ile çarpılır, 4 bitlik sağa kayma. Aksi halde, bu filtre yalnızca bir çıkarma ve bir toplama işlemi gerektirir, ancak sayıların genellikle giriş değerinden daha geniş olması gerekir (aşağıda ayrı bir bölümde daha fazla sayısal hassasiyetle).
Genellikle A / D okumalarını gerekenden çok daha hızlı alırım ve bu filtrelerden ikisini uygularım. Bu serideki iki RC filtresinin dijital eşdeğeridir ve geri alma frekansının üstünde 12 dB / oktav azaltır. Bununla birlikte, A / D okumaları için, zaman cevabındaki filtreye bakmak, zaman cevabını dikkate alarak daha uygundur. Bu, ölçtüğünüz şey değiştiğinde sisteminizin ne kadar hızlı bir değişiklik göreceğini söyler.
Bu filtrelerin tasarlanmasını kolaylaştırmak için (yalnızca FF seçmek ve kaç tanesinin basamaklandırılacağına karar vermek anlamına gelir), programımı FILTBITS kullanıyorum. Basamaklı filtre serisindeki her FF için kaydırma bitlerinin sayısını belirtirsiniz ve adım cevabını ve diğer değerleri hesaplar. Aslında bunu genellikle PLOTFILT sarma betiğimden geçiriyorum. Bu, bir CSV dosyası yapan FILTBITS uygulamasını çalıştırır ve ardından CSV dosyasını çizer. Örneğin, burada "PLOTFILT 4 4" sonucudur:
PLOTFILT parametresindeki iki parametre, yukarıda açıklanan türde basamaklı iki filtre olacağı anlamına gelir. 4 değerleri, FF ile çarpımı gerçekleştirmek için vardiya bitlerinin sayısını gösterir. Bu nedenle iki FF değeri bu durumda 1/16'dır.
Kırmızı iz, birim adım tepkisidir ve bakılması gereken en önemli şeydir. Örneğin, eğer giriş anında değişirse, birleştirilmiş filtrenin çıktısının 60 yinelemede yeni değerin% 90'ına yerleşeceğini söyler. % 95 uzlaşma süresini önemsiyorsanız, yaklaşık 73 yineleme beklemeniz gerekir ve% 50 uzlaştırma süresi için yalnızca 26 yineleme beklemeniz gerekir.
Yeşil iz size tek bir tam genlikli ani çıkışını gösterir. Bu size rastgele gürültü bastırma hakkında bir fikir verir. Tek bir numunenin çıktıda% 2,5'ten fazla bir değişikliğe neden olmayacağı görülüyor.
Mavi iz, bu filtrenin beyaz gürültü ile ne yaptığı hakkında öznel bir his vermek. Bu zorlu bir test değildir, çünkü PLOTFILT'in bu çalışması için beyaz gürültü girişi olarak seçilen rasgele sayıların içeriğinin tam olarak ne olduğuna dair hiçbir garanti yoktur. Sadece size ne kadar ezileceği ve ne kadar pürüzsüz olacağı hakkında kabaca bir his vermek.
PLOTFILT, belki FILTBITS ve özellikle PIC ürün yazılımı gelişimi için pek çok faydalı şey Yazılım İndirme sayfamdaki PIC Development Tools yazılım sürümünde bulunmaktadır .
Sayısal hassasiyet hakkında eklendi
Yorumlardan ve şimdi yeni bir cevap görüyorum ki bu filtreyi uygulamak için gereken bit sayısını tartışmaya ilgi var. FF ile çarpmanın , ikili noktanın altında Log 2 (FF) yeni bitler yaratacağını unutmayın . Küçük sistemlerde, FF genellikle 1/2 N olarak seçilir , bu çarpma gerçekte N bitlerinin sağa kayması ile gerçekleşir.
FILT bu nedenle genellikle sabit nokta tamsayıdır. Bunun, matematiğin hiçbirini işlemcinin bakış açısından değiştirmediğini unutmayın. Örneğin, 10 bit A / D değerlerini ve N = 4 (FF = 1/16) değerlerini filtreliyorsanız, 10 bitlik A / D değerlerinin altında 4 kesir bit gerekir. En işlemcilerden biri, 10 bit A / D okumaları nedeniyle 16 bit tamsayı işlemi yapıyor olacaksınız. Bu durumda, tam olarak aynı 16 bit tamsayı işlemlerini yine de yapabilirsiniz, ancak A / D okumalarını 4 bit kaydırılmış halde bırakın. İşlemci farkı bilmiyor ve gerekmiyor. Matematiğin tamamını 16 bit tam sayılar üzerinde yapmak, onları 12,4 sabit nokta veya gerçek 16 bit tam sayılar (16,0 sabit nokta) olarak kabul ettiğinizde çalışır.
Genel olarak, sayısal gösterime bağlı olarak gürültü eklemek istemiyorsanız, her bir filtre direğine N bit eklemeniz gerekir. Yukarıdaki örnekte, ikisinin ikinci filtresinin bilgi kaybetmemek için 10 + 4 + 4 = 18 bit olması gerekir. Pratikte 8 bitlik bir makinede 24 bitlik değerler kullanacağınız anlamına gelir. Teknik olarak sadece ikisinin ikinci kutbu daha geniş bir değere ihtiyaç duyacaktır, ancak ürün yazılımı sadeliği için, genellikle bir filtrenin tüm kutupları için aynı gösterimi ve dolayısıyla aynı kodu kullanırım.
Genellikle bir filtre direği işlemi gerçekleştirmek için bir alt yordam veya makro yazıyorum, sonra bunu her bir direğe uyguladım. Bir alt rutininin mi yoksa makronun da bu projede döngülerin veya program belleğinin daha önemli olup olmamasına bağlı olduğu. Her iki durumda da, FILT'yi güncelleyen alt rutine / makroya YENİ'yi iletmek için bazı çizik durumları kullanıyorum, ancak aynı zamanda bunları YENİ olan aynı çizik durumuna yüklüyorum. Bir sonrakinin YENİ. Bir alt yordam olduğunda, FILT'den hemen sonra güncellenen FILT'ye bir işaretçi işaretinin gelmesi yararlı olur. Bu şekilde alt yordam, birden çok kez çağrılırsa bellekteki ardışık filtrelerde otomatik olarak çalışır. Her yinelemede işlem yapmak için adresi girdiğiniz için bir makro ile bir işaretçiye ihtiyacınız yoktur.
Kod örnekleri
PIC 18 için yukarıda açıklandığı gibi bir makro örneği:
////////////////////////////////////////////////// //////////////////////////////
//
// Makro FİLTRE süzgeci
//
// NEWVAL'deki bir filtre çubuğunu yeni değerle güncelleyin. NEWVAL, güncellendi
// yeni filtrelenmiş değeri içerir.
//
// FILT, filtre durumu değişkeninin adıdır. 24 bit olduğu varsayılır
// geniş ve yerel bankada.
//
// Filtrenin güncellenmesi için formül:
//
// FİLT <- FİLT + FF (YENİDEN - FİLT)
//
// FF ile çarpma, FILTBITS bitlerinin sağa kayması ile gerçekleştirilir.
//
/ makro filtresi
/yazmak
dbankif lbankadr
movf [arg 1] +0, w; YENİDEN <- YENİDEN - FİLT
subwf newval + 0
movf [arg 1] +1, w
subwfb newval + 1
movf [arg 1] +2, w
subwfb newval + 2
/yazmak
/ loop n filtbit; her bit için NEWVAL sağa kaydırmak için bir kez
rlcf newval + 2, w; NEWVAL doğru bir bit kaydırma
rrcf newval + 2
rrcf newval + 1
rrcf newval + 0
/ endloop
/yazmak
movf newval + 0, w; filtreye kaydırılan değeri ekleyin ve NEWVAL'e kaydedin
addwf [arg 1] +0, w
movwf [arg 1] +0
movwf newval + 0
movf newval + 1, w
addwfc [arg 1] +1, w
movwf [arg 1] +1
movwf newval + 1
movf newval + 2, w
addwfc [arg 1] +2, w
movwf [arg 1] +2
movwf newval + 2
/ endmac
Ve burada PIC 24 veya dsPIC 30 veya 33 için benzer bir makro:
////////////////////////////////////////////////// //////////////////////////////
//
// Makro FİLTRE ffbits
//
// Bir düşük geçişli filtrenin durumunu güncelleyin. Yeni giriş değeri W1: W0
// ve güncellenecek filtre durumu W2 ile gösterilir.
//
// Güncellenen filtre değeri W1'de de döndürülecek: W0 ve W2 gösterecek
// filtre durumunu geçen ilk hafızaya. Bu nedenle bu makro olabilir.
// art arda kademeli düşük geçişli filtreler dizisini güncellemek için çağrılır.
//
// Filtre formülü:
//
// FİLT <- FİLT + FF (YENİ - FİLT)
//
// FF ile çarpım, aritmetik sağa kayması ile gerçekleştirilir.
// FFBITS.
//
// UYARI: W3 çöktü.
//
/ makro filtresi
/ var new ffbits integer = [arg 1]; kaydırılacak bit sayısını al
/yazmak
/ write "; Bir kutup düşük geçişli filtreleme gerçekleştirin, kaydırma bitleri =" ffbits
/yazmak " ;"
alt w0, [w2 ++], w0; YENİ - FİLT -> W1: W0
alt w1, [w2 -], w1
lsr w0, # [v ffbits], w0; sonucu W1: W0 yönünde kaydır
sl w1, # [- 16 ffbit], w3
ior w0, w3, w0
asr w1, # [v ffbits], w1
w0 ekle, [w2 ++], w0; W1: W0’da nihai sonucu elde etmek için FILT ekleyin
addc wl, [w2--], wl
mov w0, [w2 ++]; sonucu filtre durumuna yaz, ilerletici gösterici
mov w1, [w2 ++]
/yazmak
/ endmac
Bu örneklerin her ikisi de, yerleşik makro olanaklarından her ikisinden daha yetenekli olan PIC assembler ön işlemcimi kullanarak makro olarak uygulanır .