Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 27 lis 2024, o 18:19


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 17 ] 
Autor Wiadomość
PostNapisane: 29 cze 2013, o 17:50 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

Obrazek
Przeglądając sieć natrafiłem na fajny trik. Typowe podejście na tablicę wartości funkcji wygląda tak, że chcąc skorzystać z przykładowo sinusa, dołączamy do programu kod np. z tej strony albo sami obliczamy to w arkuszu kalkulacyjnym i przenosimy łatwiej lub trudniej do kodu programu. Można to zrobić też jak pokazano poniżej:
Plik main.c:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Plik values.txt:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jeśli tak jak w przykładzie potrzeba 24 wartości sinusa to w pliku values.txt 24 razy powtarza się dokładnie tą samą linię. Parametr __LINE__ zwraca numer linii (tutaj 1-24). Jako, że zaczyna się numeracja od 1 to we wzorze na sinus odejmowana jest najpierw 1 i wtedy argument ma wartość 0-23. Przeliczając to na stopnie mnoży się razy krok czyli 15, bo akurat potrzeba 24 wartości z całego zakresu 0-360 stopni. Następnie konieczna jest zamiana stopni na radiany (/180.0*M_PI) dlatego, że funkcja sinus na takich wartościach operuje. Kolejnym krokiem jest dopasowanie wyniku do wartości 0-255 co jest realizowane poprzez pomnożenie razy 128 i dodanie 127. No i już nie potrzeba korzystać z innych programów :)

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 cze 2013, o 18:56 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27314
Lokalizacja: Szczecin
Pomógł: 1041

O matko ;) jak pierwszy raz to przeczytałem i zobaczyłem to - powiedziałem tylko hyyyyy i nic nie zrozumiałem ;) .... więc jeszcze raz, i jeszcze raz .... i jeszcze raz .... i tak jeszcze n razy jak w tej tabeli ;)

a jak zaskoczyłem ;) .... hahahaha - no mega super trick - ale popraw mnie jeśli się mylę bo może jednak coś na końcu przeoczyłem

rezultatem tego myku jest fakt że, tzn postaram się to podsumować tak na mój rozum:

1. w programie nie zostaną użyte funkcje zmiennoprzecinkowe z math.h ;)
2. w programie zostanie stworzona ładna tablica sinusów w pamięci FLASH
3. a wartości tej tablicy przygotuje grzecznie sługa PREPROCESOR ;)
4. plik values.txt jest tylko taki pomocniczy .... ;) żeby zadać fuchę preprockowi ;)

dobrze myślę ?

jeśli tak to działa to na prawdę Krauser super mega TRICK obczaiłeś w necie ! ;) gratulacje

no i super że się nim podzieliłeś

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 cze 2013, o 18:58 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 04 paź 2011
Posty: 8587
Pomógł: 337

Ano właśnie ... kiedyś to widziałem i gdzieś przepadło w przepastnych czeluściach sieci zaiste .
dzięki za przypomnienie , bo robienie na piechotę czasem dobija :)

_________________
Zbuduj swój system [url=https://helion.pl/ksiazki/w-labiryncie-iot-budowanie-urzadzen-z-wykorzystaniem-ukladow-esp8266-i-esp32-andrzej-gromczynski,wlablo.htm#format/d]IOT[/url]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 cze 2013, o 19:58 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 14 lis 2011
Posty: 534
Lokalizacja: Mierzyn
Pomógł: 9

genialne :)

_________________
pozdrawiam
Jachu



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 cze 2013, o 20:29 
Offline
Nowy

Dołączył(a): 29 cze 2013
Posty: 1
Pomógł: 0

Ja ostatnio spotykając się z tym problemem, mając naprawdę mało czasu napisałem sobie po prostu programik który generował kod.
Generuje on sinusy o 6 różnych amplitudach w dwuwymiarowej tablicy i nie ma problemu z wygenerowaniem za pomoca tego kodu innych funkcji z math.c po lekkim przerobieniu, treść jego jest taka:

Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Pod linuksem odpalam skompilowany program np.
Kod:
./sinus_gen > sinus.h

więc nie potrzebuje zapisu do pliku, ale pod windowsem mogłoby się to przydać.

Ponieważ miałem problemy z przetwornikiem, dodatkowo zrobiłem opcję generowania przebiegu do matlaba, aby porównać sobie tablicę do tego, co widze na oscyloskopie.

Wykorzystanie preprocesora napewno jest bardziej "hackerskie", ale i trudniejsze w zrozumieniu (chociaż mnie strasznie podobają się takie tricki :) )



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 cze 2013, o 22:22 
Offline
Nowy

Dołączył(a): 29 cze 2013
Posty: 1
Pomógł: 0

@mirekk36
Te wartości nie znajdą się tam w magiczny sposób, bez wywołania funkcji sin(x) z biblioteki math.
Mniej więcej będzie to wyglądać tak:
1. Preprocesor wpierw zamieni __LINE__ w pliku values.txt na odpowiadające im numery linii
2. Następnie w miejsce #include "values.txt" wklei zawartość tego pliku czyli:
Kod:
const uint8_t sin_tab[TAB_SIZE] PROGMEM ={
    VALUE(1),
    VALUE(2),
    ...,
    VALUE(24),
};

