Kategorie: Wszystkie | Arduino
RSS
poniedziałek, 16 listopada 2009

Nudziło mi się niezmiernie ostatnimi czasy, i stwierdziłem, że warto by zebrać wszystkie znaleziska dotyczące Arduino wyprodukowane na polskich stronach. (Lepsze to niż pisanie pracy dyplomowej). W innych krajach, szczególnie za Wielką Wodą, to już szaleństwo na wyższym poziomie, a u nas to często ktoś coś robi, czasami jest o tym głośniej, ale w większości przypadków są to skromne epizodyczne spotkania z platformą Arduino.

czwartek, 05 listopada 2009

Jak rzekłem tak też robię. Wykorzystałem platformę Arduino do realizacji projektu prostego zegarka z budzikiem. A poniżej udostępniam schemat budowy urządzenia i kod źródłowy programu.

Na początku to był prosty stoper, potem zegarek, a w końcu stał się pełnoprawnym budzikiem. Lista funkcjonalności nie jest za długa:

  • wyświetlanie "aktualnego" czasu w formacie 24 godzinnym hh:mm:ss
  • możliwość ustawienia godzin, minut, sekund
  • budzik aktywujący się o ustalonym czasie
  • możliwość ustawienia godziny i minuty aktywacji budzika
  • możliwość zmiany stanu czuwania budzika: wyłączony, włączony
  • możliwość dezaktywacji budzika

Prototyp, mojej produkcji, wygląda może niezbyt ładnie, ale w miarę funkcjonalnie, i co najważniejsze wszystko jest w jednym działającym kawałku :)

Budzik

Poniżej, widok zegarka (z ikonką aktywnego budzika), i widok ustawień budzika.

Widok zegarka, widok budzika

 

Schemat budowy

Elementy składowe urządzenia:

  • Arduino Duemilanove
  • wyświetlacz 2x16 znaków LCD zgodny z sterownikiem Hitachi HD44780 (w moim przypadku model SSC2M16ULGY-03)
  • kabel USB, lub zasilanie bateryjne
  • 4 przyciski stykowe
  • 4 oporniki 10 kΩ
  • głośniczek - buzzer
  • przewody - do połączenia wszystkich elementów
  • (opcjonalnie) płytka prototypowa

Budzik można złożyć na dwa sposoby: wszystko sczepić "na pająka" lub wykorzystać płytkę prototypową. Trzecia opcja, to wytrawić płytkę PCB i wszystko ładnie zlutować, ale to chyba za dużo zachodu jak na budzik.

Budzik - schemat w Fritzing

Kod źródłowy

Poniższy kod źródłowy jest dostępny do dowolnego, nieograniczonego użytku.

#include <LiquidCrystal.h>

// LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) - przypisanie pinów
LiquidCrystal lcd(8, 7, 6, 5, 4, 3, 2);

// ikonka zegarka
byte clock1[8] = {16, 0, 1, 2, 4, 8, 16, 12};
byte clock2[8] = {24, 8, 12, 4, 6, 2, 26, 2};
byte clock3[8] = {3, 0, 0, 16, 17, 7, 28, 0};
byte clock4[8] = {4, 12, 8, 24, 16, 0, 0, 0};

// ikonka dzwonka
byte bell5[8] = {2, 5, 15, 16, 16, 16, 0, 0};
byte bell6[8] = {0, 0, 0, 16, 16, 24, 8, 12};
byte bell7[8] = {0, 0, 0, 0, 0, 31, 7, 2};
byte bell8[8] = {4, 2, 3, 1, 1, 31, 0, 0};

// zmienne czasu
int hour = 0;
int min = 0;
int sec = 0;

// zmienne budzika
int buzz_hour = 0;
int buzz_min = 0;
int buzz_on = 0;

// zmienna odliczająca interwał
long time_step = 0;

// przypisanie pinów do zmiennych
int button_hour = 12;
int button_min = 11;
int button_sec = 10;
int button_buzz = 9;
int buzzPin = 13;

