Kararlı ADC için dijital filtre

Başlatan Analogic, 13 Aralık 2011, 22:44:02

Hattuşa

Alıntı yapılan: ete - 30 Ocak 2015, 11:40:23
Bu filtrenin mantığı, okunan 10 bitlik adc değerlerinden seçiminize bağlı olarak daha büyük bit değerine sahip adc değerleri elde ederek çözünürlüğü yazılımsal olarak artırıp ufak ripple değerlerini elimine etmeye dayanmaktadır.
Daha iyi anlamanız için şu örneği verebiliriz,
Ön seçim olarak bit saysını siz seçiyorsunuz. Diyelimki 12 bit seçtik.
Alt program gidilince,
Datacount=16 olarak hesaplanmaktadır. Bu bir seferinde 16 adc okuması yapılacağını gösteriyor.
Datadivisör=4 olarak hesaplanıyor. Bu okunan adcler toplamının sonunda 4 e bölüneceğini gösteriyor.
16 adet adc okuması yapılıyor ve üst üste toplanıyor. Toplam değer 16 biti aşınca 32 bit lik değer elde etmek için 32 bitin high tarafı bir artırılıyor.
Sonuçta elde edilen değerler PBP nun 32 bit hesaplama registerlerine yerleştirilip önce 32 bitlik değer datadivisör değerine bölünüyor. Elde edilen değer tekrar advalue değerine eşitlenerek geri dönülüyor. Dönen değer 10 bitlik 16 adet adc okumasının 12 bitlik ortalaması olarak düşünülebilir.
Ete


@ete hocam yani bu filtrenin çalışabilmesi için 16 adet adc mi okunması gerekiyor, yoksa benmi yanlış anlıyorum.

ete

Datacount=16 olarak
olarak lookup tablosundan okunuyor. Seçtiğin bit sayısına göre kaç okuma yapılacağı Lookup tablosundan okunuyor ve program bu kadar okumayı otomatik olarak yapıyor senin bir şey yapman gerekmiyor. Yapacağın tek şey kaç bitlik sayı elde edeceğini belirlemek. Bu yüzden kendi programının başlarında;
ADbits = 12                 ; set to 12-bit resolution
şeklinde kaç bit çalışacağını belirliyorsun.
Include dosyasında ise;
LOOKUP2 ADbits-10,[ 1, 4,16,64,256,1024,4096],DTadCount
komut satırı seçtiğin bit sayısına göre kaç okuma yapacağını belirliyor.
ADbits-10 hesabında sen 12 bit seçmiş isen 12-10=2 çıkıyor. Lookup tablosunda;
0=1
1=4
2=16
3=64
şeklinde gidiyor. demekki 13 bit seçersen okunacak örnek sayısı 64 oluveriyor.
Ete

Hattuşa

hocam şunun için sordum;
adc okunan noktamda peş peşe 16 okuma yapmak, okunan sinyalimin kaçırılması demektir. onun yerine

şu şekilde yapsam olur mu;


adc =adin 0

adc16 =adc 15
adc15 =adc14
adc14 =adc13
adc13 =adc12
..
...
adc0 =adc



ben ana döngümde 16. adc yi okutup değişkene attığımda eldeki adc16,adc15,.....adc0 olan 16 adc değere ulaştığımda filtreyi devreye sokup çalıştırsam olur mu?umarım ne demek istediğimi anlamışsınızdır. bunu şunun için söylüyorum. bir sinüs sinyalinin 0 noktasını yakalayıpta bu 0 noktasına göre belirli bir noktadan adc okutan birisi okuttuğu adc değerlerini yukarıdaki gibi unutulan geçmiş filtre değişkenlerine atarak bu değerlerle bu filtreyi çalıştırabilirmi?

ete

Ne yapmak istediğini anlamadım. Kullanmak istediğin sistemde zaten bir nevi ortalama alma metodudur. Geçmişte okunanların ortalamasına dahil etmiş olursun kendini. Bunun üzerine ayrıca bit sayısını artırmanın gereği yok diye düşünürüm.
Diğer taraftan 1-20us s,ren bir adc okuma işleminde 16 tane ard arda okuma yapmakla bir şeyide kaçırmış olmazsın sanırım.

Ete

Hattuşa

Alıntı yapılan: pro-TR - 29 Ocak 2015, 21:32:19
@ete hocam
bahsettiğiniz filtre bumudur? ben sitenin arşivine girip bu kodu bulabildim. (bir arkadaşımın yardımı ile)

DEFINE OSC 20
INCLUDE "DT_Analog.pbp"     ; DT's 16-bit Analog Module

DEFINE ADC_BITS 10          ; Set-up ADC for fast 10-bit results
DEFINE ADC_CLOCK 2
DEFINE ADC_SAMPLEUS 5

;----[Change these to match your hardware]----------------------------------
DEFINE LCD_DREG    PORTB    ; LCD Data Port
DEFINE LCD_DBIT    0        ; Starting Data Bit
DEFINE LCD_RSREG   PORTB    ; Register Select Port
DEFINE LCD_RSBIT   4        ; Register Select Bit
DEFINE LCD_EREG    PORTB    ; Enable Port
DEFINE LCD_EBIT    5        ; Enable Bit
DEFINE LCD_BITS    4        ; Data Bus Size
DEFINE LCD_LINES   2        ; Number of Lines on LCD
DEFINE LCD_COMMANDUS  2000  ; Command Delay time in uS
DEFINE LCD_DATAUS  50       ; Data Delay time in uS

ADCON1 = %10001101          ; right justify, AN0 & AN1 analog
PAUSE 250 : LCDOUT $FE,1    ; Initialize LCD
PAUSE 100 : LCDOUT $FE,1    ;  not all LCDs need both lines

ADbits = 12                 ; set to 12-bit resolution
;---------------------------------------------------------------------------
Main:
  FOR ADchan = 0 to 1       ; Do both AN0 and AN1
    GOSUB GetADC            ; Get A/D value
    IF ADchan = 0 THEN
       LCDOUT $FE, $80      ; LCD line 1
    ELSE
       LCDOUT $FE, $C0      ; LCD line 2
    ENDIF
    LCDOUT "CH-",DEC1 ADchan," = ",DEC ADvalue,"   "
  NEXT ADchan
GOTO Main:



'****************************************************************
'*  Name    : DT_Analog.pbp                                     *
'*  Author  : Darrel Taylor                                     *
'*  Notice  : Copyright (c) 2009                                *
'*  Date    : 5/23/2009                                         *
'*  Version : 1.0                                               *
'*  Notes   : Up to 16 bit A/D with a 10-bit A/D converter      *
'*          : http://en.wikipedia.org/wiki/Oversampling         *
'****************************************************************
GOTO OverDTAnalog

ADchan       VAR BYTE        ; global - A/D channel to use
ADbits       VAR BYTE        ; global - # of bits in result
ADvalue      VAR WORD        ; global - the final A/D value
ADmax        VAR WORD        ; global - Max A/D value at this resolution
;--------------------
DTadCount    VAR WORD        ; local - sample count
DTadDivisor  VAR WORD        ; local - averaging divisor
DTadShiftR   VAR BYTE        ; local - bits to shift for UnderSampling
DTadAccum    VAR WORD[2]     ; local - 32-bit sample accumulator

;---------------------------------------------------------------------------
GetADC:
  IF (ADbits >= 10) THEN
    DTadShiftR = 0   ; 10 11 12 13  14   15   16
    LOOKUP2 ADbits-10,[ 1, 4,16,64,256,1024,4096],DTadCount
    LOOKUP  ADbits-10,[ 1, 2, 4, 8, 16,  32,  64],DTadDivisor
  ELSE
    DTadCount = 1
    DTadDivisor = 1
    DTadShiftR = 10 - ADbits
  ENDIF 
  LOOKUP2 ADbits,[0,1,3,7,15,31,63,127,255,511,1023, _
                  2046,4092,8184,16368,32736,65472],ADmax
 
  DTadAccum = 0 : DTadAccum[1] = 0     ; clear the accumulator
DTadLoop:
  ADCIN  ADchan, ADvalue               ; get 10-bit sample
  DTadAccum = DTadAccum + ADvalue      ; add it to the accumulator
  IF DTadAccum < ADvalue THEN          ; if low word overflowed
     DTadAccum[1] = DTadAccum[1] + 1   ;   increment the high word
  ENDIF
  DTadCount = DTadCount - 1            ; done with this sample
  IF DTadCount > 0 THEN DTadLoop       ; loop if not done with ALL samples
 
  R2 = DTadAccum                       ; put 32-bit accumulated value in PBP
  R0 = DTadAccum[1]                    ;   registers, prepare for DIV32
  ADvalue = DIV32 DTadDivisor          ; get the average value
  ADvalue = ADvalue >> DTadShiftR      ; Shift right if < 10-bit
RETURN
OverDTAnalog:


slm arkadaşlar bu filtreyi protona uyarlayamadım bir türlü, R2 ve R0 değerleri nedir? bunu proton koduna çevirebilecek arkadaşlara şimdiden tşk ederim.

Hattuşa

@ete hocam bu filtreyi deneyemedim henüz, R0 ve R2 değişkenleri nedir?

Alıntı YapR2 = DTadAccum                       ; put 32-bit accumulated value in PBP
  R0 = DTadAccum[1]                    ;   registers, prepare for DIV32

bu kısım hata veriyor. yani kopyele yapıştırı bile beceremiyoum, acaba yardımcı olurmusunuz?

ete

PBP da derleme yapılınca derleyici bazı değişken adlarını özel amaçlar için kullanır.
Mesela 32 bitlik bir işlem yaptığı zaman (A=300 * 2550) bu rakamı hafızada tutamaz. Sonuç 32 bitliktir. Bu 32 bitlik değeri R0-R1-R2-R3 isimli kendi değişkenlerinde tutar.
Sonra DIV 32 komutunu kullandığın zaman oradan değeri alıp bölme işlemini yapar. İşte bahsi geçen R0-R2 değişkenleri bunlardır.
Protonda da olması gerekir ama hangileridir bilemiyorum.
Şayet Proton karşılıklarını bulamıyor isen yapman gereken şey bir 32 bitlik değişken tanımlayıp (VER olsun 2 WORD uzunluğunda) Ver değişkeninin word sıralaması Word1.Word0 şeklinde olacaktır.
DTadAccum[0] bir word değişkenidir. Bu değişkeni VER isimli 32 bit değişkenin Word0 konumuna yerleştir.
Diğer DTadAccum[1] değişken değerinide Ver isimli değişkenin ikinci Word konumuna yerleştir.
DIM VER AS LONG
DIM VER0 AS WORD
DIM VER2 AS WORD

VER0 = DTadAccum[0]                      'VER değişkenleri 32 bitlik VER isimli değişkenin  ; put 32-bit accumulated value in PBP
  VER2 = DTadAccum[1]                    ;   registers, prepare for DIV32
VER.word0=VER0
Ver.Word1=VER2 şeklinde

ADvalue = VER /DTadDivisor  şeklinde de bölmeyi yapıver olsun bitsin.

Ete

Burak

#52
Alıntı yapılan: ete - 11 Şubat 2015, 17:30:54
PBP da derleme yapılınca derleyici bazı değişken adlarını özel amaçlar için kullanır.
Mesela 32 bitlik bir işlem yaptığı zaman (A=300 * 2550) bu rakamı hafızada tutamaz. Sonuç 32 bitliktir. Bu 32 bitlik değeri R0-R1-R2-R3 isimli kendi değişkenlerinde tutar.
Sonra DIV 32 komutunu kullandığın zaman oradan değeri alıp bölme işlemini yapar. İşte bahsi geçen R0-R2 değişkenleri bunlardır.
Protonda da olması gerekir ama hangileridir bilemiyorum.
Şayet Proton karşılıklarını bulamıyor isen yapman gereken şey bir 32 bitlik değişken tanımlayıp (VER olsun 2 WORD uzunluğunda) Ver değişkeninin word sıralaması Word1.Word0 şeklinde olacaktır.
DTadAccum[0] bir word değişkenidir. Bu değişkeni VER isimli 32 bit değişkenin Word0 konumuna yerleştir.
Diğer DTadAccum[1] değişken değerinide Ver isimli değişkenin ikinci Word konumuna yerleştir.
DIM VER AS LONG
DIM VER0 AS WORD
DIM VER2 AS WORD

