Mikrokontrolery - Jak zacząć?

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

czwartek, 3 marca 2011

EPP: LED vs ludzkie oko - by miszcz310

Autor: miszcz310
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%)

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

4 komentarze:

  1. Bardzo fajnie, ale mam inny pomysł. Można włączyć tryb PWM, i podstawiać do rejestru Output Compare wartość przesuwaną o 1 bit w lewo bądź prawo. OCR1A = (1<<licznik); Myślę, że tak jest prościej

    OdpowiedzUsuń
    Odpowiedzi
    1. Czyli, żeby zrobić zamiast predefiniowane progi, po prostu potęgować 2 i wstawiać? Też powinno dać radę i wyglądać ok.

      Usuń
  2. "Funkcja odwrotna do funkcji logarytmicznej jest funkcją potęgowa, czyli w naszym przypadku funkcją potęgową o podstawie 10."

    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.

    OdpowiedzUsuń
    Odpowiedzi
    1. 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ę.

      miszcz310

      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.