Fórum témák

» Több friss téma
Fórum » A/D mérési eredmény átlagolás probléma
Lapozás: OK   1 / 1
(#) nrg hozzászólása Jan 27, 2010 /
 
Üdv,

a következő méréstechnikai problémán gondolokozok már egy ideje és sajnos még nem találtam meg a választ.
Egy AVR kontroller A/D átalakítójával mérek egy hőmérséklettel arányos analóg jelet 0-5V -os tartományban. A következő két átlagolási módszer hatékonysága között nem tudok relációt állítani.
Ha az A/D kimenetét egy X valószínűségi változóként értelmezem, mely változó a [0,1023] közötti egész számokat veszi fel. A hőmérsékeletet állandónak tekintve, M várható értékkel és S2 szórásnégyzettel.
Az első módszer, hogy veszek 100 mintát, majd kiszámolom az átlagát és azt veszem az A/D mérés eredményének.
A második módszer, hogy veszek 10 mintát és kiszámolom az átlagukat, majd ezt megismétlem még kilencszer. Ekkor van 10 darab 10 mintás átlag, végül az átlagoknak veszem az átlagát és ez lesz a mérés eredménye.
Ha X értékei függetlenek és azonos eloszlásúak, akkor a két módszer ugyanazt a várható értéket és szórásnégyzetet adja elvileg.
A valóságban a két módszer várható értéke szerintem ugyan az lesz, de a szórásnégyzetben nem vagyok biztos, mivel nem biztos a minták függetlensége, valamint hogy a korrelációja egyenlő nullával.
Ha valakinek van tapasztalata vagy ötlete a felvetéssel kapcsolatban kérem ossza meg velem.

Üdvözlettel,
nrg
(#) kobold válasza nrg hozzászólására (») Jan 27, 2010 /
 
A leírt módszereket még nem alkalmaztam, de kifejezetten hőmérséklet-átlagolásra én a következőt szoktam: adott mondjuk 100 minta, elsőként kidobom a 10 legkisebb, és 10 legnagyobb értéket (gyakorlatilag ez a tranziensek elleni szoftveres védelem), a maradék 80-ból pedig egyszerű átlagot számítok.
Terem- illetve olajhőmérsékletek figyelésénél teljesen bevált, másodpercenként frissül a végeredmény - kérdés persze, hogy neked mi a célod ezzel, egyes területeken az így adódó pontatlanság már kritikus lehet.
(#) geri303 válasza kobold hozzászólására (») Jan 27, 2010 /
 
Hali!
Csatlakoznék az előttem szólóhoz, érdemes valamilyen módon szanálni a mért értékek közt. Persze ilyenkor érdemes eldönteni, hogy melyikeket kell eldobni. Aztán elég egy egyszerű átlagszámítás a maradék értékekből.

Ha részletesebb dolgok kellenek, akkor pedig talán érdemes lenne a mért értékeket valamilyen módon ábrázolni és az átlag vonalat pedig behúzni így látható lenne hol mekkora eltérés van.

Persze a kérdés nálam is az: mire szeretnéd ezt alkalmazni.
(#) nrg válasza kobold hozzászólására (») Jan 27, 2010 /
 
Köszönöm a válaszokat,
semmi különös, csak egy hőmérőt készítettem 0 - 60 °C közötti tarományra.
Csupán elméletileg érdekel a dolog, melyik módszertől várhatok jobb eredményt, illetve hogy van-e egyáltalán különbség a két módszer között.
(#) icserny válasza nrg hozzászólására (») Jan 27, 2010 /
 
A száz adat átlaga vagy a 10-szer tíz adat átlagának átlaga matematikailag azonos.
(#) nrg válasza icserny hozzászólására (») Jan 27, 2010 /
 
Ez volt a véleményem nekem is, amíg valaki el nem bizonytalanított, azzal hogy a második módszer szórásnégyzete kisebb mint az elsőé.
(#) banti22 válasza nrg hozzászólására (») Jan 28, 2010 /
 
Sziasztok!

Ezen igen érdekes kérdés lett szerintem. Ha nem tévedek, akkor ez a probléma belefér az ergodikus folyamatok témakörbe. Ugye, ami azt vizsgálja, hogy ha egyetlen realizáció áll rendelkezésünkre, akkor mikor fog az idő szerinti átlag megegyezni a sokaság szerinti átlaggal. Azaz, ha megfelelően sok mintánk van, akkor a távoli minták függetlenek lesznek egymástól. Ebben az esetben a függvényt megfelelő hosszúságú darabokra felvágva, a függvény darabokon végzett átlagolás meg fog egyezni a teljes függvényen végzett átlagolással.

A te esetedben, szerintem, lehet, hogy a 10 minta kevés, mert a következő 10 minta nem lesz független teljesen az előzőtől, túl nagy lesz a koreláció a két regisztrátum között.

Hát én a tanulmányaimból erre emlékszem.
(#) Hp41C válasza nrg hozzászólására (») Jan 28, 2010 / 6
 
Szia!

Átlag - Várható érték:
M = sum{1}{n}(x_{i}) / n

Szórás:

S^2 = sum{1}{n}((x_{i}-M)^2) / n

Ha a 100 mintát 10 darab 10-es csoportból számítod, az átlag és a szórásnégyzet is ugyan az lesz. Az átlagnál a részátlagok közös nevezője 10, 10 darab átlagot adsz össze, még osztadod kell 10-zel, azaz ugyan az, mintha a 100 elemet összeadod és az eredményt osztod 100-zal. Hasonlóan alakul a szórásnál is.

Szia
(#) vicsys válasza kobold hozzászólására (») Jan 28, 2010 /
 
Izgalmas téma! Az ötlet tetszik. Milyen algoritmussal lehet min-maxot válogatni, mondjuk 100 mintából? Egy konkrét C megoldásnak örülnék. Nem gondolom, hogy valamilyen algoritmussal sorba kéne rendezni a tömb elemeit (például buborék rendezés) és abból a 5-5 elemet eldobni, mert akkor a konverzió hosszúra nyúlna. Biztosan létezik valamilyen faék egyszerűségű rutin. :miaz:
(#) geri303 válasza vicsys hozzászólására (») Jan 28, 2010 /
 
Mivel nem tudod mi számít kicsinek és mi nagynak (mire ezt megkeresnéd így is úgy is végig kellene menni az adathalmazon), így sajnos marad a sorba rendezés. Eközben már elkezdheted szummázni is az adathalmazt, ezzel már közel kerül a megoldás, a végén már csak ki kell vonni a szummából amit eldobsz és egy osztás után a kezedben az eredmény.
(#) nrg válasza vicsys hozzászólására (») Jan 28, 2010 /
 
gyorsan összedobtam egy C függvényt, hogy hogyan gondoltam első körben ezt a kiválogató függvényt. Igaz ez is végigfut párszor a tömbön, de még mindig kevesebbszer mintha sorba kellene rendezni az egészet. A kinullázott értékek nem fognak beleszámítani az átlagolásba, mert 0-kat adunk hozzá az átlaghoz és végül nem 100-al, hanem csak 90-el osztjuk el.
Várom az esetleges ötleteket a kóddal kapcsolatban.

  1. void Valogat(uint *samples) {
  2.         uchar Nr = 100;
  3.         uint *pSmpl;
  4.         uint MaxIndex = 0;
  5.         uint MinIndex = 0;
  6.  
  7.         for (uchar n=0; n<5; n++) {
  8.                 pSmpl = samples;
  9.                 uint Max = 0;
  10.                 uint Min = 1023;
  11.  
  12.                 for (uchar x=0; x<Nr; x++) {
  13.                         if (*pSmpl >= Max) {
  14.                                 Max = *pSmpl;
  15.                                 MaxIndex = x;
  16.                         }
  17.                         if ((*pSmpl <= Min) && (*pSmpl > 0)) {
  18.                                 Min = *pSmpl;
  19.                                 MinIndex = x;
  20.                         }
  21.                         ++pSmpl;
  22.                 }
  23.                 *(samples+MaxIndex) = 0;
  24.                 *(samples+MinIndex) = 0;
  25.         }
  26. }
(#) ekkold válasza nrg hozzászólására (») Jan 28, 2010 /
 
Szerintem nagyon jó az ötleted, sokkal hatékonyabb, kisebb, és gyorsabb, mint a sorbarendezéses megoldás.
(#) t-dani válasza (Felhasználó 15355) hozzászólására (») Jan 28, 2010 /
 
Az A/D bemenetről mentett értékeknél szerény véleményem szerint nincs értelme lebegőpontos (azaz 32 bites) számokat alkalmazni. Bőven elég egy sima mezei 2 bájtos integer, a maga 16 bitjével: 65536 egymástól különböző állapot. 16 bites A/D-je talán egy PIC-nek sincs. Így biztosan több hely maradna más műveletekre is, vagy bármi másra...
(#) nrg válasza (Felhasználó 15355) hozzászólására (») Jan 28, 2010 /
 
Ha 100 számos összeadást csinálsz, ott az aktuális mérést (ADC - 16 bit) hozzáadhatod egy unsigned long int-hez(32 bit) + kell még egy osztó(8 bit). De az ADC-t nem kell tárolni, így nem kell a regiszter értékét elmenteni.
(#) szilva hozzászólása Jan 28, 2010 /
 
Én ilyenre (mért hőmérsékletértékek simítása) egyszerűen digitális aluláteresztő szűrőt alkalmaztam. Egy hőmérsékletváltozás úgysem túl gyors folyamat, tehát eléggé alacsonyra lehet méretezni a szűrő töréspontját. A hőmérsékletszabályozós PIC-es pákámban is ilyen dolgozik.

Ha a mintavétel rendszeres (periodikus), akkor lehet számolni mindenféle paraméterű digitális szűrőket a feladathoz. Ha már úgyis használunk lebegőpontos számokat a programunkban, akkor talán egyszerűbb például egy másodfokú szűrőhöz szükséges 4 értéket eltárolni, mint többtíz vagy többszáz mintával FIFO-zni (ha pl. csúszóátlagot akarunk számolni). Nekem sokkal jobb tapasztalatom volt a mérési eredmények digitális szűrővel történő kisimításával kapcsolatosan, mint amikor 32-64 mintából próbáltam átlagokat számolgatni.

Az alábbi oldalon interaktívan lehet digitális szűrőket terveztetni, sőt, még a C forráskódot is legenerálja: mkfilter
(#) ekkold válasza (Felhasználó 15355) hozzászólására (») Jan 28, 2010 /
 
A memóriafoglalás az algoritmustól is függ. Ha pl. nem akarsz eldobni (nrg megoldásához hasonlóan) értékeket, akkor az AD konverziók eredményét egyből egy változóhoz hozzáadhatod, és nem kell mindet külön tárolni.... Ha viszont "selejtetzni" is akarsz az értékek közül, akkor jó a meglátásod, nyilván nem mindegy, hogy tizes vagy százas csoportokat dolgozol fel....
(#) geri303 válasza ekkold hozzászólására (») Jan 28, 2010 /
 
Sorbarendezés talán a leggyorsabb:

Ha N a tömb legnagyobb indexe, és 0-val kezdődik, akkor egy lehetséges megoldás:
Eztán lehet átlagolni.
for(i=0;i<=N-1;i++)
for(j=i+1;j<=N;j++)
{
if(tomb[i]>tomb[j])
csere(i,j);
}>
(#) vicsys válasza geri303 hozzászólására (») Jan 28, 2010 /
 
Igen csak megint az Ordoval van a gond...
Szilva megoldása szimpatikus, erősen gondolkodok rajta, hogy ki kéne próbálgatni...
(#) ekkold válasza geri303 hozzászólására (») Jan 28, 2010 /
 
Amit beuírtál az az un. buborék módszer. Ez lehet, hogy egszuerü algoritmus, de a rendezési elvek között a leglassúbb. Jóval gyorsabb az un. minimum kiválasztásos rendezés, de nrg módszere még jobb - mert eléggé feladatspecifikus.
Rendezés szempontjából pedig a qsort a leggyorsabb, és C-ben általában van rá gyári függvény.
(#) geri303 válasza ekkold hozzászólására (») Jan 28, 2010 /
 
Igen erről van szó ő a buborék, a qsort viszont mikrovezérlőknél általában hiányzik, így mindenkinek magának kell írni algoritmust, mivel kevés általában a memória így a legkevésbé memóriaigényest kell használni.
(#) banti22 hozzászólása Jan 28, 2010 /
 
Legegyszerűbb esetben egy rekurzív átlagolással meg lehet oldani.

hat{x}(n+1) = hat{x}(n) +   1/{n+1}  [y(n) -hat{x}(n)]

n=0,1,2...
hat{x}(n+1) - az uj atlag
hat{x}(n) - elozo atlag
1/{n+1}[y(n)-hat{x}(n)] - Kigazitas az uj megfigyeles figyelembevetelevel

Rekurzív módon előállított átlag előnye, hogy nem kell az összes mintát tárolni, így memóriát és számítási időt takarítunk meg.

Vagy a csúszóablakos átlagolás, ami szintén felírható rekurzív módon.

hat{x}(n+1) = hat{x}(n)+1/N [y(n)-y(n-N)]
N - atlagolasi szam
(#) nrg válasza ekkold hozzászólására (») Jan 28, 2010 /
 
A fejemben már megvan a képe egy algoritmusnak ami ugyanazt az eredményt adja mint az előző függvény, de nem tárolja el egy 100-as int tömbben a mért eredményeket. Ha lesz egy kis időm akkor megpróbálom lekódolni..
(#) ekkold válasza nrg hozzászólására (») Jan 28, 2010 /
 
Simán megoldható amit mondasz, elég csak az aktuális 5 legkisebb, és 5 legnagyobb adatot tárolni. Csak shiftelni kell ezeket ha a legkisebbnél kisebb v. a legnagyobbnál nagyobb adat érkezik, persze nem is muszály shiftelni csak eldobni amelyik az 5-ből kiesik, és a helyére tenni az uj értéket....
(#) ekkold válasza geri303 hozzászólására (») Jan 28, 2010 /
 
Azt nem tudtam, hogy nincs kész qsort mikrovezérlőre. Viszont a minimumkiválasztásos rendezés nem bonyolultabb a buboréknál, viszont az is sokkal gyorsabb nála....
(#) nrg válasza ekkold hozzászólására (») Jan 28, 2010 /
 
Így van, pont ilyen algoritmusra gondoltam én is. Akkor ezekszerint megspóroltam a lekódolását
(#) kobold válasza vicsys hozzászólására (») Jan 29, 2010 /
 
Sajnos nem érem el azt a gépet, ahol ezek a kódok vannak, de megpróbáltam fejből reprodukálni.
A módszer nem az egy ciklusban összegyűjtött mintákon végez egy nagy, egyszeri válogatást, hanem minden mérés után néhány kisebbet. Az adatok alsó és felső értékeinek címeit tartalmazó tömbök folyamatosan frissülnek, minden konverzió után, így mire a mérési ciklus végén átlagolni kell, már nem lesz szükség a teljes adattömb sorbarendezésére, válogatására.
Gyakorlati okokból én 80 mintát szoktam venni egy ciklusban, azokból 8-8 szélsőértéket kidobok, a végén pedig csak 64-el osztva kell átlagot számolnom. Ez (nekem) azért jó, mert osztás helyett hatszor jobbra léptetem az összeget tartalmazó regisztereket, és elkerülhetem a lebegőpontos számítást.
Még talán annyit, hogy ha megszakításban megy a konverziós értékek olvasása, tömbfrissítés stb., célszerű a megszakításokat tiltani, amikor mondjuk LCD-re ír az ember valamit, nehogy gond legyen a verem-mérettel, vagy az időzítésekkel.

Főbb lefoglalt területek: három tömb, egy a mérési adatoknak, kettő kisebb a szélsőértékeknek
data[]: mérési adatok helye, annyi eleme van, amennyit egy ciklusban átlagolni szeretnénk, legyen most 100
max[]: legnagyobb mérési adatok címei, elemeinek száma annyi, amennyit a "nagyok" közül ki akarunk dobni, legyen 10
min[]: legkisebb mérési adatok címei, elemeinek száma annyi, amennyit a "kicsik" közül ki akarunk dobni, legyen 10
Nem deklaráltam változókat és függvényeket, csak az elvet akartam bemutatni. Alkalmazás előtt célszerű legalább a max[] és min[] tömbök inicializálása, nehogy valami végzetes történjen egy rossz címre való írás miatt.
  1. // Minden A/D konverzió után végrehajtódik
  2. // data[] tömb tárolja majd a mért adatokat, dataptr címzi a regisztereit
  3. data[dataptr] = ana_value;
  4. // max[] és min[] tömbökben minden mérés után frissül a tartalom
  5. // Először csinálunk egy minimumkeresést a max[] tömbben, illetve
  6. // egy maximumkeresést a min[] tömbben
  7. // Spórolunk az iterációk számával, ha a 0. elemről adunk kezdőértéket
  8. min_of_max = data[max[0]];
  9. max_of_min = data[min[0]];
  10. for (i = 1; i < 10; i++) {
  11.         if (min_of_max > data[max[i]]) {
  12.                 min_of_max = data[max[i]];
  13.                 ptr2min_of_max = i;
  14.                 }
  15.         if (max_of_min < data[min[i]]) {
  16.                 max_of_min = data[min[i]];
  17.                 ptr2max_of_min = i;
  18.                 }
  19.         }
  20. // Amikor eddig megvagyunk:
  21. // - ptr2min_of_max a max[] tömb azon elemére mutat, ami
  22. //   megcímzi a data[] tömb legnagyobb értékei közül a legkisebbet
  23. // - ptr2max_of_min a min[] tömb azon elemére mutat, ami
  24. //   megcímzi a data[] tömb legkisebb értékei közül a legnagyobbat
  25. // Összehasonlítások:
  26. // - ha az aktuális mért érték a legnagyobbak közé tartozna, mentsük
  27. //   el a max[] tömb megfelelő helyére azt a címet, ahová data[]-ban került;
  28. //   max[]-ból a minimumkeresésnek köszönhetően legkisebb elem címe esik ki
  29. if (ana_value > min_of_max)
  30.         max[ptr2min_of_max] = dataptr;
  31. // - ha az aktuális mért érték a legkisebbek közé tartozna, mentsük
  32. //   el a min[] tömb megfelelő helyére azt a címet, ahová data[]-ban került;
  33. //   min[]-ből a maximumkeresésnek köszönhetően legnagyobb elem címe esik ki
  34. if (ana_value < max_of_min)
  35.         min[ptr2max_of_min] = dataptr;
  36. // Már csak annyi maradt, hogy frissítsük data[] pointer-ét, illetve
  37. // jelezzük azt, ha kész egy mérési ciklus
  38. dataptr++;
  39. if (dataptr == 100) {
  40.         dataptr = 0;
  41.         acq_complete = true;
  42.         }
  43.  
  44. // Főprogramban valahol
  45. if (acq_complete) {
  46.         // Első lépésként kinullázzuk a tíz legnagyobb és legkisebb értéket,
  47.         // ezek címeit tartalmazza a max[] és min[] tömb
  48.         for (i = 0; i < 10; i++) {
  49.                 data[max[i]] = 0;
  50.                 data[min[i]] = 0;
  51.                 }
  52.         // Egy szelíd összeadó ciklus a teljes tömbre...
  53.         sum_of_all = data[0];
  54.         for (i = 1; i < 100; i++)
  55.                 sum_of_all += data[i];
  56.         // Majd átlagszámítás, a 20 kiesett értékre is ügyelve
  57.         average = sum_of_all / 80;
  58.         // Kész, mehet az újabb ciklus
  59.         acq_complete = false;
  60.         }
(#) vicsys válasza kobold hozzászólására (») Jan 29, 2010 /
 
Nagyon köszönöm! Izgalmas, le fogom tesztelni gyakorlatban is. Ha mégis előkerül a link, megköszönném.
(#) NyariG hozzászólása Jan 1, 2012 /
 
Én asm ben programozom a picemet és ebben szeretnék ilyen átlagolást csinálni, nekem nem kellene 100 szám elég lenne 50 is.

Tud valaki segíteni pl hogy lehet 50 mérést eltárolni? abból kiválogatni a kicsiket nagyokat és átlagot venni? ASM ben

köszi
Következő: »»   1 / 1
Bejelentkezés

Belépés

Hirdetés
Lapoda.hu     XDT.hu     HEStore.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem