RTV forum PL | NewsGroups PL

Jak uzyskać idealny przebieg sinusoidalny 425 Hz z Atmegi8 zamiast trójkąta?

Fast PWM - trójkąt zamiast sinusa na wyjś ciu

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Jak uzyskać idealny przebieg sinusoidalny 425 Hz z Atmegi8 zamiast trójkąta?

Goto page 1, 2  Next

Atlantis
Guest

Sat Feb 16, 2013 4:27 pm   



Eksperymentuję właśnie z generowaniem przebiegu sinusoidalnego za pomocą
Atmegi8. Oparłem się na drugim przykładzie z tej strony:

http://tinyurl.com/d3tyvex

Przebieg ma być dialtonem o częstotliwości około 425 Hz.

Wzór przebiegu znajduje się w tabeli, wypełnionej w następujący sposób:

for (i=0; i<256; i++) sinus_buffer[i]=128+126*sin(6.26/256*1);

PWM generowany jest za pomocą TIMER1 ustawionego na Fast PWM (tryb 14).
Funkcja włączająca generowanie przebiegu wygląda następująco:

void StartDialtone (void)
{
TCCR1A |= _BV(COM1A1) | _BV(WGM11);
TCCR1B |= _BV(WGM13) | _BV(WGM12) | _BV(CS10);
ICR1 = 255;
OCR1A = 0;

sinus_ind = 0;
TCNT0 = 182;
TCCR0 |= _BV(CS00);
TIMSK |= _BV(TOIE0);
}

Z kolei wyłączająca wygląda następująco:

void StopDialtone (void)
{
TCCR0 &= ~_BV(CS00);
TIMSK &= ~_BV(TOIE0);

TCCR1A &= ~(_BV(COM1A1) | _BV(WGM11));
TCCR1B &= ~(_BV(WGM13) | _BV(WGM12) | _BV(CS10));
ICR1 = 0;

PORTB &= ~_BV(1);
}

Zmiana współczynnika wypełnienia odbywa się w przerwaniu, po
przepełnieniu TIMER0:

ISR (TIMER0_OVF_vect)
{
OCR1A = sinus_buffer[sinus_ind];

if (sinus_ind < 255) sinus_ind++;
else sinus_ind=0;

TCNT0 = 182;
}

Za wyjściem PB1/OC1A znajduje się filtr dolnoprzepustowy RC złożony z
rezystora 330 omów oraz kondensatora 1uF do masy. Za filtrem nie mam
jednak sinusoidy, a coś przypominające trójkąt:

http://imageshack.us/photo/my-images/4/img8927kj.jpg/

Gdzie mogłem popełnić błąd? Problem będzie leżał raczej po stronie softu
czy sprzętu?

Atlantis
Guest

Sat Feb 16, 2013 4:36 pm   



Ok, niemal godzinie patrzenia w kod dostrzegłem błąd - nie wiedzieć
czemu w funkcji wypełniającej tabelę z wzorem sinusoidy nazwę zmiennej
zastąpiła jedynka...

Anerys
Guest

Sat Feb 16, 2013 5:41 pm   



Użytkownik "Atlantis" <marekw1986NOSPAM@wp.pl> napisał w wiadomości
news:kfo8i2$v93$1@portraits.wsisiz.edu.pl...
Quote:
Za wyjściem PB1/OC1A znajduje się filtr dolnoprzepustowy RC złożony z
rezystora 330 omów oraz kondensatora 1uF do masy. Za filtrem nie mam
jednak sinusoidy, a coś przypominające trójkąt:

http://imageshack.us/photo/my-images/4/img8927kj.jpg/

W sieciach tf widzialem gorsze przebiegi... Z czystym sumieniem możesz dać
taki sygnał, chyba, że chcesz dopiąć swego i mieć sinus, lub obawiasz się,
że filterkiem tniesz coś znacznie gorszego.

--
Pod żadnym pozorem nie zezwalam na wysyłanie mi jakichkolwiek reklam,
ogłoszeń, mailingów, itd., ani nawet zapytań o możliwość ich wysyłki.
Nie przyjmuję ŻADNYCH tłumaczeń, że mój adres e-mail jest ogólnodostępny
i nie został ukryty. Wszelkie próby takich wysyłek potraktuję jako stalking.

Atlantis
Guest

Sat Feb 16, 2013 5:46 pm   



W dniu 2013-02-16 17:41, Anerys pisze:

Quote:
W sieciach tf widzialem gorsze przebiegi... Z czystym sumieniem możesz
dać taki sygnał, chyba, że chcesz dopiąć swego i mieć sinus, lub
obawiasz się, że filterkiem tniesz coś znacznie gorszego.

Jak napisałem - wszystkiemu winny był błąd w instrukcji wypełniającej
tabelę wzorem sinusoidy.

Teraz przebieg na oscyloskopie jest o wiele ładniejszy - sinus o lekko
postrzępionych brzegach (widoczne przy mocno zmniejszonej podstawie
czasu na oscyloskopie).

Zastanawiam się jeszcze tylko nad sposobem, w jaki mam to podać na
słuchawkę. Rozumiem, że nie powinienem tego wyjścia za filtrem obciążać
bezpośrednio słuchawką 150 omów? Jak powinien wyglądać odpowiedni interfejs?

AlexY
Guest

Sat Feb 16, 2013 5:52 pm   



Atlantis wrote:
[..]
Quote:
Teraz przebieg na oscyloskopie jest o wiele ładniejszy - sinus o lekko
postrzępionych brzegach (widoczne przy mocno zmniejszonej podstawie
czasu na oscyloskopie).

Zastanawiam się jeszcze tylko nad sposobem, w jaki mam to podać na
słuchawkę. Rozumiem, że nie powinienem tego wyjścia za filtrem obciążać
bezpośrednio słuchawką 150 omów? Jak powinien wyglądać odpowiedni
interfejs?

Filtr dolnoprzepustowy (wygładzi przebieg) i wtórnik emiterowy.

--
AlexY
http://nadzieja.pl/inne/spam.html
http://www.pg.gda.pl/~agatek/netq.html

J.F.
Guest

Sat Feb 16, 2013 6:08 pm   



Dnia Sat, 16 Feb 2013 16:27:53 +0100, Atlantis napisał(a):
Quote:
Eksperymentuję właśnie z generowaniem przebiegu sinusoidalnego za pomocą
Atmegi8. Oparłem się na drugim przykładzie z tej strony:
http://tinyurl.com/d3tyvex

Za wyjściem PB1/OC1A znajduje się filtr dolnoprzepustowy RC złożony z
rezystora 330 omów oraz kondensatora 1uF do masy. Za filtrem nie mam
jednak sinusoidy, a coś przypominające trójkąt:
http://imageshack.us/photo/my-images/4/img8927kj.jpg/

Niezaleznie od bledu - cos tu chyba nie tak.
Skad takie strome zbocza ?
Filtr ma stala 0.33ms

J.

Atlantis
Guest

Sun Feb 17, 2013 10:07 am   



W dniu 2013-02-16 17:52, AlexY pisze:

Quote:
Filtr dolnoprzepustowy (wygładzi przebieg)

Filtr oczywiście już jest, złożony z jednego rezystora i jednego
kondensatora. Mam rozumieć, że powinienem dać jeszcze drugi taki zestaw?


Quote:
i wtórnik emiterowy.

Jak wygląda kwestia dobierania elementów wtórnika do konkretnych
warunków pracy? Szczególnie chodzi mi o rezystor w emiterze i dzielnik w
obwodzie bazy. Co decyduje o ich wartościach?

AlexY
Guest

Sun Feb 17, 2013 5:46 pm   



Atlantis wrote:
Quote:
W dniu 2013-02-16 17:52, AlexY pisze:

Filtr dolnoprzepustowy (wygładzi przebieg)

Filtr oczywiście już jest, złożony z jednego rezystora i jednego
kondensatora. Mam rozumieć, że powinienem dać jeszcze drugi taki zestaw?

Jeżeli filtrowanie jest niewystarczające to wartości elementów trzeba
zmienić lub użyć innego filtra.