// zmienne przechowujące stan przycisków
int last_button_hour = LOW;
int last_button_min = LOW;
int last_button_sec = LOW;


void setup() {
  
  // określenie pinów przycisków jako wejść
  pinMode(button_hour, INPUT);
  pinMode(button_min, INPUT);
  pinMode(button_sec, INPUT);
  pinMode(button_buzz, INPUT);
  
  // określenie pinu i wyciszenie buzzera
  pinMode(buzzPin, OUTPUT);
  digitalWrite(buzzPin, LOW);
  
  // inicjalizacja wyświetlacza: 2 wiersze po 16 znaków
  lcd.begin(16, 2);
  
  // rejestracja znaków niestandardowych wyświetlacza
  lcd.createChar(0, clock1);
  lcd.createChar(1, clock2);
  lcd.createChar(2, clock3);
  lcd.createChar(3, clock4);
  lcd.createChar(4, bell5);
  lcd.createChar(5, bell6);
  lcd.createChar(6, bell7);
  lcd.createChar(7, bell8);
}

void loop() {
  lcd.setCursor(0, 0);
  // jeśli minie przedział czasowy (interwał = 1000 - czas wykonania pętli) zmienna sec zwiększy się o 1
  if (millis() - time_step >= 995) {
    time_step = millis();
    sec++;
  }
  // warunki kontrolujące zależność minut od sekund, i godzin o minut
  if (sec > 59) {
    sec = 0;
    min++;
  }
  if (min > 59) {
    min = 0;
    hour++;
  }
  if (hour > 23) hour = 0;
  if (buzz_min > 59) buzz_min = 0;
  if (buzz_hour > 23) buzz_hour = 0;
  
  // wyświetlanie aktualnego czasu lub ustawienia budzika
  if(digitalRead(button_buzz) == HIGH) {
   // ikonka dzwonka
   lcd.write(4);
   lcd.write(5);
   lcd.print("Alarm         ");
   lcd.setCursor(0, 1);
   lcd.write(6);
   lcd.write(7);
   // ustawienia budzika
   lcd.print("   ");
   if (buzz_hour < 10) lcd.print("0");
   lcd.print(buzz_hour);
   lcd.print(":");
   if (buzz_min < 10) lcd.print("0");
   lcd.print(buzz_min);
   lcd.print(" ");
   if (buzz_on == 0) lcd.print("off");
   else lcd.print("on ");
  }  
  else {  
   // ikonka zegarka
   lcd.write(0);
   lcd.write(1);
   lcd.print("Time         ");
   // stan budzika
   if (buzz_on == 1) lcd.write(237);
   lcd.setCursor(0, 1);
   lcd.write(2);
   lcd.write(3);
   // aktualny czas
   lcd.print("   ");
   if (hour < 10) lcd.print("0");
   lcd.print(hour);
   lcd.print(":");
   if (min < 10) lcd.print("0");
   lcd.print(min);
   lcd.print(":");
   if (sec < 10) lcd.print("0");
   lcd.print(sec);
   lcd.print("    ");
  }

  // sprawdzanie stanów przycisków
  // jeśli jest wciśnięty przycisk budzika - zmiana ustawień budzika
  if (digitalRead(button_buzz) == HIGH) {
    if (digitalRead(button_hour) != last_button_hour) {
      if (digitalRead(button_hour) == HIGH) {
        buzz_hour++;
        }
       last_button_hour = digitalRead(button_hour);
    }
    if (digitalRead(button_min) != last_button_min) {
      if (digitalRead(button_min) == HIGH) {
        buzz_min++;
        }
      last_button_min = digitalRead(button_min);
    }
    if (digitalRead(button_sec) != last_button_sec) {
      if (digitalRead(button_sec) == HIGH) {
        if (buzz_on == 0) buzz_on = 1;
        else buzz_on = 0;
        }
      last_button_sec = digitalRead(button_sec);
    }
  }
  // jeśli przycisk budzika nie jest wciśnięty - zmiana aktualnego czasu
  else {
    if (digitalRead(button_hour) != last_button_hour) {
      if (digitalRead(button_hour) == HIGH) {
        hour++;
        }
      last_button_hour = digitalRead(button_hour);
    }
    if (digitalRead(button_min) != last_button_min) {
      if (digitalRead(button_min) == HIGH) {
        min++;
        }
      last_button_min = digitalRead(button_min);
    }
    if (digitalRead(button_sec) != last_button_sec) {
      if (digitalRead(button_sec) == HIGH) {
        sec++;
        }
      last_button_sec = digitalRead(button_sec);
    }
  }
  
// aktywacja alarmu budzika i działanie przez 1 minutę
if (hour == buzz_hour && min == buzz_min && buzz_on == 1) {
  if (millis() - time_step >= 400) digitalWrite(buzzPin, HIGH);
  if (millis() - time_step >= 600) digitalWrite(buzzPin, LOW);
  if (millis() - time_step >= 700) digitalWrite(buzzPin, HIGH);
  if (millis() - time_step >= 900) digitalWrite(buzzPin, LOW);
  // wyłączenie alarmu budzika przyciskiem
  if (digitalRead(button_buzz) == HIGH) buzz_on = 0;
}
else digitalWrite(buzzPin, LOW);
}

 

Wnioski

Odmierzanie czasu jest rozwiązane programowo, więc to sposób "ułomny" i niedokładny. Sekunda nie jest faktycznie sekundą, a i wbudowana funkcja millis() niestety nie pozwala na ciągłe działanie budzika przez, powiedzmy, dwa miesiące. Możliwe, że ktoś mi te wady wytknie, ale niestety nie chciało mi się lecieć do sklepu po zegar czasu rzeczywistego, a i założenie było takie, żeby całość była zrobiona z dostępnych elementów bez konieczności dokupywania czegokolwiek. Działa, nawet sprawnie mnie budzi i ...i tylko to się liczy :)

Jednakowoż, proszę o wytykanie wszelkich błędów i proponowanie udoskonaleń. Będą to dla mnie cenne uwagi.

 

Linki

 

niedziela, 01 listopada 2009

Ciąg dalszy, bo mam zamiar przerobić i rozbudować poprzednią zabawkę czyli Stoperek. To co udało mi się sklecić, działało, widać było, że działa i dodatkowo w miarę dobrze odmierzało czas :)

Do dyspozycji mam teraz:

  • to co było, czyli: Arduino Duemilanove, wyświetlacz LCD, przewód USB i kabelki,
  • breadboard, czyli po polsku płytka prototypowa,
  • około setki oporników 10 kΩ,
  • przyciski stykowe (push-buttony)
  • mały głośniczek - buzzer

Cel na dziś. Zbudować zegarek, z możliwością ustawiania aktualnego czasu za pomocą podłączonych przycisków. Ewentualnie rozszerzenie urządzenia o funkcjonalność budzika.

 

Porządki

Pierwszym krokiem będzie przeniesienie już zbudowanego układu na płytkę prototypową. Pierwotna wersja "na pająka" wyglądała średnio ładnie i raczej nie nadawała się do dalszej rozbudowy, np. podłączenia kilku przycisków.

Stoperek v2

Układ poszczególnych elementów na płytce prototypowej może być praktycznie dowolny, tak jak dowolna może być i sama płytka. Ważne jest, żeby poza już istniejącymi elementami składowymi, można było podłączyć przyciski (i oporniki do nich). Efekt w moim przypadku jest następujący (siedziałem nad tym 2 godziny):

Stoperek_v4

Żeby było ładniej, wszystkie piny wyświetlacza są podłączone w jednym ciągu, także piny linii sterujących zostały przepięte z pinów Arduino 10, 11, 12 na piny 6, 7, 8. Teraz podłączenia wyświetlacza LCD do Arduino wyglądają następująco:

