Zdravím, prosím Vás, jáke používéte nejčastěji metody na programové ošetření výkyvů vstupních hodnot?
administrator: přejmenováno z "Ošetření vstupních hodnot"
Zdravím, prosím Vás, jáke používéte nejčastěji metody na programové ošetření výkyvů vstupních hodnot?
administrator: přejmenováno z "Ošetření vstupních hodnot"
Chtel bych pouzit a porovnat par metod, nevim ted presne jake se pouzivaji a jak je aplikovat, muzete mi tu napsat par prikladu? diky.
Zkus trochu upřesnit co myslíš těmi výkyvy.
Je to nestabilita hodnoty při AD převodu, nebo kmitání výstupu tlačítek při změně stavu? Něco jiného?
U AD převodu je nezbytné v první řadě dodržet správné blokování a filtraci všech napájecích větví kolem mcu. Pak je možnost používat během měření úsporný režim (noise canceling mode) a nakonec sw filtrace. Tu poslední lze provádět třeba obyčejným průměrováním (o pár tiků rychlejší, více způsobů, ale nestabilita LSB se nedá zcela eleminovat) nebo zavést hysterezi, a do třetice je možný digitální filtr.
Takze, problem neni v AD prevodu. Ale uz ty hodnoty co do nej lezou, rekneme z potenciometru. Kdyz dochazi k posunu haze vetsi hodnoty, pri zastaveni se ustali nize na skutecne hodnote. Zas tak moc to resit neni treba. Chci jen porovnat par metod. Nasel jsem si neco o pointrech, a jeden pekny kod FIFO (zjednodusil jsem si ho), nacitam 20 hodnot z prevodniku z kterych dela prumer a potom neustale nacita a vraci posledni zprumerovanou hodnotu. Kod prikladam v priloze. Problem je ze bych chtel i neco vic nez jen prumer, dalsi filtracni metody, koukal jsem nejaka dolni propust, nasel jsem grafy a teorii ale ne aplikaci…a je tu jeste pozadavek na gaussovo rozdeleni, ale nevim jak to zakomponovat do programu:-( Staci mi jen napsat dve tri funkce, ja si o tom neco najdu a zapisu to tam.
Vlozeny kod jsem si poupravil odtud:
users.ece.utexas.edu/~valvano/em … /chap7.htm
Ale staci se mrknout jen na ten muj, je mi celkem jasny a mel by fungovat, hodne zjednodusen pro muj pripad.
je tam cteni z AD prevodniku a poslani na PWM, to nereste, tyto funkce mi funguji.
Diky moc za zkouknuti.
administrator: příspěvek byl upraven
Odkaz byl vyjmut z code.
main.c (1.78 KB)
Tvůj kód s průměrováním by šel podstatně zoptimalizovat.
Realizace digiálního filtru taky není nic složitého, jen je třeba ho navrhnout. Naneštěstí v C ho lze lze realizovat prakticky pouze ve float aritmetice. Tedy aspoň nevím, jak donutit překladač násobit jako fractional. V asm na to mají megy instrukce (fmul). Řešit problémy s přetečením a saturací pro int bude mít na výkon stejný dopad jako použití float, tedy to nejspíš nemá význam.
Jesli to bude procesor stíhat záleží na vzorkovačce.
Vzdyt vsude pisou ze pro takove filtry nebo chyby se bezne pocita s gaussovym rozdelenim, ja jen nevim jak ho zde aplikovat, myslel jsem ze napisu tento prumer, podobnym zpusobem dalsi dva vztahy (ty co nebudu pouzivat do komentu) a hotovo…
S uspechom pouzivam tento jednoduchucky algoritmus:
#define N_KRAT 3
#define M_KRAT 1 // s vyhodou N + M je mocnina dvojky, ale nie je to podmienka
//...
filtrovana_hodnota = (N_KRAT * filtrovana_hodnota + M_KRAT * nova_hodnota)/(N_KRAT + M_KRAT);
// ak N_KRAT + M_KRAT = 4 (2, 8,16), potom
filtrovana_hodnota = (N_KRAT * filtrovana_hodnota + M_KRAT * nova_hodnota)>>2; // (1,3,4) v zavislosti od hodnoty suctu
Cim je N_KRAT vacsi ako M_KRAT, toko krat sa menej prejavi nova hodnota vo vysledku a naopak.
Martin: Jak lze jednoduše napsat celočíselný IIR prvního řádu .
Akorát je tam jedna drobnost - odchylka střední hodnoty výstupu (před shiftem by měla být inkrementace).
Hanisss:
Klouzavý průměr (= FIR s koeficienty 1/N) by mohl vypadat takto:[code]#define AVG_BUF_EXP 4
#define AVG_BUF_LEN 16 // AVG_BUF_LEN = 2^AVG_BUF_EXP = 16 for AVG_BUF_EXP == 4
unsigned int avg(unsigned int newVal)
{
// funkce počítající klouzavý průměr z AVG_BUF_LEN-ti prvků
// musí platit: max(newVal)AVG_BUF_LEN < 65535 !!!
// tedy např. pro 10bit vstup (max = 1023) smí být buffer dlouhý až 64 prvků (102364 < 65535)
// Kdyby nestačil limit 65535, je nutné změnit “sum” na “long int” a modifikovat dle toho kód.
static unsigned int buff[AVG_BUF_LEN];
static unsigned int sum = 0;
static unsigned int *pLast = &(buff[0]);
sum -= *pLast;
sum += newVal;
*pLast = newVal;
pLast++;
if(pLast > &(buff[AVG_BUF_LEN-1])) pLast = &(buff[0]); // end of buffer
return ((sum + ( AVG_BUF_LEN / 2)) >> (AVG_BUF_EXP)); // divide by AVG_BUF_LEN
}[/code]
Co myslíš tím rozdělením u filtrů tedy vskutku netuším. Bývá to předpoklad pro vstupní a výstupní posloupnost aby sis mohl zjednodušit výpočty vlastností tvého výtvoru, ale samotného návrhu se parametry rozdělení nijak neúčastní.
Dakujem za typ, ma to logiku
Nevšiml sis někdy, že tvoje celočíselná filtrace (bez přičtení 1 před posuvem) končí vždy o 3 body níže pokud sleduje rostoucí hodnotu (yiir)? Opravený výpočet (s inkrementací) je na tom o bod lépe (yiir2) ale zase zůstane o bod pozadu při klesající posloupnosti. Při fractional násobení by tento problém nebyl.
FIR(zde klouzavý průměr 8 hodnot) samozřejmě těmito problémy netrpí. To ale vyplývá z podstaty FIR.
Kód pro matlab/octave:[code]close all;
clear;
clc;
N = 100;
t = 1:1:N;
s = 21*ones(1, N);
s(1:10) = 0;
s(50:70) = 8;
s(71:end) = 16;
yfir = zeros(1, N);
yiir = zeros(1, N);
yiir2 = zeros(1, N);
yiir3 = zeros(1, N);
for i=8:N
yfir(i) = floor((sum(s(i-7:i)) + 4)/8); % FIR (klouzavy prumer 8 hodnot)
yiir(i) = floor((3yiir(i-1) + s(i))/4); % IIR
yiir2(i) = floor((3yiir2(i-1) + s(i) + 2)/4); % IIR
yiir3(i) = (3*yiir3(i-1) + s(i))/4; % IIR float
end
%plot(t, s, t, yfir, t, yiir);
stairs(t, s, ‘b’);
hold on;
stairs(t, yfir, ‘g’);
stairs(t, yiir, ‘r’);
stairs(t, yiir2, ‘k’);
hold off;
legend(‘s’, ‘y fir’, ‘y iir’, ‘y iir2’);[/code]
tyjo, koukam na ten fir a moc chytry z toho nejsem:-) to je cele? i s tim bufferem? třakze to nemuzu zakomponovat do toho meho? Zkusim nad tim popremyslet, snad mi to za chvili dojde:-) mno a co ten IIR? Nemohl bys mi to prosim napsat i s tou inkrementaci a bufferem pripadne na ten muj buffer? Nic proti martinovemu zapisu, jen do toho zatim moc nevidim, snazim se to naucit a chapat:-) Mno a pak hledam i treba kalmanuv filtr nebo ten gauss…nevite? diky moc!!!
jasne, vsechno jasne:-) jeste by to chtelo neco, nevim jak ten kalmanuv, o tom toho zas tolik neni ale o fourierove transformaci se hodne pise, akorat to neni asi takova sranda prevod do frekvencni oblasti a pak zas do casove, jde to? Helfli byste mi s tim pls?
Oprava - jednička se musí přičíst na posledním bitu, který bude shiftem odstraněn.
Tedy pro posun o N bitů je nutno přičíst 2^(N-1).
Dělení 16ti ~ (x + 2^3)>>4
Opravil jsem podle toho předchozí kódy, u obrázku s odezvou filtru se ustálená hodnota iir2 posune o bod nahoru při sledování stoupající i klesající posloupnosti.
Hanisss: používat FFT pro filtraci nebude dobrej nápad. Většina implementací se omezuje na výpočet amplitud a bez fáze nelze signál rekonstruovat. To tu nikdo určitě pro zábavu vytvářet nebude.
Filtruje se buď analogově (s tím ti pomůže třeba FilterProDT od TI), digitálně nebo obojí (ani do dig. filtru nesmí složky s frekvencí > Fs/2).
O kalmanově filtru nic nevím. Jeden kolega má jeho implementaci pro stabilizaci 4 motorového vrtulník jako diplomku. Asi to nebude program na pár řádků (což by implementace dvou PID regulátorů byla).
takze s timto si nepomuzu?
Zavolat rutinu “FFTditR2”, která provede vlastní FFT transformaci. Vše probíhá na místě, takže po skončení této rutiny obsahuje pole FFTwarr] komplexní spektrum (už ve správném pořadí).
Z komplexního spektra jde dostat jak amplituda tak fáze.
To ale nebude potřeba. Pro potřeby filtrace stačí vyházet pár koeficientů (klidně v komplexním tvaru) a provést IFFT (= prakticky zase FFT, jen je tam drobná změna, teď si ovšem nevzpomínám jaká).
FFT je ale opravdu pro filtraci nevhodná a nepoužívá se pro tento účel. Už jen proto, že musíš pracovat na oknech a ta tam vkládají svá vlastní spektra.
Aha…takze jinou moznost nez FIR a IIR nemam co? Neco bych tam rad vmesnal, ale nejvic jsem se docetl jen o FIR a IIR a FFT…byl mi recen gauss ale to je normalni rozdeleni na nahodnou chybu, to ani nikde jako filtr uvedeno nebylo…tak nevim…i kdyz na skole delali v dalsim rocniku zpracovani signalu, konvoluce, gauss atd, ale nevim na AVR v GCC asi ne-e…nebo vis o necem jeste?
Asi tím myslej tento: en.wikipedia.org/wiki/Gaussian_filter
ahaaa…asi jo:-) Mno a pujde to hodit do AVR? Ja uz dneska na to nemam, jsem mrtvy…
Vytvářet konvoluci se mi vskutku nechce, obzvlášť když to nepotřebuju. Můžeš zkusit najít nějakou implementaci. Třeba to bude v openCV. Každopádně hodně štěstí .
no neco takoveho by bylo bombovni!!! snazim se a hledam ale nedari se:-(
omlouvam se ze se mi to nedarilo vlozit jako URL, ale bud se nezobrazi vubec nic nebo to nejde rozkliknout…takze treba zkopirovat…
Vazne to nikdo nepouziva? vzdyt takove by mely byt vsude, je to strasne uzitecne…ty prumery jsou na …
administrator: příspěvek byl upraven
Upraven zápis odkazu.
administrator: přiloženy externí soubory
Ehlers (Gaussian and Other Low Lag Filters).doc (77 KB)