Quote:
i wtórnik emiterowy.

Jak wygląda kwestia dobierania elementów wtórnika do konkretnych
warunków pracy? Szczególnie chodzi mi o rezystor w emiterze i dzielnik w
obwodzie bazy. Co decyduje o ich wartościach?

Ja tam dobieram wartości przypadkowe, jeśli to nie ma być generator
wzorcowy do kalibracji to poeksperymentuj z wartościami 1k i 10k, a w
emiterze coś w okolicy obciążenia.

--
AlexY
http://nadzieja.pl/inne/spam.html
http://www.pg.gda.pl/~agatek/netq.html

J.F
Guest

Mon Feb 18, 2013 4:02 pm   



Użytkownik "Atlantis" napisał w wiadomości
Quote:
Filtr dolnoprzepustowy (wygładzi przebieg)
Filtr oczywiście już jest, złożony z jednego rezystora i jednego
kondensatora. Mam rozumieć, że powinienem dać jeszcze drugi taki
zestaw?

Generalnie dokladanie kolejnych czlonow RC to nie jest najlpeszy
pomysl - filtr wychodzi z tego kiepski. Bieguny nie tam gdzie trzeba.
Ale moze do prostych celow wystarczy.

J.

Jakub Rakus
Guest

Mon Feb 18, 2013 9:15 pm   



W dniu 16.02.2013 16:27, Atlantis pisze:

Quote:
Wzór przebiegu znajduje się w tabeli, wypełnionej w następujący sposób:

for (i=0; i<256; i++) sinus_buffer[i]=128+126*sin(6.26/256*1);

Skoro wypełniasz tablice stałymi wartościami to po co do tego zaprzęgać
biednego avr i męczyć go liczeniem funkcji sinus? Policz sobie to w
jakimś arkuszu i wrzuć samą tablice gotowych wartości - będziesz miał
znacznie krótszy kod.

--
Pozdrawiam
Jakub Rakus

Atlantis
Guest

Mon Feb 18, 2013 9:55 pm   



W dniu 2013-02-18 21:15, Jakub Rakus pisze:

Quote:
Skoro wypełniasz tablice stałymi wartościami to po co do tego zaprzęgać
biednego avr i męczyć go liczeniem funkcji sinus? Policz sobie to w
jakimś arkuszu i wrzuć samą tablice gotowych wartości - będziesz miał
znacznie krótszy kod.

Ostatecznie tak właśnie zrobiłem, dzięki temu mogłem dać tablicę jako
volatile const unsigned char. :)

Jednak przy pierwszej próbie łatwiej było dać tą linijkę kodu
wypełniającego tabelę. Oczywiście zlecenie przeliczania wartości Atmedze
miało tę zaletę, że hex zajmował mniej, ale mam jeszcze na tyle wolnego
flasha, że nie muszę liczyć bajtów. Wink

Michoo
Guest

Tue Feb 19, 2013 12:56 am   



On 18.02.2013 21:55, Atlantis wrote:
Quote:
W dniu 2013-02-18 21:15, Jakub Rakus pisze:

Skoro wypełniasz tablice stałymi wartościami to po co do tego zaprzęgać
biednego avr i męczyć go liczeniem funkcji sinus? Policz sobie to w
jakimś arkuszu i wrzuć samą tablice gotowych wartości - będziesz miał
znacznie krótszy kod.

Ostatecznie tak właśnie zrobiłem, dzięki temu mogłem dać tablicę jako
volatile const unsigned char. Smile
Dlaczego?


volatile i const w jednym miejscu znaczy zazwyczaj "kompilatorze, zepsuj
mi tu optymalizacje".

Póki masz miejsce we flash to takie rzeczy powinieneś pakować w progmem.

Quote:

Jednak przy pierwszej próbie łatwiej było dać tą linijkę kodu
wypełniającego tabelę. Oczywiście zlecenie przeliczania wartości Atmedze
miało tę zaletę, że hex zajmował mniej,

