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ń