Oznaczenie Pin LCD Pin Arduino
VDD (DC+5V) 1 +5V
VSS (GND) 2 GND
VO (Kontrast) 3 GND
RS (Register Sel.) 4 8
R/W (Read/Write) 5 7
E (Enable) 6 6
DB4 11 5
DB5 12 4
DB6 13 3
DB7 14 2

Zmodyfikowany kod programu poniżej:

// LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) - przypisanie pinów
LiquidCrystal lcd(8, 7, 6, 5, 4, 3, 2);

Zabawa dopiero się rozkręca...

Zegarek ma posiadać funkcjonalność ustawiania właściwego/aktualnego czasu ...za pomocą przycisków. I o ile przyciskami się zajmować na razie nie trzeba to warto by było zastanowić się, jak ustawić czas. Funkcją millis() manipulować się nie da i zawsze zwraca czas od podłączenia zasilania. Należałoby więc uniezależnić wyświetlanie sekund, minut i godzin od funkcji millis(), i dodatkowo pozwolić na ich zmianę. Rozsądnym rozwiązaniem wydaje się utworzenie trzech zmiennych, np. całkowitych, które będą przechowywały informacje odnośnie wskazania czasu. Potrzebne będzie jeszcze zabezpieczenie przed zaistnieniem takich anomalii, jak minuta 61, czy godzina 25. Na koniec, trzeba zapewnić właściwe odmierzanie czasu. Tutaj posłużymy się interwałem, który będzie zależny od funkcji millis(), a zmienna odpowiedzialna za sekundy będzie związana z interwałem. Tak więc sekcja loop() zmieni się mniej więcej tak:

//zmienna odliczająca interwał
long time_step = 0;
int sec = 0;   //sekundy
int min = 0;   //minuty
int hour = 0;  //godziny

void loop() {
// to co się będzie zmieniać, będzie zawsze znajdować się z drugiej linijce wyświetlacza
lcd.setCursor(4, 1);
//jeśli minie przedział czasu (interwał = 1000) zmienna sec zwiększy się o 1;
if (millis() - time_step >= 1000) {
time_step = millis();
sec++;
}
//warunki kontrolujące zależność sekund od minut, i godzin od minut
if (sec > 59) {
sec = 0;
min++;
}
if (min > 59) {
min = 0;
hour++;
}
if (hour > 23) hour = 0;
//estetyka: liczby zajmują zawsze dwie cyfry
if (hour < 10) lcd.print("0");
lcd.print(hour);
lcd.print(":");
if (min < 10) lcd.print("0");
lcd.print(min);
lcd.print(":");
if (sec < 10) lcd.print("0");
lcd.print(sec);
}

Wracamy teraz do spraw sprzętowych. Do Arduino trzeba podłączyć przyciski, za pomocą których będzie ustawiany czas. Konwencji podłączania jest kilka. Ja wybrałem opcję taką, że przycisk wciśnięty oznacza stan wysoki na wejściu cyfrowym Arduino. Schemat podłączenia przycisku poniżej.

button Arduino

Moja koncepcja zegarka zakłada użycie 4 przycisków: 3 odpowiedzialnych za ustawianiem czasu, i 1 odpowiedzialny za przełączanie widoku budzik/zegarek. Zamontowałem je, tak jak na załączonym obrazku:

Arduino based timer

To tyle, jeśli chodzi o sprawy sprzętowe. teraz czas napisać kilka linijek kodu, które poprawnie obsłużą podłączone przyciski.

 

Sterowanie czasem

A więc, zabawa we władcę czasu. Mamy 3 przyciski, które pozwalają zwiększać wskazanie godzin, minut, bądź sekund. Zasada działania każdego z nich jest taka sama, więc sprawę można przedstawić opisując działanie przycisku 1, którym można zmieniać wskazanie godzin.

