{

Tutaj będą przenoszone tematy, którymi dalej nie warto się zajmować, co jakiś czas zawartość tego forum jest kasowana.
SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

{

Post autor: SQ8 » 30 paź 2011, 14:19

NiE AKTUALNE
Ostatnio zmieniony 31 gru 2012, 17:15 przez SQ8, łącznie zmieniany 2 razy.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 30 paź 2011, 14:31

A jaką szybkością taktujesz CPU ? w trybie CTC nie powinno być problemu, no i określ procesor M8 czy M88 (M = ATMEGA). Przy zegarze 8MHz to pestka, wystarczy wpisać 1000, ale wtedy trzeba użyć 16-bitowego Timera.
W przypadku PICa też by trzeba było znać konkretny model, bo tam sprawa nieco bardziej jest pokomplikowana. W sumie dla mie ciekawa sprawa bo akurat teraz uczę PICów, na PCB mam PIC16F690, mogę go potraktować max 8MHz (z wewnętrznego oscylatora) ostatecznie mam jeszcze PIC18F14K22 którego mogę pucnąć :grin: na 64MHz.

SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

Post autor: SQ8 » 30 paź 2011, 14:45

Witam! Nie spodziewałem się tak szybkiej odpowiedzi. Procesor może M8, na rezonatorze 16MHz, ale wtedy wiadomo, nie będzie to taka pestka ;). Czyli timer1, tryb 16 bit, z tym CTC to malutko w sieci opisane jest. A użycie w Bascomie to już zupełnie. Mam nadzieję, że nie porywam się z motyką na słońce i nie spotkam się z opinią, że Bascom się do tego nie nadaje. Mi się wydaje, że jak się będzie rozważnie pisało kod to i Bascom da radę spróbkować i policzyć :). Tak czy inaczej będę pierwszy oficjalny który próbuje takie coś dokonać. Pozdrawiam
PS. Co do PICów, to narazie PIC16F88 z kompilatorem PIC-C. Probówałem już tam robić takie coś, ale niestety stanąłem na tymże problemie - timer i jego wartość. W zasadzie cały program miałem na ukończeniu, tylko to zostało, ale pożuciłem go z braku czasu. Teraz czas i zapał wrócił patrząc na ceny wyspecjalizowanych scalaków dekodujących (przykład CMX823 bodajże, cena za sztukę ok. 400zł do sprowadzenia :D) tak więc zapał uzasadniony.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 30 paź 2011, 14:57

Pierwszy to raczej nie będziesz w BASCOM kto to napisze, bo tacy już chyba byli :?: :wink:
Ale ATMEGA 8 może być.
Najprościej użyć do tego Timer 2 z preskalerem 8, wtedy wystarczy wpisać do niego 250. Nie pamiętam czy timer w M8 może automatycznie wyzwalać przetwornik ADC, ale to kwestia sprawdzenia.
Co do programowania w BASCOM, da się, warunek że nie ma tam za dużo SIN i COS, wtedy trzeba znać pewne sztuczki na to, aby wydajność była odpowiednia.
:?: :shock:

Kod: Zaznacz cały

