Redakcja: dondu
Niniejszy artykuł jest częścią cyklu Efektywne Planowanie Projektu i przedstawia jedno z nadesłanych rozwiązań problemu:
LED vs ludzkie oko
Ze względu na fakt nieliniowej czułości ludzkiego oka moc oświetlenia należy zaproponować sposób realizacji liniowej skali jasności LED. Korzystając z faktu, że rozwiązaniem problemu jest funkcja potęgowa można przyjąć, że szybkie rozwiązanie powinna dać funkcja kwadratowa
gdzie:
- y - wartość rejestru OCR1A,
- x - procent jasności,
- a - współczynnik skalujący (procenty na liczbę 0-255).
Zadanie jest proste i polega na implementacji tabeli z przykładowymi 32 wartościami rejestru OCR1A, który pozwala licznikowi (timerowi) T1, przy pomocy techniki PWM, sterować sprzętowo LEDem podłączonym do pinu OC1A mikrokontrolera (tu podświetlenie LCD sterowane tranzystorem).
Osiągnięcie przez licznik wartości OCR1A powoduje zgaszenie LED, zaś przepełnienie się licznika jego zapalenie. Regulując wartością OCR1A bezpośrednio wpływamy na wypełnienie generowanego sygnału sterującego.
Wartości w tabeli pwm_lookup_table[] zostały wyznaczone z wykorzystaniem funkcji x². W związku z utworzeniem tablicy mającej 32 wartości jasność najniższa (bliska zeru), osiągana jest poprzez przepisanie do OCR1A wartości z pwm_lookup_table[0], zaś jasność największa (bliska ciągłemu świeceniu) uzyskiwana jest poprzez zapisanie do OCR1A wartości z pwm_lookup_table[31].
Jeśli chce się wyłączyć LED, lub zapalić go na stałe, powinno się zatrzymać PWM i odpowiednio ustawić poziom logiczny końcówki sterującej.
Kod sterujący nie jest duży, a jego większą część zajmuje inicjalizacja sprzętu oraz obsługa efektu rozjaśniania i ściemniania LEDa.
Tabelę przeliczeniową zawarłem w plikach:
Excella: epp_1.xls
OpenOffice: epp_1.ods
Po przeprowadzeniu testów otrzymany wynik jest zadowalający. Cykliczne przemieszczanie się po tabeli przeliczeniowej pozwala w łatwy sposób liniowo regulować jasnością podświetlenia wyświetlacza LCD.
// EPP - Rozgrzewka // Algorytm korekcji jasności LED w celu uzyskania płynnego rozjaśniania // i ściemniania widzianego przez ludzkie oko // // ky3orr, 2011.11.28 // http://www.serwis-elektroniki.prv.pl // ky3orr<mawpa>gmail.com // // Atmega8, zegar 1[Mhz] //#define F_CPU 1000000UL //wartosc sygnalu zegarowego w [Hz] #define LED_DIR DDRB //rejestr kierunku dla portu gdzie podlaczono LED #define LED_PORT PORTB //port do ktorego podlaczono LED #define LED_PIN PB1 //pin do ktorego podlaczono LED #include <avr/io.h> #include <util/delay.h> //tabela przechowujaca wartosci OCR1A wyznaczone funkcja x^2 uint8_t pwm_lookup_table[] ={1, 2, 4, 6, 8, 11, 15, 19, 23, 28, 33, 39, 45, 52, 59, 66, 74, 83, 92, 101, 111, 121, 132, 143, 155, 167, 180, 193, 207, 221, 235, 250}; void SetupLed (void) { LED_PORT &= ~(1<<LED_PIN); //standardowo niski stan logiczny na pinie LED LED_DIR |= (1<<LED_PIN); //ustawienie pinu sterujacego LED jako wyjscie } void InitPwmTimer(void) { TCCR1A |= (1<<COM1A1); //sprzetowy tryb sterowania LED przez //wyjscie OC1A (wlaczanie w zerze, //wylaczanie w OCR1A) TCCR1A |= (1<<WGM10); //tryb 8-bit fast PWM TCCR1B |= (1<<WGM12); //tryb 8-bit fast PWM TCCR1B |= ((1<<CS10) | (1<<CS11)); //preskaler = 64 (czestotliwosc pwm //okolo 60Hz) SFIOR |= (1<<PSR10); //reset preskalera OCR1A = pwm_lookup_table[0]; //minimalna jasnosc domyslnie } void SetupHardware (void) { ACSR &= ~(1<<ACD); //wylaczenie zbedznie pracujacego ACD SetupLed(); InitPwmTimer(); } int main(void) { uint8_t licznik = 0; //biezacy indeks tabeli pwm uint8_t kierunek = 1; //1-rozjasnianie, 0-sciemnianie SetupHardware(); while(1) { OCR1A = pwm_lookup_table[licznik]; //PWM zgodnie z biezacym krokiem if(kierunek) { //obsluga kierunku licznik++; } else { licznik--; } licznik &= 0x1f; //ograniczenie na 32 wartosci //(0-31 -> 0x0-0x1F) if(licznik == 0) { //sprawdzenie czy punkt zmiany kierunku if (kierunek) {licznik = 30;} //wartosc poczatkowa w przypadku //zmiany rozjasnianie->sciemnianie kierunek^=0x1; //zmiana kierunku } _delay_ms(50); //opoznienie dla oka :) } }Plik programu: led_pwm.c
Efekt końcowy:
Podsumowanie
Wykorzystane zasoby:
- pamięć programu FLASH: 234 bajty
Jak samodzielnie obliczyć wartości w exelu? Czy jest szansa na gotowy arkusz wspomniany w treści przez autora?
OdpowiedzUsuńPrzepraszam, to moje niedopatrzenie.
OdpowiedzUsuńZałączyłem już nadesłany plik tabeli przeliczeniowej w wersji Excell i OpenOffice. Przy okazji dodałem plik ze źródłem programu (pod listingiem kodu).
Program działa świetnie ale po uruchomieniu pojawiają się straszne zakłócenia, same z siebie załączają mi się mosfety umieszczone kawałek dalej na płytce prototypowej, podobno to taka wada PWMa ogólnie te zakłócenia?
OdpowiedzUsuńNajprawdopodobniej masz źle zaprojektowany schemat. Poczytaj artykuły z działu Zasilanie i zakłócenia
OdpowiedzUsuńPlik Excela jest niedostępny. Można prosić o poprawienie linku?
OdpowiedzUsuń