Redakcja: dondu
Niniejszy artykuł jest częścią cyklu Efektywne Planowanie Projektu i przedstawia jedno z nadesłanych rozwiązań problemu:
LED vs ludzkie oko
Ogólnie ludzkie oko jak i ucho ma charakterystykę proporcjonalna do funkcji
czyli do funkcji logarytmicznej o podstawie 10.
Funkcja odwrotna do funkcji logarytmicznej jest funkcją potęgowa, czyli w naszym przypadku funkcją potęgową o podstawie 10. Zatem chcemy, by nasza funkcja była podobna do funkcji potęgowej.
By uprościć kod i przyspieszyć pracę funkcji posłużyłem się dwoma tablicami. W tablicy T umieszczone są progi przełączania do następnych wartości. Progi te rozmieszczone są w sposób liniowy, czyli w równych odstępach. W funkcji przeliczającej dokonujemy sprawdzenia, w którym przedziale znajduje się nasza zmienna i zwracamy odpowiednią dla tego przedziału wartość.
Do programu dołączyłem dwa zestawy wykresów:
- prawe wykresy pokazują w jaki sposób następuje korekcja świecenia LED. Na osiach X odkładana jest zmienna licznik, natomiast na osiach Y wartość zwracana przez funkcję transformującą.
- lewe (gdzie skala osi Y jest logarytmiczna) wykresy pokazują jak dokładnie dopasowana jest korekcja do wzoru, który podałem na początku.
Poniżej wykres przedstawiający działanie funkcji z programu określonym w zadaniu.przez Dondu tutaj: LED vs ludzkie oko. Napisał on że dobrał swoje wartości eksperymentalnie, co można zauważyć porównując wykresy z czerwonymi liniami wyznaczającą przebieg wyżej podanej funkcji.
Wartości Dondu dobrane eksperymentalnie:
Wartości obliczone przeze mnie:
Program
Moje rozwiązanie ma tą zaletę, ze możemy zrobic funkcje o dowolnej charakterystyce, co moze sie przydać
nie tylko do sterowania dioda LED, ale teoretycznie do generowania dowolnych zmiennym przebiegów.
///////////////////////////////////////////////////////////// //EPP-Rozgrzewka //Funkcja tworzaca wrazenie liniowosci jasnosci diody dla oka ludzkiego // //Autor: miszcz310 //25.XI.2011 // //ATmega 8, F_CPU 8000000 //W moim kodzie poprawiana jest wartosc dla "prawej" diody ///////////////////////////////////////////////////////////// #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include<inttypes.h> /////////////////////////////////////////////////////////////////////////////// //Dzieki tej czesci kodu latwiejsze beda ewentualne zmiany //Dokladniejsze omowienie tego fragmentu nizej, podczas omawiania funkcji //przeliczajacej. Bo tylko do niej odnosi sie ten fragment kodu. #define N 12 const uint8_t T[N]={0,21,42,63,85,106,127,148,170,191,212,233}; const uint8_t LED_tab[N]={0,1,2,3,6,10,20,36,66,120,218,254}; ///////////////////////////////////////////////////////////// //Inicjalizacja doklanie taka sama jak dla programu //kolegi Dondu void PWM_init() { DDRB= (1<<PB2) | (1<<PB1); //Pod te piny podpiete LED'y TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0) | (1<<WGM10); //PWM tryb 5- Fast PWM, 8-bit TCCR1B = (1<<CS12); //preskaler = 256 } //Koniec inicjalizacji //Funkcja przeliczajaca. uint8_t LED(uint8_t liczba) { uint8_t i=0; while(liczba>T[i]) //Dopoki nie w przedziale { i++; if(i>N-1) //Wieksza niz indeks ?(zabezpieczenie) { i=N-1; //Ustaw maksymalny możliwy indeks break; //Przerwij pętlę } } return LED_tab[i]; //zwróc wartość funkcji dla odpowiadającego przedziału } int main() { PWM_init(); //Inicjalizacja uint8_t licznik=0; //Zmienna sterujaca wypenieniem uint8_t kierunek=1; while(1) { if(kierunek==1) { licznik+=1; if(licznik>=255) { kierunek=0; licznik=255; } }else{ licznik-=1; if(licznik<=0) { kierunek=1; licznik=0; } } OCR1B = licznik;//bezposrednie wypisanie OCR1A = LED(licznik); //Wppisanie po przeliczeniu _delay_ms(1); //Odczekaj } }
A oto efekt końcowy:
Podsumowanie
Wykorzystane zasoby:
- pamięć programu FLASH: 366 bajtów (0,3%)
"Funkcja odwrotna do funkcji logarytmicznej jest funkcją potęgowa, czyli w naszym przypadku funkcją potęgową o podstawie 10."
OdpowiedzUsuńNieprawda. Funkcja potęgowa ma zmienną podstawę a stały wykładnik. Funkcją odwrotną do logarytmicznej jest funkcja wykładnicza. Ma ona stałą podstawę (w tym przypadku 10), a zmienny wykładnik.
Oczywiście masz rację! Jak to pisałem to niesprawdziłem. W ogóle to jestem zaskoczony, że po 5 latach ktoś to jeszcze czyta! Dziękuję za cenną uwagę.
Usuńmiszcz310
i po siedmiu też ;)
UsuńCzyli, żeby zrobić zamiast predefiniowane progi, po prostu potęgować 2 i wstawiać? Też powinno dać radę i wyglądać ok.
OdpowiedzUsuń...i po 9ciu :)
OdpowiedzUsuń