Skocz do zawartości

Bufor cykliczy - nadpisywanie 1 elementu, odczyt całości


radek04

Pomocna odpowiedź

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

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 przez MR1979
  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

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

(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 przez radek04
Link do komentarza
Share on other sites

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.

 

  • Pomogłeś! 1
Link do komentarza
Share on other sites

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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.