Można by się ograniczyć do wykrywania wciśnięcia przycisku - przycisk wciśnięty to zmienna odpowiadająca godzinie zwiększa się o 1. Ale jakoś nie wierzę, żeby znalazł się ktoś, kto puści przycisk w ciągu kilku mikrosekund. Jeśli przycisk będzie przytrzymany dłużej wartość zmiennej wzrośnie o 2. W praktyce, każde użycie przycisku, ustawi wartość zmiennej na inną niż można by tego oczekiwać. Zatem, potrzebne jest wykrywanie zmiany stanu przycisku. Jeśli jest wciśnięty, a cykl wcześniej - nie, to wtedy wartość zmiennej zwiększa się o 1.

//sprawdzanie stanów przycisków
if (digitalRead(button_hour) != last_button_hour) {
if (digitalRead(button_hour) == HIGH) {
hour++;
}
last_button_hour = digitalRead(button_hour);
}

I zegarek już powinien działać, już można ustawić właściwy czas. Dodanie zerowania stanów przycisków, w warunku, gdzie sprawdzany jest interwał, pozwoli na przyciśnięcie i przytrzymanie przycisku, i zwiększanie wartości odpowiedniej zmiennej w tempie około sekundy.

 

Budzik

Cały kod potrzebny do działania budzika już praktycznie jest. Trzeba tylko powielić odpowiednie sekcje i operować na innych zmiennych (tych, które będą pamiętać czas budzika). Od zera trzeba tylko napisać kod, który spowoduje aktywację budzika. No i trzeba podłączyć do Arduino buzzera, żeby się gdzieś dźwięk wydobyał (polecam pin 13).  A więc do roboty!

Powielamy sekcję odpowiedzialną za sprawdzanie stanu przycisków. Działać ma tak: jeśli jest wciśnięty przycisk nr4 (budzikowy), to każde wciśnięcie pozostałych trzech przycisków zmienia stan zmiennych czasu budzika. Jeśli wciśnięty nie jest, to każde wciśnięcie tychże 3 przycisków zmieni czas zegarka. Czyli w praktyce, wstawiamy warunek sprawdzający stan przycisku od budzika, i w zależności od wyniku odpowiednią wersję skopiowanego kodu. Wyglądać to może mniej więcej tak:

  if (digitalRead(button_buzz) == HIGH) {
    if (digitalRead(button_hour) != last_button_hour) {
      if (digitalRead(button_hour) == HIGH) {
        buzz_hour++;
        }
       last_button_hour = digitalRead(button_hour);
    }
    if (digitalRead(button_min) != last_button_min) {
      if (digitalRead(button_min) == HIGH) {
        buzz_min++;
        }
      last_button_min = digitalRead(button_min);
    }
    if (digitalRead(button_sec) != last_button_sec) {
      if (digitalRead(button_sec) == HIGH) {
        if (buzz_on == 0) buzz_on = 1;
        else buzz_on = 0;
        }
      last_button_sec = digitalRead(button_sec);
    }
  }
  else {
    if (digitalRead(button_hour) != last_button_hour) {
      if (digitalRead(button_hour) == HIGH) {
        hour++;
        }
      last_button_hour = digitalRead(button_hour);
    }
    if (digitalRead(button_min) != last_button_min) {
      if (digitalRead(button_min) == HIGH) {
        min++;
        }
      last_button_min = digitalRead(button_min);
    }
    if (digitalRead(button_sec) != last_button_sec) {
      if (digitalRead(button_sec) == HIGH) {
        sec++;
        }
      last_button_sec = digitalRead(button_sec);
    }
  }

Podobnież należy postąpić z sekcją odpowiedzialną za prezentację wyników na wyświetlaczu LCD. Ja tam chcę widzieć, jak zmieniają się ustawienia budzika :)