5 N = 512 // zakładamy długość sygnału wejściowego
10 DIM SIG [N] // deklaracja tablicy na 512 próbek, N = 512
20 DIM REX [N/2+1] // deklatacja tablicy ReX o długości N/2+1 = 257
30 DIM IMX [N/2+1] // deklatacja tablicy ImX o długości N/2+1 = 257
40 SIG := sygnał wejściowy do analizy // symbolicznie opisane ładowanie tablicy SIG
// zerowanie tablic ReX i ImX
50 FOR I:=0 TO (N/2+1)
60 ReX[I] := 0
70 ImX[I] := 0
80 LOOP I
// wyliczenie właściwej DFT
90 FOR K:=0 TO (N/2) // dla każdego elementu tablic ReX i ImX
100 FOR I:=0 TO (N-1) // dla każdej próbki sygnału wejściowego
110 REX[K[ := REX[K] + SIG[I] * COS(2*pi*I*K / N)
120 IMX[K[ := IMX[K] - SIG[I] * SIN(2*pi*I*K / N) // pamiętamy o minusie
130 LOOP I // powtórz dla każdej próbki sygnału wejściowego
140 LOOP K // powtórz dla każdego elementu tablic ReX i ImX
Oczywiście trzeba przetrawić na BASCOM.
Ostatnio zmieniony 30 paź 2011, 15:33 przez kayron, łącznie zmieniany 1 raz.

SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

Post autor: SQ8 » 30 paź 2011, 15:14

W zasadzie jest tylko jedno mnożenie z użyciem COS.

Kod: Zaznacz cały

k=N*(FREQS[X]/SAMPLING);
coeffs = 2*cos(2*pi*(k/N));
Oczywiście to do Bascoma ma się nijak, bo to tylko przykład wzięty z mojego pierwszego programu dla PICka i to w dodatku w C :). To się oblicza w pętli przerwania dla X częstotliwości które chcemy zbadać. Ogólnie prosto. Jak narazie chciałbym:
-Uruchomić Timer (powiadasz Timer2)
-Zrobić podprogram do przerwania który zczytuje ADC (10 bitów jest ok, tak mi się wydaje)
-Wysłać testowo po RS232 do komputera co zczytuje ADC.
Jak to zadziała, to już w zasadzie będziemy w domu. Ale na ten czas mówię bardzo pobieżnie, bez myślenia o kodzie, za nie długo coś pewnie mi wpadnie do głowy jak postudiuję jeszcze dokumentację. Pozdrawiam ;)

---------

Ojojoj to co kolega dodał to nijak mi nie pasuje do prostego Algorytmu Goertzela ;) który w zasadzie wygląda tak dla jednej częstotliwości:

Kod: Zaznacz cały

s_prev = 0
s_prev2 = 0
normalized_frequency = target_frequency / sample_rate;
coeff = 2*cos(2*PI*normalized_frequency);
for each sample, x[n],
  s = x[n] + coeff*s_prev - s_prev2;
  s_prev2 = s_prev;
  s_prev = s;
end
power = s_prev2*s_prev2 + s_prev*s_prev - coeff*s_prev*s_prev2;
Ps. Skąd tamto jest :D? to chyba jakaś implementacja FFT albo DFT

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 30 paź 2011, 15:40

Z powyższego przykładu ciężko to widzę na ATMEGa 8 która ma tylko 512B RAM. Tablica próbek musiała by być mała góra 64 bajty, lub procesor ATMega 168 który ma 1KB RAM, wtedy pewnie poradziło by 128B tablicę próbek, zrobić. Dodatkowo doszła by tablica coeffs żeby nie liczyć za każdym razem tego nieszczęsnego COS w pętli. No i obliczenia złożone typu

Kod: Zaznacz cały

coeffs = 2*cos(2*pi*(k/N)); 
trzeba rozbić na obliczenia proste, bo BASCOM nie trawi takich zapisów.
EDIT. A bo to pełny algorytm, dla całego widma, poczytaj ten temat na ELCE.
http://www.elektroda.pl/rtvforum/topic1 ... asc-0.html
PS. czy DTF można użyć do wykrycia w sygnale jakiś częstotliwości np. 30KHz, 33KHz, 56KHz ?
No i jakie wymogi są wtedy stawiane.

SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

Post autor: SQ8 » 30 paź 2011, 21:01

kayron pisze: PS. czy DTF można użyć do wykrycia w sygnale jakiś częstotliwości np. 30KHz, 33KHz, 56KHz ?
No i jakie wymogi są wtedy stawiane.
Myślę, że można, choć DFT jest nie do tego stworzona i to jak by do muchy strzelać z armaty :D. DFT ma tylko przedstawić liczbowo (moc prążków, energia) jak "widzi" sygnał który próbkuje (analizatory widma audio np.) a gdy szukamy właśnie konkretnych częstotliwości (jak ja chcę to zrobić) to wtedy okrojona wersja DFT czyli algorytm Goertzela - jeżeli któraś częstotliwość odpowiada tej wyliczonej we współczynnikach to gdy się do niej zbliżamy magnituda powoli rośnie aż do nagłego skoku, a następnie opada (podobnie jak filtr). A jakie wymagania? Myślę, że Pan Nyquist bedzie zadowolony jak zastosujemy się do jego twierdzenia :) http://pl.wikipedia.org/wiki/Cz%C4%99st ... 7_Nyquista czyli w moim przypadku filtr dolno przepustowy o częstotliwości cięcia 4kHz max. Na dziś chyba tyle, spróbuję się wgłębić w eksperymenty z Timerem2 i przerwaniem + ADC.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 30 paź 2011, 21:12

Tzn. przepisałem ten mój przykład do BASCOM, ale tempo w symulacji to ma straszne :shock: ogólnie musiałbym to wrzucić do jakiego procka, i to takiego co ma sporo RAMu. Posiadam nawet odpowiedni komputerek na ATMega162 z 32KB RAM, ale niestety nie ma tam ADC, wiec musiałbym zgrać jakiś przykładowy przebieg do pamięci, i traktować go jako dane z ADC, albo doposażyć układ w przetwornik ADC.

SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

Post autor: SQ8 » 30 paź 2011, 21:21

Czyli jakieś postępy. Tak czy inaczej DFT to zbyt duża armata jak mówię ;) o ile armata może być inna jak nie duża :D. Odrazu mówię, ja z Timerami jestem na 0, czy takie coś by miało ręce i nogi jeżeli chodzi o same przerwanie i powrót?

Kod: Zaznacz cały

$regfile = "m8def.dat"                                    
$crystal = 16000000                                        

Config Timer2 = Timer , Prescale = 1

On Timer2 przerwanie
Enable interrupts
Enable Timer2
Load Timer2 , 250


Do
Loop
End

przerwanie:
Load Timer2 , 250
Return
Wartość załadowana 250 i chyba powinno działać z częst. 8kHz. Czy napewno?

SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

Post autor: SQ8 » 30 paź 2011, 22:51

Odpowiem sobie sam :D Wszystko działa jeżeli chodzi o przerwanie. Dodałem nawet odczyt ADC do "Procedury" i wysyłam sobie na RS232 co mi tam przychodzi. Dałem bezczelnie Wait 10 :d do pętli głównej by wszystko wstrzymać a przerwanie ciągle śmigało i był odczyt pomimo zwisu całości. Wniosek - ruszyliśmy do przodu. Tylko coś nie tak z częstotliwością próbkowania. Aktualnie kwarc mam 12MHz niestety, prescale 1, wartość 250, i nijak to się ma do tych 8kHz pomijając, że to liczone było dla bodajże 8MHz rezonatora. W tym przypadku powinno być więcej troszkę, a jest bardzo bardzo dużo więcej. Sprawdzam to poprzez Toggle PortX.y i mierząc częstotliwość na pinie. jak zmienię na Prescale 8 to uzyskuję jakieś 15kHz na pinie. Jak to policzyć?

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Re: Ciekawostka. Algorytm Goertzela w Bascomie?

Post autor: dondu » 31 paź 2011, 5:41

SQ8 pisze:Problemem jest w zasadzie u mnie zmuszenie Timera0 bądź 1 do przerwania i próbkowania z częstotliwością 8kHz. O ile samo przerwanie się robi prosto, to jaką wartość załadować do Timera - już nie. W zasadzie timerów nigdy nie lubiłem właśnie z tego powodu. Czy możemy razem coś w tym temacie podziałać?
Kiedyś musisz je polubić, bo to podstawa mikrokontrolerów, bez timerów to właściwie tylko zwykłe liczydła ;)

Może zacznij je lubić od skorzystania z różnych kalkulatorów które za Ciebie policzą, co i jak ustawić: http://mikrokontrolery.blogspot.com/p/k ... onika.html

A później postaraj się zrozumieć, dlaczego tak, a nie inaczej kalkulator policzył i nawet nie zauważysz, że już je poznałeś.

I dobra rada - przesiądź się na C jak najszybciej.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 31 paź 2011, 8:26

Odpalenie Timera 2 żeby zgłaszał przerwania z 8KHz na 16MHz to chyba będzie tak:
Napisałem chyba, bo ja to zawsze robiłem okrężnie wpisując wartości do odpowiednich rejestrów SFR, ale się skompilowało.

Kod: Zaznacz cały

Config Timer2 = Timer , Prescale = 8 , Clear Timer = 1
Compare2 = 250
Enable Interrupts
Enable Oc2
Start Timer2
Potem nic nie trzeba robić, Timer2 sam będzie pracował jak należy, trzeba tylko obsługiwać przerwania od niego. Zapis dla ATMegi 8. A zgadzać się powinno bo 16MHz / 8 to 2MHz / 250 czyli 2 000 000 / 250 = 8 000 czyli 8KHz.
Co do Timerów to faktycznie musisz je opanować bo to podstawa, w lepszych CPU są z nimi sprzężone przetworniki ADC i inne moduły, w PICach np. sprzętowe moduły modulacji danych, czy obsługi klawiatury pojemnościowej.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 31 paź 2011, 12:12

