Spróbuję uściślić o co mi chodzi. Zrobiłem na 8051 częstotliwościomierz który po odpowiednim wyskalowaniu(przeliczeniu) będzie wskazywał obroty jednego silniczka. W ramach testów podłączyłem 50 Hz z sieci (50 Hz to tak jakby 50 obr/sek. czyli 3 tyś obr/min) i niby wszystko jest dobrze ale.Te "ale" to to że ostatnie cyfry wyniku ciągle się zmieniają. Rozumiem że nic nie jest idealne i po przeliczeniu wychodzi że obroty to: 2998 2999 3000 i z powrotem 2998. I tu się właśnie zastanawiam jak w prosty sposób w programie uśrednić (przefiltrować) wyniki pomiarów aby mieć na wyświetlaczu stabilny odczyt. Zgadzam się na pewną utratę dokładności czyli niech dla przykładowo podanych wyników wyświetla cały czas 2999 nie wnikając czy naprawdę jest
2998 czy już 3000. Jedyne ograniczenie to że 8051 nie jest demonem szybkości a wszystko jest na przerwaniach czyli by było miło jeśli algorytm byłby w miarę prosty czyli nie czasowo (milisekundowo) chłonny.
Użytkownik <pisz snipped-for-privacy@dionizos.zind.ikem.pwr.wroc.pl> napisał w wiadomości news:efgkuf$bp2$ snipped-for-privacy@panorama.wcss.wroc.pl...
[ciach]
Pewnie i tak, ale to nie rozwiązuje problemu że przy pracującym silniku z kołem zamachowym będę miał na przemian 2999 3000 2999 3000 a nic tak nie deneruje jak ciągła zmiana najbardziej znaczącej cyfry. Dlatego wolę filtrować i uśredniać. Bo czy on naprawdę ma 3001 czy 2999 obr to mnie nie rusza byle wynik był w miarę stabilny i zmieniał się dopiero jak silnik pod obciążeniem zacznie tracić obroty i straci tak z 20 50 obr /sek
Filtrowanie, niezależnie od stałej czasowej - zawsze będzie powodować skakanie wyniku. Co najwyżej okres skakania się wydłuży, ale wtedy będziesz miał opóźnienie wyniku.
Rozwiązanie, któego szukasz to histereza. Dla tych, którzy nie wiedzą co to histereza: Wyobraź sobie, że wskazówka Twojego miernika drga. Ale ty montujesz widełki, które są przesuwane przez wskazówkę: Do widełek montujesz nową wskazówkę.
Tak więc, dopóki wskazówka waha się pomiędzy widełkami, nowa wskazówka nie poruszy się.
A teraz działający fragment kodu:
#define SH 2 // 4 kwanty na wartość histerezy // napiecie - wartosc mierzona // wph - wartosc po histerezie - wynik if (wph<napiecie) { if ((napiecie-wph)>SH) wph=napiecie-SH; } else{ if ((wph-napiecie)>SH) wph=napiecie+SH; }
no ale może chce uśrednić? Jakby chcieć, to można zrobić średnią z pomiarów, np. 4 ostatnie pomiary uśredniać. Czyli robisz 4x oversampling, dodajesz wsio, przesuwasz o 2 bity w prawo i gotowe.
Skakanie wyniku przy przetwarzaniu A/C ma prawo wystepowac na poziomie ostatniego bitu lub +/-1, a nie na poziomie jakims niewiadomo jak wysokim. Na zmiennosc ostatniego bitu lub koncowki bitow przy stalym sygnale mierzonym jest proste rozwiazanie - usrednianie arytmetyczne. Mozna uzyskac wieksza dokladnosc pomiaru niz ostatni bit - np jesli w
70% wyniku mial on wartosc 1, a w 30$ - 0, to mamy .7 po przecinku ;) Pozatym dla sygnalu mierzonego niestalego nalezaloby zbadac okres niestalosci/zaklucen i dobrac usrednianie z tego okresu lub jego wielokrotnosci (obojetnie czy po stronie analogowej czy cyfrowej, a najlepiej po obu)
Przy przetwarzaniu typu zliczanie - skakania nie ma prawa byc. W koncu zliczasz dokladnie np 3000impulsow/okresow/przejsc przez zero, a nie
2999.7 przejsc przez zero. Nie ma czegos takiego jak niecalkowite przejscie. Albo jest zle pomiar zmajstrowany, albo nieprecyzyjna podstawa czasu bramkowania (przy czestotliwosci) albo algorytm zly (i wkrada sie gdzies obliczanie wartosci niecalkowitej). Moze byc tak, ze przejscie "ostatniego" okresu jest na granicy momentu bramkowania (i przy kolejnych zliczeniach zalapie sie lub nie)- ale oznacza to ze albo zbyt szybki sygnal bramkujemy zbyt wolnym gate, albo zbyt niedokladnie bramkujemy. I praktycznie moze to doprowadzic tylko do bledu +/- zliczenie...
Najlatwiej na procesorze wykonac taki manewr, majac niewiele ramu/rejestrow, ze wynik pomiaru (w koncu dosc czestego) jest sumowany - np przez 16,64,256 lub inna potege 2. A potem taka suma z np 16 pomiarow jest dzielona przez 16 (a dzielenie przez potege 2 sie robi prosto i szybko - przez przesuwanie w prawo bitow) - i masz usredniony wynik z 16 pomiarow. Oczywiscie typ zmiennej trzymajacy taka liczbe musi byc odpowiednio duzy, by sie zmiescila ta wielokrotnosc. Ta metoda mozna "scalkowac" wyniki z tylu pomiarow, by okres calkowania byl wielokrotnoscia okresu zaklucajacego pomiar. Sens to ma dla liczby sumowan od 8 w gore - a najlepiej 16 w gore, by zwiekszyc precyzje o jedno miejsce. Np dla przykladu z wynikami w okolicy 3000 (16bit) i 8xsuma wynik1= 2998 wynik2= 2999 wynik3= 3000 wynik4= 2999 wynik5= 2998 wynik6= 3000 wynik7= 2998 wynik8= 2999 suma = 23991 (miesci sie na 16 bit nadal!) 0101110110110111 dzielimy przez 8, czyli przesuwamy w prawo przecinek o 3 miejsca 0000101110110110 , 111 dla spokoju wyrzucamy jeszcze ostatnie 2bity, zeby nie bylo wazne czy sie zmieniaja czy nie, wiec 1 po w reszczie oznacza .5, a 0 w reszcie oznacza .0 suma/8= 2998,5
Ale jesli bedzie nadal przeszkadzala roznica pomiedzy kolejnymi zsumowanymi i podzielonymi wynikami - to trzeba zuzyc wiecej ramu/rejestrow - i kazdy pomiar wrzucac do osobnej zmiennej. Kolejne pomiary wrzucac cyklicznie do zmiennych w tablicy (np inkrementujac modulo wskaznik do elementu tablicy), a wyswietlac obliczona srednia (lub np srednia wazona) - za kazdym pomiarem obliczona oddzielnie dla calej tablicy, bedzie wieksza dynamika...
Nie rozumiesz problemu. Istota tkwi w tym, ze masz raz 2999 a raz 3000. Chociazby nie wiem ile razy to usrednisz to wynik bedzie ci nieprzyjemnie skakal, pomimo, ze to roznica ciagle jednego bitu. Gdyby to bylo 2998 i 2999 to nie ma problemu, a tak jeden bit przestawia cale wyswietlanie i jest to nieprzyjemne. Kiedys majac taki problem wlasnie zaczalem usredniac 256 pomiarow, efekt taki, ze ograniczylem to skakanie, ale nie wyeliminowalem. Oczywiscie moge usrednic 2^16 pomiarow, ale nie tedy droga. IMHO wprowadzenie histerezy to wlasciwe rozwiazanie.
No nie jest to idealnie biorąc pod uwagę, że częstotliwość sieci energ. jest naprawdę nieźle stabilizowana (nie to co kilkadziesiąt lat temu). Albo masz niestabilny generator lokalny - może wpływy zewnętrzne elektromagnetyczne?, efekt "zbliżenia ręki"?, pływanie/szpilki na zasilaniu? Albo, co bardziej prawdopodobne, jest to skutek niedokładnego wyznaczania momentu rozpoczęcia/zakończenia pomiaru przy komparacji zbocza sygnału mierzonego. Najmniejszy bląd osiąga się wyznaczając moment przejścia przez zero sygnału wejściowego - komparując bowiem na innym napięciu (różnym od zera) dostajemy fluktuacje czasowe wynikające z ew. zmian amplitudy sygnału wejść. Tu jest też drugi element poprawiający precyzję komparacji - sygnał wejść. powinien mieć jak największą amplitudę i szybkość narastania/opadania zboczy. Oczywiście aby nia zabić komparatora, amplituda tego napięcia powinna być obcięta na samym wejściu komparatora (np.diodowo) do zakresu dopuszczalnego. Nie opisałeś jak masz zrobione "wejście" sygnału mierzonego do procka - powinno się dać tam jakiś dobry zewnętrzny komparator.
Najprościej uśrednianie zrealizować zliczając częstotliwość wzorcową z podzielnika timera uP przez kilka okresów sygnału mierzonego, a potem dzieląc wynik przez ilość tych okresów. Z oczywistych względów ta liczba powinna być 2^n, bo dzielenie sprowadza się wtedy tylko do zwykłego przesuwu rejestrów. Dzielenie musi być z zaokrągleniem, czyli ostatni bit zaokrąglający (za umownym przecinkiem) powinien być dodany do wyniku końcowego. Niestabiność takiego pomiaru (czyli takie przeskakiwanie 2999<->3000) będzie tym rzadsza im więcej okresów wejściowych będzie uśredniane i im wyższą częstotliwość pomiarową zastosujesz. Oczywiście jeśli wynik końcowy ma mieć 3-4 cyfry dziesiętne znaczące, to do przetwarzania musisz mieć jest 11-14 bitów znaczących, a wszelkie dodawania, przesuwania itd. muszą być dwubajtowe.
Algorytm na przerwaniach jest oczywiście optymalny - moment wyznaczony przez komparator czy timer powinien być zawsze obsłużony jak najszybciej, minimalną liczbą rozkazów, bez zbędnych fluktuacji czasowych. Resztę czasu uP może sobie poświecić na przeliczenia, wyświetlanie itd.
Ale to nic nie zmieni. Powiedzmy, ze masz 8 bitow, ktore wyswietlasz i 8 ukrytych (z sumowania). Co z sytuacja kiedy masz tak 01111111 11111111 i przeskoczy ci najmlodszy bit? Uzyskasz 10000000 00000000. Czyli nieprzyjemny efekt. Takie granice zawsze bedziesz mial przy sumowaniu, co najwyzej bedzie sie to zdarzac rzadziej w miare jak masz co raz wiecej sum.
Nie twierdze ze jest to rozwiazanie ostateczne na wszelkie problemy swiata, ale jak sam zauwazasz - granice beda wystepowac rzadziej. Najlepiej by bylo polaczyc metody - sumowania (lub tabelkowa, z przesuwaniem wynikow i liczeniem sredniej) zwiekszajacej rozdzielczosc oraz histerezy/widelek na tej zwiekszonej rozdzielczosci...
Jest tez rozwiazanie proste ale zupelnie niedokladne ;) Wyswietlac najmniejsza/najwieksza wartosc jaka sie trafi w ciagu X pomiarow, przy czym X jest bardzo duze. Reset licznika X dokonywac gdy wartost aktualna jest dosc duzo (np 5-10%) rozna od tej wyswietlanej. Tak jest robione np w termometrach samochodowych wbudowanych w oplach (przy czym X inne jest dla temp opadajych, inaczej dla rosnacych)
W dniu 28-09-2006 16:07, pisz snipped-for-privacy@dionizos.zind.ikem.pwr.wroc.pl napisał:
Kiedy kilka lat temu (~10) byłem na Elektrowni Opole, to widziałem na jednym z turbogeneratorów wyświetlacz LED ze wskazaniami obrotów. Pokazywał sobie na zmianę 2999 i 3000, raz nawet chyba 3001, ale te zmiany to były rzadsze niż raz na kilka-kilkanaście sekund.
Co do uśredniania. Dodajesz sobie wyniki dowolnej, będącą potęgą dwójki liczby pomiarów i później przez tą potęgę dwójki dzielisz używając przesuwania bitów w prawo. Szybkie i eleganckie.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.