if(digitalRead(button_buzz) == HIGH) {
    if (buzz_hour < 10) lcd.print("0");
    lcd.print(buzz_hour);
    lcd.print(":");
    if (buzz_min < 10) lcd.print("0");
    lcd.print(buzz_min);
    lcd.print("  ");
    if (buzz_on == 0) lcd.print("off");
    else lcd.print("on ");
  }  
  else {  
    if (hour < 10) lcd.print("0");
    lcd.print(hour);
    lcd.print(":");
    if (min < 10) lcd.print("0");
    lcd.print(min);
    lcd.print(":");
    if (sec < 10) lcd.print("0");
    lcd.print(sec);
    lcd.print("   ");
  } 

Do tego dorzucimy warunki trzymające w ryzach wskazania budzika, tak samo jak czasu:

  if (buzz_min > 59) buzz_min = 0;
  if (buzz_hour > 23) buzz_hour = 0; 

I na koniec "aktywator: budzika:

if (hour == buzz_hour && min == buzz_min && buzz_on == 1) {
  digitalWrite(buzzPin, HIGH);
  delay(200);
  digitalWrite(buzzPin, LOW);
  delay(100);
  digitalWrite(buzzPin, HIGH);
  delay(200);
  digitalWrite(buzzPin, LOW);
  delay(500);
}
else digitalWrite(buzzPin, LOW);

} 

Wnioski

Zegarek jest już gotowy, ma funkcję budzika, i w ogóle jest super. Ale jak to zwykle bywa, nie jest wolny od wad. Na początek: aktywacja alarmu. Jak już się włączy to będzie "grać" przez całą minutę, i sam się nie wyłączy. Oczywiście zmiana ustawienia stanu budzika z "on" na "off" załatwi sprawę, ale to dwa przyciski, a jakoś nie widzę siebie, nieprzytomnego, jak wykonuję aż tak skomplikowane czynności. Powinno się to odbywać intuicyjnie - leniwym pacnięciem w jeden przycisk.

Druga sprawa, to użycie przy miarowym "pik" "pik" budzika funkcji delay(). Przy zabawie z odmierzaniem czasu, lepiej omijać ją z daleka. Przy kodzie w powyższym stanie, po odegraniu minutki "pikania" zegarek będzie się spóźniał o około 3 sekundy. Warto by to znowu uzależnić jakoś od funkcji millis().

I na koniec: estetyka. Jakiś informatyk, czy inny geek będzie się cieszyć z byle jakiej formy prezentacji, byle tylko wśród innych krzaczków, znalazł to coś, co poprawnie wyświetla czas. Ale to ma być ładny zegarek, więc warto by ładnie wszystko wyświetlać :)

W chwili obecnej kod zegarka wygląda wygląda mniej więcej tak jak tutaj.

Po rozwiązaniu powyżej wymienionych problemów, na pewno wrzucę gotowy kod w osobnym poście :)

środa, 28 października 2009

Mam Arduino ...i mam wyświetlacz LCD. Operowanie na przyciskach i diodach jest bardzo edukujące, ale prawdziwa zabawa zaczyna się gdy naprawdę "widać" efekty pracy. A najlepiej ogląda się je, na dużym czytelnym LCD'ku.

Co mam, co chcę zrobić

Otóż do dyspozycji mam, wstępnie:

  • Arduino Duemilanove
  • Wyświetlacz LCD (2x16 znaków) - model: SSC2M16ULGY-03
  • praktycznie nieograniczona ilość skrętki ethernetowej kat. 5e (przewody)
  • brak baterii do zasilania Arduino, ale za to jest dłuuuugi kabel USB

Co chcę z tego wykombinować:

  1. podłączyć wyświetlacz LCD do Arduino,
  2. wyświetlić za pomocą Arduino cokolwiek, byleby to sensownie wyglądało,
  3. napisać sensowny programik-zabawkę na Arduino, żebym widział jak to ładnie wszystko działa.

 

Lutownica w dłoń...

Wyświetlacz LCD, świeżo po wydobyciu z opakowania miał jeden wielki minus. Nie można było wetknąć nigdzie przewodów, żeby nie trzeba było ich na stałe lutować. Zatem, pierwszym krokiem było przylutowanie do pinów na wyświetlaczu gniazdek GoldPin. Dzięki temu mogłem w nie wtykać przewody podobnie jak normalnie w Arduino :)

Tył wyświetlacza LCD

Krok numer dwa: dowiedzieć się koniecznie, co to za wyświetlacz, i opisać kolejne numery pinów. Co wiem? Wyświetlacz jest zgodny ze sterownikiem Hitachi HD44780, przynajmniej wg pana na allegro, u którego to kupiłem (no i był tani - 10zł). Czyli na pewniaka będzie działał z Arduino i dedykowaną dla nich biblioteką LiquidCrystal. Zaczynam dwa równoległe poszukiwania: jak wyprowadzone są piny na wyświetlaczu zgodnym ze sterownikiem HD44780 i jak - na wyświetlaczu SSC2M16ULGY-03. Poszukiwanie nr.2 prowadzi mnie donikąd - wszyscy mają problem z podłączeniem tego wyświetlacza do czegokolwiek, ale znajduję cenne info, że zasilanie powinno być na pinach 1, 2 lub 13, 14. Wraz ze słowem kluczowym HD44780 znalazłem tutorial Wiring up an LCD to an Arduino. Natomiat poszukiwanie nr. 1 doprowadziło do ciekawszych rezultatów, bo tam zasilanie było zawsze na pinach 1 (GND) i 2 (+5V). Był tylko jeden mankament, wszystkie zdjęcia wyświetlaczy wyglądały podobnie (do siebie), ale zupełnie różnie od egzemplarza posiadanego przeze mnie. Wygląd pasował idealnie do obrazka z znalezionego wczesniej tutorialu.

Teraz już wiem, że podstawową zasadą to: szukać właściwej specyfikacji aż do bólu.

Błędy jakie popełniłem:

  • piny 13, 14 wg tutorialu Wiring up an LCD to an Arduino, okazały się później pinami linii danych - mogłem spalić układ
  • większość forów, poradników itp, zgodnie twierdziła, że jak już zasilanie jest na pinach 1, 2, to na pinie 1, jest GND - u mnie jakoś nawet podświetlanie nie chciało zadziałać.
  • trudności w zlokalizowaniu pinu od kontrastu wyświetlacza (V0), czasami to pin 3, czasami 4, albo jeszcze inny, i zasilaniem do niego  - podobno trzeba przyłożyć napięcie +5V - u mnie nic nie było widać :/

 

Podłączenie

Warto gniazda GoldPin wlutować tak żeby nie zafajdać numeracji pinów wyjściowych, albo zapamiętać numerację przed wlutowaniem gniazdek. Co prawda, w przypadku podłączenia zasilania do pinów 13, 14, najpierw się scalak na wyświetlaczu się mocno nagrzeje, a dopiero po jakimś czasie spali, ale wg mnie lepiej nie ryzykować.

Opis pinów na wyświetlaczu LCD

 

A teraz cała reszta. Oznaczamy potrzebne nam piny wg specyfikacji:

Opis wyprowadzenia pinów wyświetlacza. Źródło: specyfikacja producjenta

Trzymać się będziemy luźno tutorialu Aruino - Liquid Crystal, czyli potrzebujemy pinów zasilania RS, R/W, Enable i 4 pinów linii danych (komunikacja 4-bitowa). Opisujemy połączenia LCD <=> Arduino:

Oznaczenie Pin LCD Pin Arduino
VDD (DC+5V) 1 +5V
VSS (GND) 2 GND
VO (Kontrast) 3 GND
RS (Register Sel.) 4 12
R/W (Read/Write) 5 11
E (Enable) 6 10
DB4 11 5
DB5 12 4
DB6 13 3
DB7 14 2

Pin R/W na LCD wg niektórych źródeł, można podłączyć do masy (GND), jednak osobiście nie testowałem :)

