Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.

czwartek, 3 marca 2011

EPP: LED vs ludzkie oko (korekcja gamma)


Autor: Dondu

2011.11.24

Na rozgrzewkę małe zadanie, które będzie nam potrzebne w pierwszym odcinku cyklu Efektywne Planowanie Projektu, w którym jednym z kilku zadań realizowanych przez mikrokontroler, będzie wykorzystanie PWM do regulacji świecenia diodą LED (będzie to zaledwie drobna część projektu).

Niektórzy z Was wiedzą z praktyki, inni z teorii, a jeszcze inni nie wiedzą, że regulując liniowo wypełnienie PWM, nie otrzymamy liniowego wrażenia zwiększania lub zmniejszania się światła generowanego przez LED.

Rozwiązania zadania:
Wynika to z faktu, iż każdy LED ma swoją charakterystykę strumienia światła i nie jest ona liniowa. Dodatkowo oko ludzkie także ma nieliniową charakterystykę czułości, na domiar złego zależną od barwy światła.


Możesz to zauważyć obserwując poniższy film:




Gdzie to można wykorzystać?
  • płynne regulacja LED np. w podświetlaniu wyświetlacza LCD,
  • liniowe sterowanie tranzystorem itp.
  • itd.


Proponuję więc na rozgrzewkę  zadanie stricte programowe, polegające na opracowaniu funkcji korygującej wypełnienie PWM (korekcja gamma) w taki sposób, by oko ludzkie miało wrażenie płynnego rozjaśniania i ściemniania diody.

Tych którzy nie wiedzą, co to takiego PWM, zapraszam do lektury: PWM - Co to takiego?

To co widzicie na filmiku zrealizowałem tak:

// EPP - Rozgrzewka
// Algorytm korekcji jasności LED w celu uzyskania płynnego rozjaśniania
// i ściemniania widzianego przez ludzkie oko
//
// Dondu, 2011.11.24
// http://mikrokontrolery.blogspot.com
//
// Atmega8, zegar 8MHz

#include <avr/io.h> 
#include <avr/interrupt.h> 
#include <util/delay.h> 


//progi PWM 
#define prog_0 230
#define prog_1 205
#define prog_2 180
#define prog_3 155
#define prog_4 130
#define prog_5 105
#define prog_6 80
#define prog_7 55
#define prog_8 30
#define prog_9 15


char LED_przelicz_jasnosc(char wartosc){
 
 //funkcja korygująca jasność świecenia, wartości dobrane doświadczalnie

 if(wartosc > prog_0) {
  return 255;
 }else if(wartosc > prog_1) {
  return 128;
 }else if(wartosc > prog_2) {
  return 80;
 }else if(wartosc > prog_3) {
  return 60;
 }else if(wartosc > prog_4) {
  return 50;
 }else if(wartosc > prog_5) {
  return 35;
 }else if(wartosc > prog_6) {
  return 20;
 }else if(wartosc > prog_7) {
  return 10;
 }else if(wartosc > prog_8) {
  return 6;
 }else if(wartosc > prog_9) {
  return 3;
 }else{
  return 0;
 }
}


int main(void) 
{ 

 char test = 0; //zaczynamy od PWM z duty cycle = 0
 char w_gore = 1; //
   
 DDRB= (1<<PB2) | (1<<PB1); //LEDY podpięte pod: PB2-LED lewy, PB1-LED prawy

 //PWM Mode 5 - Fast PWM, 8-bit
 //piny OC1A i OC1B ustawiane na Compare Match, kasowane przy BOTTOM czyli
 //Set OC1A/OC1B on Compare Match, clear OC1A/OC1B at BOTTOM, (inverting mode)
 TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0) | (1<<WGM10);
 
 TCCR1B = (1<<CS12); //preskaler = 256

  //pętla główna
 while(1) 
    { 
       
  _delay_ms(20); //opóźnienie, by efekt było widać

  if(w_gore) {   
   
   //rozjaśnianie LED

   if(test<240){
    test += 15;  //zmiana PWM (kork co 15)
   }else{
    //osiągnięto górną granicę
    test = 255;  
    w_gore = 0;  // zmień kierunek
   }

  }else{

   //ściemnianie LED

   if(test>15){
    test -= 15;  //zmiana PWM (kork co 15)
   }else{
    //osiągnięto dolną granicę
    test = 0;
    w_gore = 1;  // zmień kierunek
   }
  }

  
  OCR1B = LED_przelicz_jasnosc(test); //ustaw PWM LED lewy z korekcją
  OCR1A = test;      //ustaw PWM LED prawy bez korekcji
    } 
}
Plik programu: main11.c 

Jak zauważyłeś korekcja została zrealizowana z użyciem 10 progów, co wystarcza do osiągnięcia efektu jak na filmie. Ale innymi sposobami można zwiększyć płynność - spróbuj sam :-)

Podsumowanie

Wykorzystane zasoby:
  • pamięć programu FLASH: 228 bajtów (0,3%)




Zadanie dla Was
Waszym zadaniem jest opracować inne wersje rozwiązania tego problemu.
Stawiam tylko jeden warunek: Nie używamy liczb zmiennoprzecinkowych!

Masz pytania?
Jeżeli coś nie jest jasne, to zadaj pytanie w komentarzu do niniejszego artykułu.

Termin
Termin nadsyłania rozwiązań w przypadku rozgrzewki będzie krótki i ustalam na niedzielę 27.11.2011.
Zmiana terminu (prośba w komentarzu).  Nowy termin: 04.12.2011
Termin już upłynął, ale możesz przesłać swoje rozwiązanie, jeżeli jest ono inne (czytaj: lepsze) niż te opublikowane.

Forma dostarczania rozwiązań
Spakowany projekt AVR Studio 4 lub plik tekstowy o rozszerzeniu *.c
Proszę o bogate komentarze!

Po otrzymaniu rozwiązań wybiorę najciekawsze i opublikuję zgodnie z zasadami określonymi tutaj: Zasady publikacji EPP

Rozwiązania zadania:
Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

13 komentarzy:

  1. szkoda że taki krótki czas.
    nie było mnie na weekend i nie miałem pojęcia o zadaniu :)
    tydzień lub dwa to byłoby ok.
    Grzegorz Kaczmarek

    OdpowiedzUsuń
  2. OK, przedłużam więc czas o tydzień, do 4 grudnia 2011 (niedziela) włącznie.
    By nie przegapić niczego, warto się zarejestrować na Facebooku lub subskrypcji tematu: Subskrypcja

    Do tej chwili nadeszło jedno rozwiązanie, które opublikuję nie czekając na pozostałe, ponieważ jest bardzo fajnie opracowane z wykresami i filmikiem.

    OdpowiedzUsuń
  3. Ponieważ na razie nie wszyscy są artystami w C mam prośbę aby przynajmniej na początku pisać bardziej czytelny kod źródłowy. Chodzi o klamerki. Ciało poszczególnych funkcji powinno być wyraźnie widoczne. Początkującemu dosyć trudno odnajdować w listingu odpowiadające sobie pary nawiasów. Być zrozumiałym to cnota a nie ujma.

    OdpowiedzUsuń
  4. To nie jest takie proste ze względu na wąski obszar do pisania kodu zaledwie 80 znaków. Dodatkowo strasznie dużo pracy kosztuje przygotowanie tego dla HTML, na ale to nie jest wytłumaczenie :-)

    Postaram się zwracać bardziej uwagę na ten aspekt, w następnych kodach, by wyglądały co najmniej tak: Przykład

    Dziękuję za zwrócenie uwagi.

    OdpowiedzUsuń
  5. Jestem początkujący, i w programowaniu, i w programowalnych scalaczkach.

    Mógłby ktoś dokładniej opisać co znaczą komendy w linijkach 65-73?

    Szukałem, ale nic nie znalazłem.

    OdpowiedzUsuń
  6. Szukać powinieneś w datasheet ATmega8.

    Są to ustawienia bitów w rejestrach TCCR1A i TCCR1B, które odpowiednio ustawiają Timer1. Opis co zostało ustawione jest w komentarzu w liniach, które podałeś.
    Każdy bit jest nazwany dokładnie tak jak w datasheet, gdzie jest opis za co każdy z nich odpowiada.

    OdpowiedzUsuń
  7. Nie wiem dlaczego, ale u mnie dioda zamiast płynnie rozjaśniać się i ściemniać, miga po prostu z różną częstotliwością... Co może być powodem?

    OdpowiedzUsuń
  8. Na początek sprawdź, czy masz zegar ustawiony na 8MHz -(program jest napisany na taki zegar). Drugie co na szybko przychodzi mi do głowy z tak krótkiego opisu jak Twój, to może zastosowałeś diodę samodzielnie mrugającą?

    OdpowiedzUsuń
  9. Masz racje że nie powinnismy zaśmiecać tamtego wątku http://www.elektroda.pl/rtvforum/viewtopic.php?p=11224706#11224706 więc ponawiam moje zastrzeżenie tutaj - nieliniowość jest przede wszystkim efektem logarytmicznej charakterystyki oka http://pl.wikipedia.org/wiki/Prawo_Webera-Fechnera a nieidealne zachowanie diody nie będzie w praktyce zauważalne - przynajmniej w takim prostym układzie małej mocy gdzie LED zapala się i gaśnie praktycznie natychmiast.
    Więc popraw to co napisałeś :)

    OdpowiedzUsuń
  10. Tak, masz rację, że w tym wypadku najważniejsza jest charakterystyka ludzkiego oka, o której piszemy. Faktycznie powinien to być pierwszy argument na liście, a nie drugi - poprawię.

    Jednakże pozostałe czynniki, jak nieliniowość strumienia światła oraz źródła zasilania także w jakimś stopniu wpływają na końcowy efekt. Czy zauważalny dla oka? Być może nie, a być może nie dla każdego. To zależy od wielu czynników, np. częstotliwości PWM vs parametr czasu zapalania i gaszenia LED.

    Jednakże powinniśmy o tym pisać, by za chwilę ktoś inny, nie zarzucił nam, że nie napisaliśmy :-)

    Dziękuję za uważne czytanie artykułów.

    OdpowiedzUsuń
  11. A że tak zapytam. Gdzie można zobaczyć konkursowe rozwiązania?

    OdpowiedzUsuń
    Odpowiedzi
    1. Są na samym początku tego artykułu po prawej stronie pod pierwszą grafiką :)

      Usuń

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.