VER0 = DTadAccum[0]                      'VER değişkenleri 32 bitlik VER isimli değişkenin  ; put 32-bit accumulated value in PBP
  VER2 = DTadAccum[1]                    ;   registers, prepare for DIV32
VER.word0=VER0
Ver.Word1=VER2 şeklinde

ADvalue = VER /DTadDivisor  şeklinde de bölmeyi yapıver olsun bitsin.

Ete

Hocam bu R0-R1-R2-R3 ifadeleri PicBasic'te ön tanımlı olan WORD tipi değişkenler mi ?

Diyelim ki 32 bitlik bir çarpma yaptık ... DIV32 ile bölme işlemini hemen bir satır sonra yapmakta istemiyorum bu durumda R0,1,2,3 dahili derleyici değişkenlerini kendi oluşturduğum değişkenlere aktarıp istediğim zaman bu değişkenlere geri yükleyip div32 kullansam olur mu ?

Mesela ;


a var word
b  var word
c  var word
d  var word
e  var word
f  var word
a=b*c

d=R0 : e=R1

'.....
'bir blok işlem
'.....
R0=d
R1=e

f=div32 290




Burak
Ω Gens Una Sumus Ω

ete

Darrel taylor öyle yapmış. Mantık olarak basic in 32 bitlik çarpımları bir değişkende saklaması gerektiğini biliyordum. Ama hangileri bilmiyordum. Bu programla öğrenmiş oldum. R0-R1-R2 bu iş için ayrılmış değişkenler.

Ete

Burak

Yıllar geçti ve ben bunu bugün öğrendim hocam :) Çünkü PBP manual'de de yazmıyo hiçbişi .. Çok az bi bahsi geçmiş sadece RAM allocation bölümünde ama açıklamalı bir ifade yok ...

Peki ;

Bu işlemlendirme sadece çarpmalar için değildir bu durumda , çünkü filtrede akümülasyon sonucunu yüklemişler R değişkenlerine .. Bu durumda ben 16 bit sınırlarını aşan bir toplama yaptığımda da bu işlem sonucunu R değişkenlerinden çekebileceğim ... Siz ne düşünüyosunuz Hocam ?

Burak
Ω Gens Una Sumus Ω

ete

Denemek lazım diyorum. Bir ara deneyeceğim.

Ete

Hattuşa

slm arkadaşlar; ;D  ;D  ;D

bu konuyu gene hortlattım sanırım,KALMAN filtresi nedir? basic dilinde KALMAN filtresi algoritması yapılamıyormu? bununla ilgili yardımcı olacak arkadaşlar yokmu?

Burak

Tam olarak neden KALMAN filtresini öğrenmek istiyosunuz , kullanım alanı neresi olucak ?

Burak
Ω Gens Una Sumus Ω

Hattuşa

Alıntı yapılan: Burak GÜNAY - 30 Aralık 2015, 20:54:29
Tam olarak neden KALMAN filtresini öğrenmek istiyosunuz , kullanım alanı neresi olucak ?

Burak

burak usta bir ivme sensörü buldum biryerlerden 3 eksenli, onu I2C ile haberleştirip dataları aldım ama datalar çok oynak birkaç arkadaşa sordum stabil hale getirmek için ne yapmalıyız diye onlarda KALMAN cevabını verdiler.

Burak

Kalman bir öngörü filtresidir ... Estimasyon yapar .. yani 3 noktasi bilinen bir egrinin olasi bir sonraki noktasini belirlemede kullanilir ... Aslinda sizin daha cok bubble sort turevi filtreleri baz almaniz gerek diye dusunuyorum ...

Burak
Ω Gens Una Sumus Ω

Powered by EzPortal