radek04 Napisano Czerwiec 26, 2023 Udostępnij Napisano Czerwiec 26, 2023 Cześć, problem mam chyba dość prosty, ale przy moich umiejetnościach robi się trudny 🙂 Potrzebuję bufor cykliczny, który będę zapełniał odczytami z czujnika w równych odstępach czasu. W trakcie działania programu chcę najstarszą wartość nadpisać nową, a nastepnie odczytać i przetworzyć cały bufor. Np. dla 8 elementów (indeksy od 0 do 7) i kolejnej iteracji pętli, pod indeks nr 4 zapisuję nowe dane, a następnie odczytuję cały bufor w kolejnosci: 5,6,7,0,1,2,3,4. O ile odczytanie pojedynczej komórki z takiego bufora jest problemem często poruszanym, o tyle mam kłopot ze złożeniem w chronologiczną tablicę całego bufora. Czy za każdym razem muszę podawać adres każdej z 8 komórek bufora, czy da radę odczytać wszystkie 8 (w odpowiedniej kolejności) jednym poleceniem? Link do komentarza Share on other sites More sharing options...
Popularny post ethanak Czerwiec 26, 2023 Popularny post Udostępnij Czerwiec 26, 2023 26 minut temu, radek04 napisał: a nastepnie odczytać i przetworzyć cały bufor. Przecież bufor powinien wiedzieć jaki jest indeks następnego wpisu, czyli coś w stylu: for (i=0; i< bufor.size; i++) { czytaj_komórkę ( (i + bufor.indeks) % bufor.size); } To taka jedna z tysiąca różnych możliwości... 3 Link do komentarza Share on other sites More sharing options...
MR1979 Czerwiec 26, 2023 Udostępnij Czerwiec 26, 2023 (edytowany) Nie podałeś na jakiej platformie pracujesz i w jakim języku piszesz. A odczytać i przetworzyć dane możesz np następująco: #define BUF_SIZE 8 uint8_t index; uint32_t buf[BUF_SIZE]; // Gdy odbierzesz dane to zapisujesz je w buforze pod adresem index, oraz zwiększasz zmienną index o jeden buf[index] = Nowe dane; index++; index %= BUF_SIZE; // Ograniczasz index do 8 elementów // Gdy przetwarzasz dane z bufora to odczytujesz je chronologicznie w pętli for (uint8_t i = 0; i < BUF_SIZE; i++) { Przetwarzaj_dane(buf[(index + i) % BUF_SIZE]); // operator % oznacza modulo (poczytaj o tym operatorze) } Edytowano Czerwiec 26, 2023 przez MR1979 1 1 Link do komentarza Share on other sites More sharing options...
radek04 Czerwiec 26, 2023 Autor tematu Udostępnij Czerwiec 26, 2023 Korzystam z STM32 i piszę w C. No tak, modulo powinno wystarczyć. Myślałem o tym, by od razu odczytać wiele komórek bez jorzystania z petli, ale z pętlą for też powinno być dobrze. Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
radek04 Czerwiec 27, 2023 Autor tematu Udostępnij Czerwiec 27, 2023 (edytowany) Kurczę, chyba nie będzie to tak proste, jak mi się wydawało. Ale może znów coś doradzicie. Chodzi o to, że w jednym momencie owo "przetwarzanie danych" to nie trywialna operacja matematyczna, a szybka transformata Fouriera (FFT). Korzystam z gotowej funkcji i mam pewne wątpliwości, w które miejsca dokładnie dodawać operację modulo z użyciem indeksu, a w które nie. Zastanawiam się, czy przed wywołaniem funkcji FFT o nazwie dittt() można użyć tej sztuczki z modulo, czy jednak trzeba ingerować w samą funkcję dittt(). Żeby nie zmieniać oznaczeń w kodzie, podaję moje odpowiedniki wcześniej wymienionych zmiennych: BUF_SIZE - TRSIZ index - iteration_TRSIZ Program wykonuje kilka operacji po drodze, ale w najważniejszym momencie mój bufor (tak naprawdę mam 24 podobne bufory, ale będę pisał o jednym) jest rozszerzany dwukrotnie i w co drugie miejsce wpisywane są zera (wartości urojone - wymagania użytej funkcji FFT). for (int i = TRSIZ-1; i >= 0; i--) { adcc_AaX[2*i] = AaX[i]; //parzyste indeksy - real adcc_AaX[2*i+1] = 0; //nieparzyste indeksy - imagine //tutaj pozostałe bufory } (Wiele lat temu pierwszy raz korzystałem z tej funkcji FFT i w sumie dziś już nie wiem, dlaczego indeks w pętli jest dekrementowany, a nie inkrementowany. Ale zdaje się, że nie ma to znaczenia) Następnie ten rozszerzony bufor poddawany jest przetwarzaniu FFT: for (int i = 0; i < liczba_sensorow; i++) { if (i==0) dittt(adcc_AaX); //tutaj pozostałe bufory } Poniżej gwóźdź programu, czyli realizacja FFT: void dittt(float data1[2*TRSIZ]) //oblicza FFT { skok = fs / TRSIZ; float wtemp, wr, wpr, wpi, wi, theta; float tempr, tempi; int N = TRSIZ; int i = 0, j = 0, n = 0, k = 0, m = 0, isign = -1, istep, mmax; float *data; data = &data1[0] - 1; //data = &data1[(0+iteration_TRSIZ)%TRSIZ] - 1; //Tutaj moja zmiana - czy dobrze? Czy raczej musi być już 2*TRSIZ zamiast TRSIZ? n = N * 2; j = 1; //do the bit-reversal for (i = 1; i < n; i += 2) { if (j > i) { SWAP(data[j], data[i]); //czy tutaj modulo? SWAP(data[j + 1], data[i + 1]); //czy tutaj modulo? } m = n >> 1; while (m >= 2 && j > m) { j -= m; m >>= 1; } j += m; } //calculate the FFT mmax = 2; while (n > mmax) { istep = mmax << 1; theta = isign * (6.28318530717959 / mmax); wtemp = sin(0.5 * theta); wpr = -2.0 * wtemp * wtemp; wpi = sin(theta); wr = 1.0; wi = 0.0; for (m = 1; m < mmax; m += 2) { for (i = m; i <= n; i += istep) { j = i + mmax; tempr = wr * data[j] - wi * data[j + 1]; //czy tutaj modulo? tempi = wr * data[j + 1] + wi * data[j]; //czy tutaj modulo? data[j] = data[i] - tempr; //czy tutaj modulo? data[j + 1] = data[i + 1] - tempi; //czy tutaj modulo? data[i] = data[i] + tempr; //czy tutaj modulo? data[i + 1] = data[i + 1] + tempi; //czy tutaj modulo? } wtemp = wr; wr += wtemp * wpr - wi * wpi; wi += wtemp * wpi + wi * wpr; } mmax = istep; } for (k = 0; k < N; k += 2) { m = k / 2; if (k == 0) { fx[m] = 0.0; amplituda[m] = 0; } //zerowanie w indeksie [0] else { modul = sqrt(pow(data[k + 1], 2) + pow(data[k + 2], 2)); //czy tutaj modulo? fx[m] = fx[m - 1] + skok; amplituda[m] = modul * 2 / TRSIZ; } featuresSTM[wykonania_dittt*TRSIZ/2+m] = amplituda[m]; } wykonania_dittt++; } W komentarzach zaznaczyłem miejsca, gdzie wg mnie powinny być zmiany. Proszę o sprawdzenie mojego pomysłu. I rozumiem, że w tej funkcji korzystać muszę już z rozmiaru bufora równego 2*TRSIZ, prawda? Mimo że rzeczywiste (niezerowe) wartości występują tylko w liczbie TRSIZ. Chyba że zaproponujecie jakiś lepszy sposób użycia bufora cyklicznego bez ingerencji w funkcję dittt(), która nie jest mojego autorstwa (coś tam bardzo delikatnie dorobiłem na swoje potrzeby). Może da radę w miejscu, gdzie rozszerzam bufor, poukładać dane w odpowiedniej kolejności? Edytowano Czerwiec 27, 2023 przez radek04 Link do komentarza Share on other sites More sharing options...
ethanak Czerwiec 27, 2023 Udostępnij Czerwiec 27, 2023 36 minut temu, radek04 napisał: lepszy sposób użycia bufora cyklicznego bez ingerencji w funkcję dittt() Coś mi tu pachnie błędem w założeniach. Jakie rozszerzanie bufora i po co? Zarówno owo "rozszerzenie" jak i samo wywołanie funkcji dittt zmieni zawartość bufora czyniąc go bezużytecznym. Nie lepiej stworzyć sobie jakąś tablicę roboczą? Coś w stylu: float robocza[2*TRSIZ]; for (i=0; i<TRSIZ;i++) { robocza[2*i] = twój_bufor[(i+iteration_TRSIZ] % TRSIZ); robocza[2*i+1] = 0; } dittt(robocza); Wynik masz w tablicy roboczej, a funkcja dittt pozostaje taka jaka jest. 1 Link do komentarza Share on other sites More sharing options...
radek04 Czerwiec 27, 2023 Autor tematu Udostępnij Czerwiec 27, 2023 41 minut temu, ethanak napisał: Jakie rozszerzanie bufora i po co? Funkcja dittt() to uogólniona postać szybkiej transformacji Fouriera. Jako dane wejściowe przyjmuje liczby zespolone: indeks parzysty - część rzeczywista, indeks nieparzysty - część urojona. W moim przypadku są tylko liczby rzeczywiste, dlatego "ręcznie" muszę dodać część urojoną, stąd rozszerzony 2x bufor. 43 minuty temu, ethanak napisał: Zarówno owo "rozszerzenie" jak i samo wywołanie funkcji dittt zmieni zawartość bufora czyniąc go bezużytecznym. Nie lepiej stworzyć sobie jakąś tablicę roboczą? Masz rację. Dlatego - dopiero po napisaniu mojego posta - pomyślałem o tym, by ta główna tablica AaX o rozmiarze TRSIZ była buforem cyklicznym, natomiast wartości w tablicy adcc_AaX o rozmiarze 2*TRSIZ "układać" w taki sposób, by pod indeksem nr 0 znalazł się zawsze odpowiedni w danym momencie element z bufora AaX. 47 minut temu, ethanak napisał: float robocza[2*TRSIZ]; for (i=0; i<TRSIZ;i++) { robocza[2*i] = twój_bufor[(i+iteration_TRSIZ] % TRSIZ); robocza[2*i+1] = 0; } dittt(robocza); I chyba właśnie coś takiego zaproponowałeś. Zdaje się, że właśnie o to mi chodziło. Dzięki. Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »