{
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ąć
na 64MHz.
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ąć
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
) tak więc zapał uzasadniony.
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
Pierwszy to raczej nie będziesz w BASCOM kto to napisze, bo tacy już chyba byli
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.
Oczywiście trzeba przetrawić na BASCOM.
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.
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
Ostatnio zmieniony 30 paź 2011, 15:33 przez kayron, łącznie zmieniany 1 raz.
W zasadzie jest tylko jedno mnożenie z użyciem COS.
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:
Ps. Skąd tamto jest
? to chyba jakaś implementacja FFT albo DFT
Kod: Zaznacz cały
k=N*(FREQS[X]/SAMPLING);
coeffs = 2*cos(2*pi*(k/N));
-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
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;
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
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.
Kod: Zaznacz cały
coeffs = 2*cos(2*pi*(k/N));
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.
Myślę, że można, choć DFT jest nie do tego stworzona i to jak by do muchy strzelać z armatykayron 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.
Tzn. przepisałem ten mój przykład do BASCOM, ale tempo w symulacji to ma straszne
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.
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
. 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?
Wartość załadowana 250 i chyba powinno działać z częst. 8kHz. Czy napewno?
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
Odpowiem sobie sam
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ć?
Re: Ciekawostka. Algorytm Goertzela w Bascomie?
Kiedyś musisz je polubić, bo to podstawa mikrokontrolerów, bez timerów to właściwie tylko zwykłe liczydłaSQ8 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ć?
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.
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.
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.
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
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.
Na razie udało mi sie sklecić coś takiego :
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.
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
ReturnWitam! Nie spodziewałem się takiego czegoś
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:
Potem w przerwaniu od Timera miałem w pętli FOR zmianę od 0 do zmiennej TONES czyli
Potem kolejna pętla z liczeniem współczynników Y0,1,2
czyli
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ć?
?
Spróbowałem przepisać ten fragment na to by Bascom wziął takie działanie:
A tu moje wypociny. Zwinięte od środka:
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];
Kod: Zaznacz cały
For ZMIENNA = 0 to TONES
//OBLICZANIE COEFF
NEXT
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;
}
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));
}
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
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