2. Wszystkie miejsca gdzie użyte jest makro VALUE(a) przed kompilacją zamieni na:
Kod:
const uint8_t sin_tab[TAB_SIZE] PROGMEM ={
    (sin( ( ( (1-1) * STEP )/180.0 )*M_PI )*128 + 127 ),
    (sin( ( ( (2-1) * STEP )/180.0 )*M_PI )*128 + 127 ),
    ...,
    (sin( ( ( (24-1) * STEP )/180.0 )*M_PI )*128 + 127 ),
};

3. Kompilator wygeneruje kod w asemblerze, który inicjalizuje tę tablicę, czyli do każdej wartości z tablicy przypisze wartość otrzymaną po wywołaniu tego wyrażenia.

Tak przy okazji wydaje mi się, że ten wzór na zamianę <-1.0f, 1.0f> na <0, 255> jest zły.
Jak sin(x) wyjdzie -1 to otrzymasz (-1.0f)*128 + 127 => -128.0f + 127 => -1.0f i po rzutowaniu na unsigned short int wyjdzie 255.
Imo lepiej użyć wzoru:
Kod:
(sin((a-1)*STEP*PI/180.0f)*127.5f + 127.5f)


Wg mnie zamiast kombinować z takimi hackami lepiej jest po prostu wygenerować sobię tę tablicę i ręczne przekleić do kodu. Niestety takie stuczki zmniejszają czytelność i jak nie znamy dokładnego zachowania kompilatora to mogą prowadzić do powstania błędów w programie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 cze 2013, o 23:46 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27314
Lokalizacja: Szczecin
Pomógł: 1041

krz napisał(a):
Te wartości nie znajdą się tam w magiczny sposób, bez wywołania funkcji sin(x) z biblioteki math


Nie pisałem, że magiczny ;) pisałem że w programie nie zostanie użyta biblioteka math.h - i nie zostanie bo całe wyliczenia zostaną zrobione na etapie preprocesora właśnie i to jest fajne.

Dobrze, że rozpisałeś to po swojemu w punktach bo dzięki temu jeszcze łatwiej będzie zrozumieć ideę działania tego tricku wielu ludziom ;)

krz napisał(a):
Wg mnie zamiast kombinować z takimi hackami lepiej jest po prostu wygenerować sobię tę tablicę i ręczne przekleić do kodu


łeeeej ;) no bez przesady - po to są właśnie takie sposoby, jako alternatywa i tak należy to rozumieć. Sposób działa i to się liczy - jak się już go zrozumie - to okazuje się że wcale nie jest skomplikowany a wręcz banalnie prosty - i to jest siła takich rozwiązań w niektórych przypadkach.

krz napisał(a):
Niestety takie stuczki zmniejszają czytelność i jak nie znamy dokładnego zachowania kompilatora to mogą prowadzić do powstania błędów w programie


To by oznaczało, że w zasadzie jak coś wygląda dziwnie - to lepiej tego nie ruszać. To jest dla osób które już zaskoczą o co tu chodzi - a myślę że sporo zaskoczy dzięki temu całemu wątkowi ... i nic nie będzie się działo ze zmniejszeniem czytelności kodu ;) ... tym bardziej, że działa to TYLKO na poziomie preprocesora. Dlatego ja akurat uważam, że warto na pewno czasem to wykorzystywać ;) jak najbardziej.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 cze 2013, o 11:15 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

krz napisał(a):
Tak przy okazji wydaje mi się, że ten wzór na zamianę <-1.0f, 1.0f> na <0, 255> jest zły.
Jak sin(x) wyjdzie -1 to otrzymasz (-1.0f)*128 + 127 => -128.0f + 127 => -1.0f i po rzutowaniu na unsigned short int wyjdzie 255.
Imo lepiej użyć wzoru:
Kod:
(sin((a-1)*STEP*PI/180.0f)*127.5f + 127.5f)

Tak wzór jest zły (pozdrawiam panią od matematyki :oops: ), ale w wyniku działań na liczbach zmiennoprzecinkowych sin(270) > -1 i po odcięciu części ułamkowej wychodzi 0. To osobny temat poruszony już przy okazji omawiania obliczania UBRR. W związku z tym lepiej użyć jeszcze innego wzoru (tylko dla preprocesora, gdzie wynik jest większy o 0,5):
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Teraz wartości są jak te z arkusza po zaokrągleniu. Dodanie do wzoru 360 nic nie zmienia, ale wtedy obie wartości dla 0 i 180 stopni są równe i wynoszą 128 (jak w arkuszu kalkulacyjnym). Chociaż z drugiej strony bardziej symetryczne wyniki są, gdy dla 180 mamy wartość 127. Co kto woli. Środek jest na poziomie 127,5, a takiej wartości nie można wybrać. Zwiększenie rozdzielczości do 16 bitów też nic nie zmieni, bo znowu środek jest na poziomie 511,5 .

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 wrz 2013, o 20:05 
Offline
Nowy