Na razie udało mi sie sklecić coś takiego :

Kod: Zaznacz cały

' algorytm Goertzela.
' CPU ATMEGA 8.
$regfile = "m8def.dat"        'CPU - ATMEGA8
$crystal = 16000000           ' Zegar 16MHz
$sim                          ' UWAGA !! Usunąć tę linie przy kompilacji dla fizycznego CPU !!
'Configi
Config Timer2 = Timer , Prescale = 8 , Clear Timer = 1
Config Adc = Single , Prescale = 128 , Reference = Avcc
'ADC taktowany 125KHz, napiecie odniesienia VCC (zasilanie CPU)
'nagłowki funkcji
On Timer2 Sample_adc



'definicje zmiennych i stałych
Const Kanal = 1               ' tutaj wpisz nr kanału z ADC
Const Max_tab = 64            'rozmiar tablicy próbek.MAX 256 elementów bo wsk jest 8 'bitowy. 
Dim Sig(max_tab) As Word
'tablica próbek musi być typu word ponieważ GETADC zwaraca właśnie takie dane
Dim Sample As Word
Dim Wsk As Byte
Dim Tab_ovl As Bit

Compare2 = 250


Enable Interrupts
Enable Oc2


'tu powinna być konfiguracja portów I/O CPU
Start Timer2
Do

Loop

Sample_adc:
  Sample = Getadc(kanal)      'odczytaj wartość z ADC
  'UWAGA !! Moze sie okazać ze trzeba wykonać te instrukcje 2 razy w nowszych ' 'BASCOMAch ? Co niestety skutecznie obniży próbkowanie 2 razy, więc preskaler trzeba wtedy przestawić na 64.
  Sig(wsk) = Sample .         'przypisz ją do elementu tablicy
  Incr Wsk                    ' zwiększ wskaźnik tablicy
  If Wsk > Max_tab Then       'jeżeli osiagnięto koniec tablicy
    Wsk = 0                   '- zeruj wskaźnik tablicy
    Set Tab_ovl               '- ustaw flagę zakończenia wypełniania tablicy próbkami
    Stop Timer2               'zatrzymanie timera 2, aby nie wpisywano kolejnych próbek do 'tablicy
  End If
Return
Tyle jeżeli chodzi o zbieranie danych z ADC, ale co chcesz z tym robić dalej ? Znaczy sie, czy chcesz przetworzyć tablicę i zacząć zbierać nowe próbki po tej operacji czy analizować dane w real Time ? teoretycznie dało by się w Real time, ale wtedy potrzebne są dwie tablice próbek wypełnianie i przetwarzane na przemian, ale jest pewien haczyk. Mianowice algorytm musi nadążać przetwarzać tablice, zanim ADC je wypełni, tak aby nie nadpisano się nawzajem.

SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

Post autor: SQ8 » 31 paź 2011, 13:01

Witam! Nie spodziewałem się takiego czegoś :D właśnie dziś chciałem to samo robić a tu taka niespodzianka. Teraz trzeba dopisać tablicę z tonami do dekodwania. W C dla PICków miałem to tak zrobione:

Kod: Zaznacz cały

#define  TONES       11
const double freqs[TONES] = { 1124,1197,1275,1358,1446,1540,1640,1747,1860,1981,2110 }; //NASZE TONY
static signed int16     y0;
static signed int16     y1[TONES];
static signed int16     y2[TONES];
Potem w przerwaniu od Timera miałem w pętli FOR zmianę od 0 do zmiennej TONES czyli

Kod: Zaznacz cały

For ZMIENNA = 0 to TONES
//OBLICZANIE COEFF
NEXT
Potem kolejna pętla z liczeniem współczynników Y0,1,2
czyli

Kod: Zaznacz cały

for ( i = 0; i < TONES; i++ )
 {
 Y0 = *coeffS[i] * y1[i] - y2[i] + adc_data;
 y2[i] = y1[i];
 y1[i] = Y0;
 }
To bardzo pobieżne przykłady. Za chwilę będę kombinował dalej z tym, ale jest już blisko. Pozdrawiam ;)
PS. Czy w Bascomie ten fragment da się inaczej zrealizować?

Kod: Zaznacz cały

Dim TONES(11) as Word 'Tablica TONES 11-elementowa

