Diody LED czyli jak migac i świecić

UWAGA -nowa wersja
Po prawie pięciu latach odświeżyliśmy ten wpis, tak by lepiej odpowiadał na pytania początkujących. Zamiast tego wpisu polecamy nowe Diody LED czyli jak migać i świecić

Ostatnio zapadła cisza na StarterKicie, bo przed świętami przygotowywałem się do Bootstrapa 9.4, które to przygotowania zajęły mi większość wolnego czasu. Teraz korzystając z dnia wolnego, który sobie po świętach zostawiłem, nadrabiam zaległości.

Poprzednio zajmowaliśmy się tym jak Arduino może odczytać wartość z zewnętrznego czujnika (fotorezystora). Teraz będziemy starać się odczyt pokazać.

Użyjemy do tego 7 diod LED, które ułożone w rząd będą tworzyć wskaźnik – im więcej światła pada na fotorezystor tym więcej diod się zapali. Zaczniemy od końca, czyli jak to wygląda w akcji.


Arduino’s Eye from Starter Kit on Vimeo.

Wybaczcie słabą jakość, ale kamera w komórce to jedyne czym dysponuję aby uwiecznić moje eksperymenty.

Widać jednak co się dzieje. Poza kadrem przybliżam i oddalam fotorezystor do lampy, kolejne diody zapalają się i gasną w miarę jak natężenie światła padające na fotorezystor rośnie i maleje.

Diody LED są zamocowane bezpośrednio na płytce prototypowej, przez sprytne wygięcie i przycięcie nóżek układają się w linię i jednocześnie trzymają się pewnie na płytce.

Dioda LED zamocowana na płytce prototypowej

Dioda LED zamocowana na płytce prototypowej

Zdjęcie jest trochę nieostre (znowu komórka w akcji) ale widać dobrze jak jest zamocowana dioda. W jednym z dolnych rzędów otworów w płytce prototypowej podłączona jest masa układu i wszystkie diody dzielą to jedno podłączenie.W jaki sposób wygięte są nóżki diody pokazuje następne zdjęcie.

Pojedyncza dioda przygotowana do montażu

Pojedyncza dioda przygotowana do montażu

 

Schemat elektryczny połączenia diod LED z Arduino

Masa z Arduino (Gnd) zostaje podłączona do dolnego rzędu na płytce prototypowej. Dzielnik napięcia z fotorezystorem zostaje wpięty między masę a zasilanie z Arduino. Jako drugi rezystor użyłem 5,7 kΩ. Mając na uwadze, że rezystancja mojego fotorezystora zmienia się od kilkuset Ω do kilku MΩ mierzone napięcie na rezystorze 5,7kΩ będzie się wahać między prawie 5V a ledwo nad 0V, dlatego wartości odczytywane z wejścia analogowego będą w pełnej skali od 0 do 1023.

Tutaj na prośbę czytelników rysunek układu we Fritzingu:

Schemat na płytce stykowej połączenia diod LED z Arduino

Wszystkie diody zostają podłączone do szyny z masą. Każda z diod zostaje dopięta do wyjść cyfrowych Arduino przez rezystor. Rolą tego rezystora jest ograniczenie maksymalnego prądu jaki popłynie przez diodę. Nie chodzi o bezpieczeństwo diody ale wyjścia cyfrowego Arduino.

KOD:

// pin 1 nie jest używany
// gdy wartość jest 0 - to nie ma świecić
int leds[] = {-1,2,3,4,5,6,7,8};
int photoPin = 0;
int size = 8;
int val = 0;

void setup()
{
  //ustawiamy
  for (int i=1; i< size; i++) {
    pinMode(leds[i], OUTPUT);
  }
}

void loop()
{
  val = analogRead(photoPin);
  val = val/128;
  for (int i=1;i<size;i++) {
    if (i <= val ) {
      digitalWrite(leds[i], HIGH);
    } else {
      digitalWrite(leds[i], LOW);
    }
  }
  delay(200);
}

leds jest tablicą zawierające numery wyjść cyfrowych, do których podłączyliśmy kolejne diody. Ponieważ tablica jest numerowana od zera, wpisując nieistniejącą wartość wyjścia oraz pracując na indeksie tablicy zawsze od 1, pomijając zerowy, gdy natężenie światła jest najsłabsze gasną wszystkie diody.