Dołączył(a): 20 sie 2013
Posty: 7
Pomógł: 0

Czy da się się w tym "tricku" podstawić inną funkcję zamiast sinusa z math.h? Konkretnie chodzi mi o funkcję przez siebie zdefiniowaną spoza biblioteki standardowej.?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 wrz 2013, o 20:39 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

Zauważ, że:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

to nie jest po prostu:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Można używać innych makr (makro to nie funkcja, ale może ją zastąpić) np.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 wrz 2013, o 20:53 
Offline
Nowy

Dołączył(a): 20 sie 2013
Posty: 7
Pomógł: 0

Czy chcesz powiedzieć, że preprocesor umie policzyć wartość sinusa z liczby? Raczej nie. Zakomentowanie lini #include<math.h> spowoduje błędy, zatem wartość sinusa obliczana jest na podstawie algorytmu zawartego w bibliotece math.h.

Cytuj:
Zauważ, że:
Składnia: [ Pobierz ] [ Ukryj ]
język c

#define VALUE(a) (sin( ( ( (a-1) * STEP)/180.0 )*M_PI )*127.5 + 128 )/* wzór na wartość sinusa */

GeSHi

to nie jest po prostu:
Składnia: [ Pobierz ] [ Ukryj ]
język c

#define VALUE(a) (sin(a))


w sumie pierwsze sprowadza się do drugiego



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 wrz 2013, o 20:59 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27314
Lokalizacja: Szczecin
Pomógł: 1041

rafrew napisał(a):
Czy chcesz powiedzieć, że preprocesor umie policzyć wartość sinusa z liczby?


Kolego naprawdę poczytaj troszkę o preporcesorze gdzieś ;) ... pewnie że preprocesor oblicza sin() i to bez żadnego inkludowania <math.h> bo ta biblioteka jest potrzebna tylko gdy obliczeń trzeba dokonywać w kodzie w procku.

Co to za problem dla preprocesora obliczyć sin czy podobną funkcję - na PC? miałby to być kłopot ?

a makro VALUE() działa tu TYLKO i wyłącznie w taki sposób że zwraca stałą dosłowną która zostanie wyliczona przez preprocesor właśnie

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 wrz 2013, o 21:25 
Offline
Nowy

Dołączył(a): 20 sie 2013
Posty: 7
Pomógł: 0

Ok, jeśli tak to już wszystko jasne. Faktycznie muszę coś poszukać bo o funkcjach jakie umie wyliczyć preprocesor jakoś nigdzie się nie natknąłem. Dzięki za odpowiedzi. Pozdrawiam.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lut 2014, o 00:18 
Offline
Użytkownik

Dołączył(a): 25 sty 2014
Posty: 185
Lokalizacja: Działoszyn
Zbananowany użytkownik

Pomógł: 8

Tamta stronka juz wygasła wiec pomyslalem ze moze dobrze bedzie zgrac z google webcache tametego generatora poki jeszcze jest dostepne.


Załączniki:

Aby zobaczyć załączniki musisz się zalogować. Tylko zalogowani użytkownicy mogą oglądać i pobierać załączniki.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 21 maja 2014, o 09:53 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Witam,

Właśnie natknąłem się na inny ciekawy sposób tworzenia tablicy z wartościami wyliczanymi przez preprocesor. Nie trzeba robić dodatkowego pliku do includowania a wykorzystać rekurencję:
Kod:
#define XTAB0(n) func(n),
#define XTAB1(n) XTAB0(n) XTAB0(n+1)  XTAB0(n+2)  XTAB0(n+3)
#define XTAB2(n) XTAB1(n) XTAB1(n+4)  XTAB1(n+8)  XTAB1(n+12)
#define XTAB3(n) XTAB2(n) XTAB2(n+16) XTAB2(n+32) XTAB2(n+48)
#define XTAB4(n) XTAB3(n) XTAB3(n+64) XTAB3(n+128) XTAB3(n+192)

const uint8_t TABLE[] PROGMEM = { XTAB4(0) };


Dla powyższego kodu dostajemy w TABLE[] wartości będące wynikiem func(n) dla n od 0 do 255. Ale można to bardzo łatwo zmodyfikować na inne wielkości tablic oraz zmienić wartość początkową n na inną (zmiana w wywołaniu XTAB4(start_value)).

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 21 maja 2014, o 10:04 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27314
Lokalizacja: Szczecin
Pomógł: 1041

no fajne ciekawostki i smaczki ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 26 gru 2014, o 11:08 
Offline
Użytkownik

Dołączył(a): 08 gru 2014
Posty: 53
Lokalizacja: Sz-n
Pomógł: 0

A ja dłubałem program w Delphi, co mi zmienia format Excelowego słupka na format Pgm Space. Szlo to dość szybko, ale ta metoda jest niezła. Będę musiał ją przetrenować bo w perspektywie jest wpisanie okolo 30 tablic po 2048 elementów 16-bitowych by zrobić wavetable.
Jak będzie zainteresowanie, udostępnię wspomniany programik.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 17 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO