Płytka aplikacyjna APP002 – 10 diod LED


Tematy pokrewne   Podrozdziały
(w budowie)
  Jedna linia, dwie diody LED.
Płytka aplikacyjna APP002
Programy dla APP002
 
 

Jedna linia, dwie diody LED

 
   

Mikrokontroler ATTINY13 posiada tylko 5 linii portów od PB0 do PB4 (PB5 pełni funkcję RESET), co pozwala dołączyć do niego bezpośrednio 5 diod LED. Opcję tę wykorzystujemy właśnie w płytce aplikacyjnej APP001. Okazuje się jednak, że przy pewnych założeniach do jednej linii portu da się podłączyć dwie diody LED i sterować nimi niezależnie. Jak?

Na płytce stykowej zmontuj poniższy układ:

Spis elementów

Element Ilość Opis
Płytka bazowa ATTINY13 1  
Programator 1  
Kabel z wtykami męskimi 3 Połączenia
Dioda LED niebieska 2  
Opornik 470Ω/0,125W 2 –(                )–

 

    

W układzie tym istotne są diody LED niebieskie, ponieważ ich napięcie pracy wynosi ponad 3V. Jeśli układ podłączymy do napięcia zasilania +5V, to diody pozostaną zgaszone, gdyż nie odłoży się na żadnej z nich potrzebne im napięcie pracy (2,5V to zbyt mało, aby dioda zaświeciła). Układ dołączamy za pomocą przewodów odpowiednio do wyjść Vcc, GND i PB0 w gnieździe wyjściowym na płytce APP000:

Vcc PB0 PB2 PB4
GND PB1 PB3 PB5

Gniazdo wyjściowe na APP000, widok od strony otworów.

Każda linia portu PB0...PB4 może znajdować się w czterech różnych stanach w zależności od ustawień sterujących nią bitów w portach DDRB i PORTB:

Nr Bity n = 0...4
DDRBn PORTBn Linia PBn
1 0 0 pracuje jako wejście. stan wysokiej impedancji
2 0 1 pracuje jako wejście, lecz podpięta do wewnętrznego opornika podciągającego
3 1 0 pracuje jako wyjście, stan logiczny 0, dołączona do masy
4 1 1 pracuje jako wyjście, stan logiczny 1, dołączona do Vcc

W stanie nr 1 mikrokontroler odłącza linię PBn, która przechodzi w stan wysokiej impedancji (praktycznie nie pobiera żadnego prądu, jakby jej nie było) i zaczyna pracować jako wejście danych. W tym stanie linia PB0 nie wpływa na nasz układ i obie diody pozostają zgaszone:

Stan nr 2 nas tutaj nie interesuje.

W stanie nr 3 na linii PB0 panuje poziom logiczny 0 (około 0,4V). Linię możemy potraktować tak, jakby wewnątrz mikrokontrolera została zwarta do masy (w sumie tak się dzieje, tyle że sygnał przechodzi przez tranzystor polowy, który pełni tutaj rolę włącznika elektronicznego). Skoro tak, to na diodzie D0 i górnym oporniku odłoży się napięcie prawie równe 5V i dioda ta zacznie świecić. Dioda D1 jest zwarta do masy i dalej nie świeci:

W stanie nr 4 linia PB0 ma wysoki poziom logiczny. Utrzymuje się na niej napięcie zbliżone do 5V (co najmniej 4,2V). Możemy przyjąć, że linia PB0 jest wewnątrz mikrokontrolera zwarta do linii zasilania Vcc (co również jest prawdą, ponieważ zwarcie następuje poprzez inny tranzystor polowy). W efekcie dioda D0 zostanie zwarta i nie będzie świecić. Natomiast napięcie na diodzie D1 i oporniku wzrośnie na tyle, że dioda się zaświeci:

Wynika z tego wniosek, że możemy zaświecać jedną z dwóch diod lub mieć obie zgaszone. Aby otrzymać świecenie obu diod naraz, musimy szybko zmieniać stan logiczny linii PB0 pomiędzy 0 a 1, gdy pracuje ona jako wyjście danych. Wtedy użytkownik zobaczy to jako zaświecenie się obu diod, chociaż naraz zawsze świeci się tylko jedna z nich. Zwróć uwagę, że jasność przy zaświeceniu obu diod nieco spada. Czy potrafisz wyjaśnić, dlaczego tak się dzieje?

Czy to samo da się uzyskać dla czerwonych diod LED? Tak, o ile zasilisz swój kontroler napięciem około 3V. Przy napięciu 3,3V z programatora (niektóre programatory posiadają możliwość zmiany napięcia na niższe za pomocą zworki) możesz dodać diodę prostowniczą, która obniży napięcie na diodach o około 0,6V (w przeciwnym razie w stanie nr 1 diody będą lekko świeciły, a o to nam przecież nie chodzi):

 

Jeśli nie masz możliwości obniżenia napięcia poniżej 5V, to zastosuj układ zasilania z dzielnikiem napięcia i tranzystorem:

Układ działa następująco:

Oporniki 470Ω i 1kΩ tworzą dzielnik napięcia. Na bazie tranzystora pojawia się napięcie równe około 3,4V. Jeśli tranzystor ma przewodzić prąd, to na jego emiterze musi być napięcie niższe od napięcia bazy o 0,6...0,7V. W efekcie na obu diodach i ich opornikach ograniczających odłoży się napięcie 2,7...2,8V. Jest ono zbyt niskie, aby diody zaświeciły (dla czerwonej diody LED napięcie przewodzenia wynosi około 1,8V). Zatem, gdy linia portu PBx mikrokontrolera jest w stanie wysokiej impedancji, obie diody LED są zgaszone. Jeśli teraz na linii PBx pojawi się niski poziom logiczny (napięcie około 0,7V), to dolna dioda będzie zwarta do masy i nie zaświeci. Natomiast na górnej diodzie i jej oporniku odłoży się napięcie około 2,1V. Opornik ograniczający prąd powinien mieć oporność równą (2,1 - 1,8) / 0,01 = 27...33Ω. Jeśli na linii PBx pojawi się poziom logiczny 1 (napięcie co najmniej 4,2V), to górna dioda nie zaświeci, ponieważ jest spolaryzowana zaporowo. Zaświeci dolna dioda. Opornik ograniczający powinien mieć oporność równą około (4,2 - 1,8) / 0,01 = 270Ω. Tranzystor wykorzystujemy tutaj jako regulator napięcia. W momencie przewodzenia diody górnej odkłada się na nim napięcie około 2,2V przy prądzie 0,01A. Daje to moc traconą równą 0,022W. Może to zatem być dowolny tranzystor npn (np. tani BC547, który potrafi przewodzić prąd do 0,2A). Jeden tranzystor pozwoli w ten sposób zasilić kilka diod, dla pewności warto do niego przykleić małą blaszkę miedzianą jako radiator odprowadzający nadmiar ciepła.

Po tym wstępie teoretycznym wróćmy do naszego pierwotnego układu z dwoma niebieskimi diodami LED na płytce stykowej. Prześlij do mikrokontrolera poniższy program:

Uruchom Eclipse, utwórz nowy projekt dla ATTINY13 i wpisz do edytora poniższy program:

