Ve článku 1-Wire barometr s ADS1100 je místo problematické filtrace RC článkem zmiňována její digitální náhrada.
Jak na to s omezenými prostředky PIC ? V úvahu přichází - průměrování N posledních hodnot
- použít medián tj. prostřední hodnotu z N posledních hodnot
- použít vážený průměr z předchozího průměru a naměřené hodnoty
Průměrování z N posledních hodnot je celkem běžně používané, jeho dynamická odezva na změnu je konstantní a start je dána jen naplněním pole N vzorků. Z HW vyžaduje jen paměť na N vzorků, z SW realizovat kruhový buffer a operaci sčítání a dělení (resp. typičtěji posuv, při N zvoleném jako mocnina 2). Medián může být někdy jednodušší a u některých měření i vhodnější, když výsledná hodnota může nabývat jen několika diskrátních hodnot. Spočívá v tom, že se naměřené hodnoty setřídí a jako výsledná hodnota se použije prostřední hodnota. Nicméně naonec jsem použil vážený průměr z předchozího průměru a naměřené hodnoty. Tento algoritmus více-méně napodobuje chování klasického integračního RC článku. Nicméně stejně jako analogové počítače používají obvody pro nastavení výchozích podmínek na integračním článku, tak je i při použití tohoto algoritmu vhodné počítat s obdobným řešením. Zrychlí se tím start po výpadku napájení. Konkrétně algoritmus používá 16ti bitový, 16ti stupňový filtr realizující funkci AVE = (15*AVE +NEW)/16 tj. ze nová hodnota se uplatní ve výsledku pouze z 1/16 a z 15/16 se uplatní předchozí průměr. ; 16 bit 1/2/../16/../256 step Averageing filter by Radek Benedikt ; ; input ; new1(MSB)new0(LSB) ; output ; ave2(MSB)ave1(LSB) ; AVE = (15*AVE +NEW)/16 ; the formula can be rewrite as: ; AVE = AVE + (NEW - AVE)/16 ; avg clrf new2 ; expand 16 bit to 24 bit btfsc new1,7 ; expand sign decf new2,f clrf ave3 ; expand 16(24) bit to 24(32) bit btfsc ave2,7 ; expand sign decf ave3,f ; new' = new - ave movf ave1,w ; sub low bytes subwf new0,f movf ave2,w ; sub mid bytes skpc ; carry_in, so just sub incfsz ave2,w ; add carry_in to ave2 subwf new1,f ; sub and propagate carry_out movf ave3,w ; sub high bytes skpc ; carry_in, so just sub incfsz ave3,w ; add carry_in to ave3 subwf new2,f ; sub and propagate carry_out btfss skipOutVar goto avggo btfsc new2,7 ; test sign goto avggoM movf new2,w btfss STATUS,Z return movf new1,w btfss STATUS,Z return goto avggo avggoM incf new2,w btfss STATUS,Z return incf new1,w btfss STATUS,Z return avggo ; avg precision, std *16/256 movf avgPR,w movwf avgCNT avglop bcf STATUS,C rlf new0,f ; *2 rlf new1,f rlf new2,f decfsz avgCNT,f goto avglop ; ; (std mode) ave = ave + 16*(new - ave)/256 movf new0,w ; add low bytes addwf ave0,f movf new1,w ; add mid bytes skpnc ; no carry_in, so just add incfsz new1,w ; add carry_in to new1 addwf ave1,f ; add and propagate carry_out movf new2,w ; add high bytes skpnc ; no carry_in, so just add incfsz new2,w ; add carry_in to new2 addwf ave2,f ; add and propagate carry_out return Detailní pohled do kódu ukáže dvě proměnné, složící k "tunningu" algoritmu¨ avgPR - udává počet vzorků použitých pro průměrování, pro 16 vzorků je roven 4, pro nastartování algoritmu tj. 1 vzorek je roven 8, pro 4 vzorky je roven 6 skipOutVar - bitová proměnná, pokud je On, tak se do průměru nezahrne hodnota lišící se od průměru o více než 255. Jejich použití je vidět nejlépe ze startovací sekvence po zapnutí movlw 0x08 movwf avgPR ; init averageing filter call adscan9 ; exec Convert Sensor movlw 0x06 movwf avgPR call adscan ; exec Convert Sensor call adscan ; exec Convert Sensor movlw 0x04 movwf avgPR bsf skipOutVar
Nejprve se de facto vypne průměrování a do průměru se nakopíruje i když trochu složitě naměřená hodnota z A/D převodníku. Teoreticky může být tato hodnota "ulétnutá" komunikace s A/D převodníkem nemá žádnou kontrolu na chyby. Proto se vzápětí přejde na režim průměrování s váhou 1/4 a s touto váhou se provedou dvě měření. Poté se přejde na režim průměrováni 1/16 a zapne se režim ignorování hodnot lišících se o více než 255. Ve zdrojovém textu baro.asm je vidět detailně celý kód pro komunikaci s ADS1100 a zpracování dat z něj. Popis 1-wire komunikace (modul 1wire675.inc) zas někdy příště. |