Nasz wyświetlacz ma 8 stanów (od 1 do 7 diod świecących oraz stan zerowy ze zgaszonymi wszystkimi diodami) dlatego wartość odczytaną z wejścia analogowego dzielimy przez 128, uzyskując wynik od 0 do 7, co określa nam które diody mamy zaświecić.

Podsumowanie

Jest to pierwszy z postów, w którym zajmujemy się diodami LED, w jednym z następnych będzie o tym, jak wybrnąć z sytuacji gdy chcemy sterować diodami LED w liczbie większej niż 14. W takim przypadku odpada nam rozwiązanie użyte w tym układzie, gdzie jedno wyjście cyfrowe steruje jedną diodą.

22 thoughts on “Diody LED czyli jak migac i świecić

  1. RaV

    Cześć, od niedawna się tym bawię – fajne rzeczy piszesz na tych stronach.
    Niestety ten opis mi nie wychodzi, nie widzę opisu po lewej części obrazka – pod które piny należy podłączyć kabelki w okolicy czujnika światła?
    Pozdrawiam

    Odpowiedz
  2. RaV

    Tak, dokładnie o to chodziło. Tylko pod które wejście Analogowe to podpiąć – z kodu rozumiem, że jest to Analog 0, czy tak?
    Przy okazji, możesz wytłumaczyć zapis:
    int leds[] = {-1,7,8,2,3,4,5,6};
    dlaczego mamy tu “-1” a pozostałe cyfry nie są w kolejności, ma to jakieś znaczenie?

    I jeszcze jedno poza tym – tego już totalnie nie mogę rozgryźć – często w opisach (również w tym) spotykam zapis:
    (int i=1; i< size; i++)
    lub podobny,
    możesz mi powiedzieć o co tu chodzi i jaki jest tego funkcja i cel, co to jest “i”?
    Może pytania laika, ale o elektronice nie mam zielonego pojęcia i właśnie próbuję coś z tego zrozumieć

    Pozdrawiam

    Odpowiedz
  3. netmaniac Autor wpisu

    Tak, photoPin w tym kodzie to jest 0, wiec analog 0.
    -1 – to pozostałość ze starego kodu, bo miało być wyjście pomijane gdy wartość w tablicy jest mniejsza niż 0. Ale w pętli potem zaczynamy od indexu 1, wiec ten pierszy o numerze 0 (tablice w C są liczone od 0) i tak jest pomijany.

    Można by w sumie usunąć to -1 z początku tablicy i w pętli potem zacząć od 0 i kończyć na size-1

    for (int i=1; i< size; i++) {} to konstrukcja z języka C definiująca pętlę - w nawiasie są trzy pola oddzielone średnikiem. Pierwsze jest definicją tymczasowej zmiennej dostępnej 'w pętli', drugie pole jest warunkiem który jest sprawdzany przed każdym wykonaniem pętli - jeśli rezultat jest TRUE to kod zawarty w {} jest wykonywany raz. Ostanie pole jest wykonywane po każdym przebiegu kodu {}. Czyli definiujemy zmienną i o wartości początkowej 1, pętla jest wykonywana dopóki i nie jest równe lub większe od wartości size, a po każdym wykonaniu kodu wewnątrz {} i zostanie zwiększone o 1.

    Odpowiedz
  4. RaV

    OK,
    coraz więcej rozumiem i mam coraz więcej pytań,
    1. co z tą kolejnością cyfr w “int leds[] = {-1,7,8,2,3,4,5,6};” czy jest dowolna?

    2. z tego co widzę, to zawartość void setup() – “for (int i=1; i< size; i++)” czyli ta mała pętla, jest powtórzona w void loop().
    Po co ona jest w setup? Nie można pozostawić pustego setup?

    3. jeszcze pytanie z początku kodu, tu definiujemy co jest czym, prawda? czyli ustawiamy, że int to są diody, oraz, że int to photoPin, skąd program np. w tym miejscu “int i=1; i< size; i++” wie, o które int mi chodzi – czy ma wartości dodawać do diód czy do tego zera przy photoPin?

    Jeszcze raz zaznaczam, że się nie znam, dlatego jak będziesz tracił cierpliwość daj znać. Albo poleć jakiś adres gdzie akurat te proste podstawy programowania (?) są jeszcze prościej wyjaśnione ;-)

    Pozdrawiam

    Odpowiedz
  5. netmaniac Autor wpisu

    zwartość tablicy leds to są numery portów do których podłączamy kolejne diody – jak pomieszasz kolejność numerów to albo inaczej diody podłącz, albo diody nie będą się ‘po kolei’ zapalać.

    W setup pętla ustawia odpowiedni pin cyfrowy w tryb pracy wyjścia. W loop petla przechodzi po wszystkich wyjściach cyfrowych z diodami i zapala albo gasi w zależności od wartości odczytanej z fotrezystora.

    Co do 3 – to ze tablica “leds to sa diody” to nie wynika wprost z nazwy czy tego jak to zostało zdefiniowane – zależy to od kontekstu w jakim dane zostają użyte – wartości leds są używane aby zainicjować porty wyjścia i potem zeby wiedzieć gdzie jest która dioda i zapalać/gasić używając digitalWrite.

    Trudno to wytłumaczyć- trzeba poszukać tutoriali – jeżeli angielski to nie problem to polecam http://arduino.cc/en/Tutorial/HomePage do spraw związanych z Arduino. Tutoriala do samego C nie polecę, bo takowego nie potrzebuję, więc trduno mi coś polecić.

    Odpowiedz
  6. RaV

    Mam pytanie, dlaczego w każdym z układów podłączamy osobny opornik pod każdą diodę?
    Z tego co wyczytałem w sieci, spadek napięcia na diodzie koloru czerwonego wynosi 2V a prąd używany to 20mA.
    Czyli moglibyśmy np. 5 diód podłączyć równolegle do wspólnej masy przez opornik, którego opór wyliczymy tak:
    spadek napięcia 5V-2V=3V, równolegle podłączone 5 diód potrzebuje prąd wartości 5*20mA = 100mA. Czyli potrzebowalibyśmy jeden opornik o wartości R=3V/0,1A = 30ohm.
    Teoria powinna się zgadzać, ale dlaczego nie stosujemy tego w praktyce.
    (Problem pojawiłby się oczywiście przy stosowaniu diód o różnych kolorach-różne spadki napięć).

    Byłbym wdzięczy za informację na ten temat.

    Pozdrawaim

    Odpowiedz
  7. netmaniac Autor wpisu

    To by działało tylko jak zapalić chcesz wszystkie diody na raz. Jak chcesz zapalić jedną, to przez jedną by poszedł prąd 100 mA. Tyle nie da wyjście cyfrowe z Arduino a i dla żywotności diody to ma znaczenie. Jak dobierzesz mniejszy prąd to będą różnice w jasności świecenia w zależności od tego czy świeci jedna czy 5 diod…

    Odpowiedz
  8. Krzysztof

    A możesz dodać do tego bardziej czytelny schemat podłączenia jak w innych tutkach narysowany w Fritzing?
    Chciałbym zrobić ten schemat ale nie wiem do końca jak podłączyć kabelki.

    Odpowiedz
  9. netmaniac Autor wpisu

    @Krzysztof
    Będzie tylko jeszcze trochę czasu – standardowa dioda LED we Fritzingu ‘nie pasuje’ – rysunek będzie bardzo mało czytelny. Przerabiam część tak aby pasowała lepiej do tego zastosowania.

    Daj mi jeszcze dzień lub dwa i postaram się skończyć tak żeby było ładnie widać :)

    Odpowiedz
  10. SiB

    Albo mi się mieni w oczach albo w “Schemat elektryczny połączenia diod LED z Arduino” diody LED są zaporowo ustawione.

    Odpowiedz
  11. Ludwik

    1. Dlaczego ta macierz jest ułożona w taki sposób?
    int leds[] = {-1,7,8,2,3,4,5,6}; – diody zapalają się nieregularnie.
    Zauważyłem, że jak zmienię na int leds[] = {-1,2,3,4,5,6, 7,8}; to wtedy zapalają się tak jak na filmie.
    2. Jestem jeszcze świeży w arduino, więc pytanie podstawowe: dlaczego wstawiamy -1? a potem rosnąco? Diody mamy wpięte od wyjścia digital od 2 do 9, zatem skąd arduino wie, że taka jest kolejność? Przepraszam jeśli za głupie pytanie, ale nie rozumiem tego.

    Odpowiedz
  12. netmaniac Autor wpisu

    @Ludwik
    Szczerze mówiąc nie wiem czemu taka kolejność. Tzn wpis ma już swoje kilka lat :) a nie mam czasu odtworzyć układu. Faktycznie na zdrowy rozum powinno być tak jak Ty podałeś.

    W którymś momencie odręczne rysunki zmienialiśmy na te ładniejsze we Friztingu i może podczas tego został zrobiony porządek na schemacie a nie został poprawiony kod. W każdym bądź razie poprawię kod w przykładzie.

    A co do -1 – jest to wartość dla pokazania że nie jest używana. Pierwsza wersja kodu zaczynała numerować tablicę od indeksu 1, a C każda tablica automatycznie jest numerowana od zera. Więc można było inaczej skonstruować pętlę for albo po prostu wpisać bzdurną, nigdy nie używaną wartość – dlatego -1.

    Wniosek jest jeden – cały przykład należy napisać od nowa ;)

    Odpowiedz
  13. Ludwik

    Podpytałem kolegów i poprawiliśmy kod, aby nie było już problemów. Jak na razie wszystko działa, dzięki :)

    //pin 1 nie jest używany
    //gdy wartość jest 0 – to nie ma świecić

    int leds[] = {-1,2,3,4,5,6,7,8,9};
    int photoPin = 0;
    int size = 9;
    int val = 0;
    int val2 = 0;

    void setup()
    {
    Serial.begin(9600);
    //ustawiamy
    for (int i=0; i<size; i++) {
    pinMode(leds[i], OUTPUT);
    }
    }

    void loop()
    {
    val = analogRead(photoPin); //sczytuje wartość z fotorezystora w rozdzielczosci 1024
    val2 = analogRead(photoPin);
    val = map(val,160,950,0,8); //przyjęliśmy wartości 160 i 950, bo mniej więcej w takich granicach pojawiały // się odczyty val2 w serial monitorze. Dzięki temu łatwiej osiągnąć zgaszenie i zapalenie wszystkich diod
    for (int i=0; i<size; i++){
    if (i<=val) {
    digitalWrite(leds[i], HIGH);
    } else {
    digitalWrite(leds[i], LOW);
    }
    }
    delay(200);
    Serial.println(val2);
    }

    Odpowiedz
  14. Segitarius

    Odnośnie migania i świecenia. Mam taki kod do nauki. (Na żywca z książki). :

    // Listing 4.3
    #define LED 12
    #define BUTTON 7
    void setup()
    {
    pinMode(LED, OUTPUT); // pin wyjściowy dla diody LED
    pinMode(BUTTON, INPUT); // pin wejściowy dla przycisku
    }
    void loop()
    {
    if ( digitalRead(BUTTON) == HIGH )
    {
    digitalWrite(LED, HIGH);
    }
    else
    {
    digitalWrite(LED, LOW);
    }
    }

    Na pinie 7 powinienem mieć przycisk. Ale nie muszę go nawet podłączyć żeby dioda zaświeciła bo podpięcie samego przewodu do pinu 7 powoduje zaświecenie się diody. Żadnego napięcia nie podaję na ten pin a Arduino rozpoznaje go jako stan wysoki. O co chodzi? Robię coś źle?? Czy Arduino ma takie humory? Dziękuję z góry za pomoc :)

    Odpowiedz
    1. netmaniac Autor wpisu

      nie wiem jak wygląda Twój układ, ale jeżei nie podłączysz przycisku, wówczas wejście cyfrowe ‘wisi’ w powietrzu. Jest to stan nieustalony i w losowy sposób może się zmieniać. Ma prawo. Samo podłączenie przycisku nic nie zmieni, bo w momencie gdy przycisk jest ‘niewciśnięty’ to jest rozłączony i wejście cyfrowe nadal jest niepodłączone. Dlatego, zakładając że przycisk zwierać ma wejście do masy to w setup trzeba zmienić ustawienie przycisku BUTTON na: pinMode(BUTTON,INPUT_PULLUP);. Wówczas zostanie włączony wbudowany w Atmegę rezystor łączący zasilanie z wejściem. Dzięki temu, nawet z niedpodłączonym wejściem, będzie na nim cały czas napięcie 5V i nie będzie ‘migania’ stanów.

      Przycisk wtedy zwiera wejście do masy i w momencie gdy jest naciśnięty to jest LOW w pozostałych przypadkach HIGH, więc pewnie by uzyskać zapalanie się diody po naciśnięciu to trzeba zmienić warunek w if na digitalRead(BUTTON) == LOW

      Odpowiedz

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

This site uses Akismet to reduce spam. Learn how your comment data is processed.