/*
 * main.c
 *
 *  Created on: 03 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint16_t i;
    while(1)
    {
        DDRB = 0;   // Wszystkie linie w stan wysokiej impedancji
        PORTB = 0;
        _delay_ms(500);

        DDRB = 1;   // Linia PB0 jako wyjście, stan niski
        _delay_ms(500);

        PORTB = 1;  // Linia PB0 jako wyjście, stan wysoki
        _delay_ms(500);

        for(i = 0; i < 500; i++)
        {
    	    _delay_ms(1);
    	    PINB = 1; // Na przemian 0 i 1 na linii PB0
        }
    }
}

Po uruchomieniu diody powinny cyklicznie zaświecać się i gasić w kombinacjach: obie zgaszone, świeci lewa, świeci prawa, świecą obie. Świecenie obu diod uzyskujemy przez szybkie naprzemienne zapalanie raz jednej, raz drugiej diody.

 

 

 

Płytka aplikacyjna APP002

 
   

Płytka APP002 przewlekana z niebieskimi diodami LED

Zaprojektujemy płytkę, która będzie zawierała 10 niebieskich diod LED. Schemat układu jest następujący:

Spis elementów

Element Ilość Opis
Złącze kątowe męskie 2 x 4 Goldpin 1 połączenie z APP000
Dioda LED niebieska 10  
Opornik 470Ω/0,125W 10 –(                )–

 

    

 

Jeśli nie chcesz konstruować płytki aplikacyjnej APP002, to równie dobrze proponowany układ zmontujesz na płytce stykowej, którą podłączysz do płytki bazowej APP000 za pomocą przewodów.

Płytkę PCB projektujesz w programie Eagle (utwórz sobie nowy projekt o nazwie APP002) wg poznanych wcześniej zasad. Nie będziemy tego opisywać, ponieważ wszystkie elementy płytki APP002 były już zastosowane wcześniej w projekcie płytki APP001.

 

Płytka APP002 SMD z niebieskimi diodami LED

Na schemacie wymień elementy przewlekane na ich odpowiedniki SMD:

rlc   R-EU   R-EU_M0805   (oporniki)

led   LED   LEDSML0805 (diody LED)

 

 

 

 

 

Płytka aplikacyjna APP002 z czerwonymi diodami LED

Czerwone diody LED posiadają napięcie przewodzenia równe około 1,8V.  Napięcie zasilające układ musi być niższe od 3V, inaczej diody będą świeciły w stanie neutralnym. Obniżenie napięcia z 5V dokonamy za pomocą opisanego wcześniej układu na jednym tranzystorze n-p-n, np. BC 547. Tranzystor ten wytrzymuje maksymalny prąd IC-E = 100mA. Ustalimy zatem dla diod LED prąd 10mA.

Spis elementów

Element Ilość Opis
Złącze kątowe męskie 2 x 4 Goldpin 1 połączenie z APP000
Dioda LED czerwona, jasna 10  
Opornik 100Ω/0,125W 5 –(                )–
Opornik 220Ω/0,125W 5 –(                )–
Opornik 470Ω/0,125W 1 –(                )–
Opornik 1kΩ/0,125W 1 –(                )–
Tranzystor BC 547/548 1  

 

    

 

Płytka aplikacyjna APP002 z diodami ustawionymi w koło

Ciekawe efekty świetlne uzyskamy, jeśli diody LED na płytce APP002 będą ustawione w koło. Sam schemat elektryczny nie ulega zmianie. Modyfikacji wymaga tylko płytka PCB.

Linie czerwone oznaczają zworki. Wykonujesz je z kawałka drutu w izolacji, który prowadzisz po stronie elementów i przylutowujesz do pól lutowniczych po stronie ścieżek.

 

Płytka aplikacyjna APP002 z diodami czerwonymi ustawionymi w koło

Poniżej projekt płytki APP002 wykorzystujący diody czerwone LED 3mm.

 

 

 

Programy dla APP002

 
   

Program zaświecający naprzemiennie diody parzyste i nieparzyste

Ten program będzie bardzo prosty. Port B ustawiamy w tryb przesyłania danych z mikrokontrolera. Jeśli wpiszemy do rejestru PORTB bity zero, spowoduje to zaświecenie diod parzystych (D0, D2, D4, D6 i D8). Wpisanie do PORTB bitów 1 spowoduje zaświecenie diod nieparzystych (D1, D3, D5, D7 i D9). Operacje te wykonujemy cyklicznie w pętli.

/*
 * main.c
 *
 *  Created on: 10 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    DDRB  = 0b11111; // PB0..PB4 jako wyjścia
    PORTB = 0;       // Zapalamy diody nieparzyste

    while(1)
    {
        _delay_ms(500); // Czekamy 1/2 sekundy
        PINB = 0b11111; // Naprzemiennie zapalamy diody parzyste i nieparzyste
    }
}

 

Program przesuwający w lewo pojedynczy punkt

W programie będziemy musieli sterować kierunkiem linii portu B. Linia PBx jest ustawiana jako wyjście tylko wtedy, gdy jedna z podpiętych do niego diod LED ma być zaświecona. Jeśli obie diody LED mają pozostać zgaszone, linia PBx zostanie ustawiona jako wejście. Do przechowywania pozycji bitu stosujemy osobną maskę w zmiennej m.

/*
 * main.c
 *
 *  Created on: 10 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint8_t m = 0b00001; // maska

    while(1)
    {
        DDRB = m;       // Jedną z linii PBx ustawiamy jako wyjście
        _delay_ms(100); // Czekamy 1/10 sekundy
        DDRB = 0;       // Gasimy diody
        PINB = m;       // Dioda parzysta lub nieparzysta do zapalenia
        if(!PORTB)      // Jeśli parzysta, to było już 2 obiegi pętli
        {
            if(m == 0b10000) m = 0b0001; // Modyfikujemy maskę
            else             m <<= 1;
        }
    }
}

 

Program przesuwający punkt w lewo i prawo.

Dodajemy do poprzedniego programu zmienną d, w której przechowujemy informację o kierunku ruchu punktu. Dodatkowo należy zmienić logikę sterowania portem B.

/*
 * main.c
 *
 *  Created on: 10 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint8_t m = 0b00001; // maska
    uint8_t d = 1;       // kierunek ruchu, d = 1 - w lewo, d = 0 - w prawo

    while(1)
    {
        DDRB = m;       // Jedną z linii PBx ustawiamy jako wyjście
        _delay_ms(100); // Czekamy 1/10 sekundy
        DDRB = 0;       // Gasimy diody
        PINB = m;
        if(d)           // d = 1, punkt przesuwamy w lewo
        {
            if(!PORTB)
            {
                m <<= 1;
                if(m == 0b100000)
                {
                    PORTB = d = 0;
                    m = 0b10000;
                }
            }
        }
        else           // d = 0, punkt przesuwamy w prawo
        {
            if(PORTB)
            {
                PORTB >>= 1;  // Bit ma pozostać 1, lecz na niższej pozycji,
                              // inaczej spowoduje dołączenie opornika podciągającego
                m >>= 1;      // Przesuwamy maskę w prawo
                if(!m)
                {
                    d = 1;
                    PORTB = m = 0b00001;
                }
            }
        }
    }
}

W programie pojawiła się nowa konstrukcja:

 

a = b = wyrażenie;

 

Przypisanie (nadanie zmiennej wartości za pomocą operatora przypisania =) posiada w języku C wartość równą wartości przypisywanego wyrażenia. Pozwala to nadać wartość kilku zmiennym w jednej instrukcji:

 

a = b = c = d = e = f = 0;   // Wszystkie zmienne otrzymają wartość zero
a = b = c = d = e = f = 100; // Wszystkie zmienne otrzymają wartość sto

 

Kolejny program wykonuje to samo zadanie co poprzedni, lecz tym razem sterujemy liniami portu B dynamicznie na podstawie numeru diody, która ma zostać zapalona. Program staje się o wiele krótszy.

/*
 * main.c
 *
 *  Created on: 10 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint8_t n = 0;  // Numer LED
    int8_t  d = 1;  // Przyrost

    while(1)
    {
       DDRB = PORTB = 0;          // Gasimy wszystkie diody
       DDRB = (1<<(n >> 1));      // Wybieramy parę LED
       if(n & 1) PORTB = DDRB;    // Zapalamy właściwą diodę
       _delay_ms(100);            // Czekamy 1/10 sekundy
       n += d;                    // Modyfikujemy n
       if((n == 9) || !n) d = -d; // Modyfikujemy d
    }
}

 

Program tworzący dwa punkty poruszające się w lewo

Wbrew pozorom, rozwiązanie nie jest takie oczywiste. Dwa punkty świetlne będą wymagały zaświecenia obu diod parzystej i nieparzystej. Nie jest to możliwe. Zamiast tego będziemy szybko zapalać raz diodę parzystą, a raz nieparzystą. Obserwatorowi z powodu bezwładności wzroku będzie się wydawało, że świecą naraz obie diody LED. Poruszaj płytką szybko tam i z powrotem. Zobaczysz, że światło diod LED nie jest ciągłe, lecz przerywane.

/*
 * main.c
 *
 *  Created on: 10 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint8_t n = 0;  // Numer pierwszej diody LED
    uint8_t p,i;

    while(1)
    {
        for(i = 0; i < 51; i++)
        {
            DDRB = PORTB = 0;      // Gasimy wszystkie diody
            p = n;
            if(i & 1)              // Obieg nieparzysty
            {
                if(!(p & 1)) p++;  // Pozycja punktu nieparzystego
                p %= 10;
                DDRB = PORTB = (1 << (p >> 1));
            }
            else
            {
                if(p & 1) p++;     // Pozycja punktu parzystego
                p %= 10;
                DDRB = (1 << (p >> 1));
            }
            _delay_ms(2);
        }
        n++;
        if(n == 10) n = 0;
    }
}

Użyj do tego programu płytki z diodami ustawionymi w koło. Efekt będzie jeszcze ciekawszy. Jako ćwiczenie zastanów się nad przerobieniem tego programu tak, aby punkty poruszały się w prawo.

 

Program odwzorowujący bity ze zmiennej

Program będzie zaświecał diody, dla których bity zmiennej mają stan 1. Ponieważ diod LED na płytce APP002 jest 10, będziemy potrzebowali zmiennej 16-to bitowej. Typy zmiennych 16-to bitowych to:

int16_t  – zmienna 16-bitowa ze znakiem, zakres od -215 do 215 - 1, czyli od -32768 do 32756
uint16_t – zmienna 16-bitowa bez znaku, zakres od 0 do 216 - 1, 0...65535.

Program w pętli wyświetla na przemian bity parzyste i nieparzyste zmiennej b, w której tworzymy "węża", przesuwając bity w lewo i dopisując na końcu bit 0 lub 1.

/*
 * main.c
 *
 *  Created on: 11 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint16_t b = 0;  // Zmienna 16-to bitowa
    uint8_t  m;      // Maska bitowa
    int8_t i;
    uint8_t j,d = 1;

    while(1)
    {
        for(j = 0; j < 51; j ++)  // Pętla opóźniająca
        {
            m = PORTB = DDRB = 0; // Gasimy wszystkie diody
            for(i = 8 + (j & 1); i >= 0; i-= 2) // Pętla bitowa
            {
                m <<= 1;
                if(b & (1<<i)) m |= 1;  // Dodajemy bit 1
            }
            if(j & 1) PORTB = DDRB = m; // Zaświecamy diody nieparzyste
            else              DDRB = m; // Zaświecamy diody parzyste
            _delay_ms(1);
        }
        b = (b << 1) | d;
        if(      b == 0b0000001111111111) d = 0;
        else if (b == 0b1111110000000000) d = 1;
    }
}

Zastanów się nad programem przesuwającym "węża" w prawo.

Drobna modyfikacja w programie daje nam 10-cio bitowy licznik binarny:

/*
 * main.c
 *
 *  Created on: 11 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint16_t b = 0;  // Zmienna 16-to bitowa
    uint8_t  m;      // Maska bitowa
    int8_t i;
    uint8_t j;

    while(1)
    {
        for(j = 0; j < 51; j ++)  // Pętla opóźniająca
        {
            m = PORTB = DDRB = 0; // Gasimy wszystkie diody
            for(i = 8 + (j & 1); i >= 0; i-= 2) // Pętla bitowa
            {
                m <<= 1;
                if(b & (1<<i)) m |= 1;  // Dodajemy bit 1
            }
            if(j & 1) PORTB = DDRB = m; // Zaświecamy diody nieparzyste
            else              DDRB = m; // Zaświecamy diody parzyste
            _delay_ms(1);
        }
        b++;
    }
}

oraz odbijające się trzy punkty:

/*
 * main.c
 *
 *  Created on: 11 paź 2015
 *      Author: Geo
 */

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

int main(void)
{
    uint16_t b = 0b111;  // Zmienna 16-to bitowa
    uint8_t  m;          // Maska bitowa
    int8_t i;
    uint8_t j,d = 1;

    while(1)
    {
        for(j = 0; j < 101; j ++) // Pętla opóźniająca
        {
            m = PORTB = DDRB = 0; // Gasimy wszystkie diody
            for(i = 8 + (j & 1); i >= 0; i-= 2) // Pętla bitowa
            {
                m <<= 1;
                if(b & (1<<i)) m |= 1;  // Dodajemy bit 1
            }
            if(j & 1) PORTB = DDRB = m; // Zaświecamy diody nieparzyste
            else              DDRB = m; // Zaświecamy diody parzyste
            _delay_ms(1);
        }
        if(d) b <<= 1;
        else  b >>= 1;
        if((b == 0b1110000000) || (b == 0b111)) d ^= 1;
    }
}

 

 

Program tworzący efekt strzałów laserowych

W rozdziale o tablicach opisaliśmy sposób regulacji jasności świecenia diod LED przez sterowanie ich przebiegiem impulsowym o różnym stopniu wypełnienia. Ten sam sposób da się zastosować również tutaj. Poniższy program wykorzystuje tablicę do przechowywania wartości wypełnień impulsów sterujących poszczególne diody. Na podstawie tej tablicy program tworzy odpowiednie maski dla diod parzystych i nieparzystych. Efekt wygląda szczególnie ciekawie na płytce z diodami ustawionymi w koło.

/*
 * main.c
 *
 *  Created on: 12 paź 2015
 *      Author: Geo
 */

#include <avr/io.h>

int main(void)
{
    uint8_t t[] = {0,0,0,0,0,0,0,0,0,0};   // Tablica wypełnień
    uint8_t p = 0,i,j,k,m;
    while(1)
    {
        for(k = 0; k < 20; k++)            // Określa liczbę okresów  
        {
            for(j = 0; j < 32; j++)        // Tworzy okres
            {
                m = 0;                     // Zerujemy maskę
                for(i = j & 1; i < 10; i += 2) // Ustawiamy maskę
                {
                    m >>= 1;
                    if(t[i] > j) m |= 0b10000; // wg stanu wypełnień
                }
                PORTB = DDRB = 0;           // Gasimy diody
                if(j & 1) PORTB = DDRB = m; // Zaświecamy diody nieparzyste
                else              DDRB = m; // Zaświecamy diody parzyste
            }
            PORTB = DDRB = 0;
      }
      p++;                                  // Pozycja punktu
      if(p == 10) p = 0;
      for(i = 0; i < 10; i++) t[i] >>= 1;   // Zmniejszamy wypełnienia
      t[p] = 63;                            // Ustawiamy maksymalne wypełnienie
    }
}

 

W ramach ćwiczeń spróbuj stworzyć ciekawe efekty świetlne na płytkę APP002. Miło nam będzie, jeśli podzielisz się z nami wynikami swojej pracy – interesujące programy opublikujemy w naszym serwisie.

 



List do administratora Serwisu Edukacyjnego Nauczycieli I LO

Twój email: (jeśli chcesz otrzymać odpowiedź)
Temat:
Uwaga: ← tutaj wpisz wyraz  ilo , inaczej list zostanie zignorowany

Poniżej wpisz swoje uwagi lub pytania dotyczące tego rozdziału (max. 2048 znaków).

Liczba znaków do wykorzystania: 2048

 

W związku z dużą liczbą listów do naszego serwisu edukacyjnego nie będziemy udzielać odpowiedzi na prośby rozwiązywania zadań, pisania programów zaliczeniowych, przesyłania materiałów czy też tłumaczenia zagadnień szeroko opisywanych w podręcznikach.



   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2017 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.