Jeśli już mamy wszystko podłaczone, możemy podłączyć zasilanie do Arduino i sprawdzić czy wszystko działa prawidłowo. Na sucho (bez żadnego programu w Arduino), zobaczymy, że w wyświetlaczu LCD działa podświetlanie, i kontrast: powinno być widać jeden rząd czarnych prostokątów.

 

Testing, testing...

Na wstępie: przykładowy program z Arduino IDE, ten z File > Examples > LiquidCrystal > Hello World, można spokojnie olać, przynajmniej w powyższej konfiguracji pinów (w wersji pin R/W do GND - powinno ładnie działać). Wykorzystuje 6 pinów, natomiast powyższy układ - 7 pinów.

#include <LiquidCrystal.h>

// LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) - przypisanie pinów
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

void setup() {
// Inicjalizacja wyświetlacza: 2 wiersze po 16 znaków
lcd.begin(16, 2);
// Wypisujemy tekst
lcd.print("Cos glupiego"); 
// zmiana pozycji kursora: drugi wiersz, pierwszy znak (numeracja od zera)
lcd.setCursor(0, 1);
// i jeszcze jeden tekst
lcd.print("Cos glupszego");
}
void loop() {
}

 

Coś konkretniejszego

Wyświetlacz jest podłączony, komunikuje się z Arduino, i poprzez bibliotekę LiquidCrystal potrafią się nawzajem zrozumieć. Teraz czas na coś, co pokaże, że wyświetlacz w połączeniu z Arduino "żyje", a nie tylko tępo i monotematycznie świeci - coś z pokaże trochę dynamizmu :)

Ma być dynamicznie. A Arduino działa w oparciu o wykonywanie pętli. Więc logicznym i prostym rozwiązaniem jest napisanie prostego stopera. Który będzie liczył czas, który minął od chwili podłączenia zasilania do układu.

Założenia:

  • prostota: więc wykorzystamy najprostszą funkcję millis(), liczącą milisekundy czasu działania Arduino,
  • to jest stoper: czyli godzina, ma 60 minut, minuta - 60 sekund.
Efekt poniżej:

#include <LiquidCrystal.h>

// LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) - przypisanie pinów
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

void setup() {
// Inicjalizacja wyświetlacza: 2 wiersze po 16 znaków
lcd.begin(16, 2);
// Tytuł  - nie będzie się zmieniać
lcd.print("Stoperek v0.2");
}

void loop() {
// to co się będzie zmieniać, będzie zawsze znajdować się z drugiej linijce wyświetlacza
lcd.setCursor(0, 1);
// trik, który czyści linijkę wyświetlającą czas
if ((millis()/1000)%60==0) lcd.print("            ");
lcd.setCursor(0, 1);
// godziny
lcd.print((millis()/3600000)%24);
lcd.print(":");
// minuty
lcd.print((millis()/60000)%60);
lcd.print(":");
// sekundy
lcd.print((millis()/1000)%60);
}

Skompilować, wgrać do Arduino, odpalić i... działa!

Poniżej efekt podłączenia sprzętu nr.1 ( czyli na pająka) z działającym programem.

Stoperek_v2

 

Wskazówka: Jeśli już będziemy pewni, że komunikować się będziemy z wyświetlaczem w trybie 4-bitowym, warto przesunąć podłączenia pinów wyświetlacza RS, R/W, Enable z pinów Arduino 12, 11, 10 na piny 8, 7, 6. Przynajmniej wszystko w kupie siedzi, i ewentualnie jakąś prowizoryczną wtyczkę można zrobić.

środa, 21 października 2009

Mając chwilkę wolnego czasu założyłem bloga. Tym razem porzuciłem Wordpressa i własny serwer, i zdecydowałem się na platformę blogową udostępnianą bezpłatnie przez firmę Agora SA. Do wyboru miałem jeszcze Bloggera, ale jakoś nie jestem chyba aż takim fanatykiem Google, i wstępnie zdecydowałem się na coś z krótką nazwą i polską domeną.

Zobaczymy co z tego wyniknie :)