Tones(0) = 1124 
Tones(1) = 1197
Tones(2) = 1275
Tones(3) = 1358
Tones(4) = 1446 
Tones(5) = 1540
Tones(6) = 1640
Tones(7) = 1747
Tones(8) = 1860 
Tones(9) = 1981
Tones(10) = 2110
?
Spróbowałem przepisać ten fragment na to by Bascom wziął takie działanie:

Kod: Zaznacz cały


for(X = 0; X < MAX_BINS; X++) 
{
k=N*(FREQS[X]/SAMPLING);
coeffs = 2*cos(2*pi*(k/N));
}
A tu moje wypociny. Zwinięte od środka:

Kod: Zaznacz cały

   For I = 0 to MAX_TONE
	k1=Tones(I)/FreQ_sampling
	K=N * K1
	KN = K/N
	KN_PI=  6,28318 * KN
	KN_PI_COS = COS * KN_Pi
	IIKN_PI_COS=2*KN_PI_COS
	Coeff=IIKN_PI_COS
   Next

SQ8
-
Posty: 44
Rejestracja: 30 paź 2011, 14:11
Lokalizacja: ---

Post autor: SQ8 » 31 paź 2011, 13:36

W nowym poście cały program:

Kod: Zaznacz cały

' algorytm Goertzela. 
' CPU ATMEGA 8. 
$regfile = "m8def.dat"        'CPU - ATMEGA8 
$crystal = 16000000           ' Zegar 16MHz 
$sim                          ' UWAGA !! Usunąć tę linie przy kompilacji dla fizycznego CPU !! 
'Configi 
Config Timer2 = Timer , Prescale = 8 , Clear Timer = 1 
Config Adc = Single , Prescale = 128 , Reference = Avcc 
'ADC taktowany 125KHz, napiecie odniesienia VCC (zasilanie CPU) 
'nagłowki funkcji 
On Timer2 Sample_adc 

'definicje zmiennych i stałych 
Const Kanal = 1               ' tutaj wpisz nr kanału z ADC 
Const Max_tab = 64            'rozmiar tablicy próbek.MAX 256 elementów bo wsk jest 8 'bitowy. 
Dim Sig(max_tab) As Word      'tablica próbek musi być typu word ponieważ GETADC zwaraca właśnie takie dane 
Dim N as Byte		      'N - pasmo
Dim Freq_sampling as Word     'częstotliwość próbkowania 8kHz do dalszych obliczeń.
Dim MAX_TONE as Byte          'liczba tonów 11

N=64	
Freq_Sampling=8000 
MAX_TONE = 11

Dim TONES(MAX_TONE) as Word
Tones(0) = 1124 
Tones(1) = 1197
Tones(2) = 1275
Tones(3) = 1358
Tones(4) = 1446 
Tones(5) = 1540
Tones(6) = 1640
Tones(7) = 1747
Tones(8) = 1860 
Tones(9) = 1981
Tones(10) = 2110

Dim K as Word
Dim K1 as Word
Dim Coeff as Word
Dim KN as Word
Dim KN_PI as Word
Dim KN_PI_COS as Word
Dim IIKN_PI_COS as Word
Dim I as Byte
Dim Sample As Word 
Dim Wsk As Byte 
Dim Tab_ovl As Bit 
Compare2 = 250 
Enable Interrupts 
Enable Oc2 


'tu powinna być konfiguracja portów I/O CPU 
Start Timer2 
Do 
Loop 

Sample_adc: 

  Sample = Getadc(kanal)
   For I = 0 to MAX_TONE
	k1=Tones(I)/FreQ_sampling
	K=N * K1
	KN = K/N
	KN_PI=  6,28318 * KN
	KN_PI_COS = COS * KN_Pi
	IIKN_PI_COS=2*KN_PI_COS
	Coeff=IIKN_PI_COS
   Next

  Sig(wsk) = Sample .         'przypisz ją do elementu tablicy 
  Incr Wsk                    ' zwiększ wskaźnik tablicy 
  If Wsk > Max_tab Then       'jeżeli osiagnięto koniec tablicy 
    Wsk = 0                   '- zeruj wskaźnik tablicy 
    Set Tab_ovl               '- ustaw flagę zakończenia wypełniania tablicy próbkami 
    Stop Timer2               'zatrzymanie timera 2, aby nie wpisywano kolejnych próbek do 'tablicy 
  End If 
Return

Zablokowany