Myślę, ze raczej wynikało to z błędu w kodzie - z tego co widzę sinus
miał stały argument, więc całe to "liczenie" sprowadziło się do
podstawienia wartości 131. Liczenie sinusa to nie takie hop-siup bo
powoduje wciągnięcie całej biblioteki zmiennoprzecinkowej - dodatkowe 4kB.

Quote:
ale mam jeszcze na tyle wolnego
flasha, że nie muszę liczyć bajtów. Wink

Masz eeprom na pokładzie - jak zacznie brakować to użyj go.

--
Pozdrawiam
Michoo

Atlantis
Guest

Wed Feb 20, 2013 6:20 pm   



W dniu 2013-02-19 00:56, Michoo pisze:

Quote:
Dlaczego?

volatile i const w jednym miejscu znaczy zazwyczaj "kompilatorze, zepsuj
mi tu optymalizacje".

Kierowałem się analogią do wyczytanej kiedyś zasady, że wszystkie
zmienne globalne używane w przerwaniach powinny mieć "volatile" przy
definicji. "Const" z kolei dałem na wszelki wypadek, aby zabezpieczyć
się przed możliwością zmiany zawartości tabeli po jej wypełnieniu.
Rozumiem, że w przypadku stałej "volatile" nie jest wskazane?


Quote:
Póki masz miejsce we flash to takie rzeczy powinieneś pakować w progmem.

Jak rozumiem masz na myśli użycie avr/pgmspace.h i zdefiniowanie tablicy
przez:

prog_char sinus_buffer[] = {wartość 1, wartość 2, .., wartość n};

oraz odczyt przez:

pgm_read_byte(&sinus_buffer[sinus_ind])

?

Rozumiem, że przy definicji takiej tabeli nie muszę stosować "volatile",
nawet jeśli będę się do niej odwoływał w przerwaniu?

Tak z ciekawości: jak zachowa się program przy próbie zapisania czegoś
do takiej tabeli, przechowywanej w pamięci programu?

Atlantis
Guest

Wed Feb 20, 2013 6:32 pm   



I jeszcze jedno: czy odczytywanie wartości z tabeli przechowywanej w
pamięci flash bardzo spowolni wykonywanie programu? Pytam, ponieważ
odwołuję się do niej w przerwaniu, a jak wiadomo ono powinno się
wykonywać jak najszybciej...

Michal Schulz
Guest

Mon Mar 11, 2013 4:43 pm   



Am 20.02.13 18:20, schrieb Atlantis:

Quote:
volatile i const w jednym miejscu znaczy zazwyczaj "kompilatorze, zepsuj
mi tu optymalizacje".

Kierowałem się analogią do wyczytanej kiedyś zasady, że wszystkie
zmienne globalne używane w przerwaniach powinny mieć "volatile" przy
definicji.

Marna to zasada bo zbytnio uogolnia.

Quote:
Póki masz miejsce we flash to takie rzeczy powinieneś pakować w progmem.

Jak rozumiem masz na myśli użycie avr/pgmspace.h i zdefiniowanie tablicy
przez:

prog_char sinus_buffer[] = {wartość 1, wartość 2, .., wartość n};

oraz odczyt przez:

pgm_read_byte(&sinus_buffer[sinus_ind])

Dokladnie o to chodzilo. Trzymanie tablicy ze stalymi w RAM to
marnotrastwo pamieci ktorej Atmel ma dosc malo. Tak samo jak trzymanie
tam np. wszelkich lancuchow tekstowych.

Quote:
Rozumiem, że przy definicji takiej tabeli nie muszę stosować "volatile",
nawet jeśli będę się do niej odwoływał w przerwaniu?

Ale po co tam mialo by byc volatile? to slowo informuje kompilator, ze
zawartosc pamieci moze ulec zmianie w sposob dla kompilatora malo
przewidywalny, innymi slowy kompilatorowi nie wolno optymalizowac
dostepu do zmiennej.

Goto page 1, 2  Next

elektroda NewsGroups Forum Index - Elektronika Polska - Jak uzyskać idealny przebieg sinusoidalny 425 Hz z Atmegi8 zamiast trójkąta?

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map