LCD 쉴드를 이용해서, 원하는 글자를 출력해보자.

LCD 쉴드

LCD 쉴드에는 아래 그림처럼 LCD(8 * 2) 와 6 개의 스위치 버튼이 준비되어 있다.

총 9 개의 핀을 사용한다. 각각의 핀 매칭은 다음과 같다.

  1. LCD RS pin to digital pin D8
  2. LCD R/W pin to digital pin D11
  3. LCD Enable pin to digital pin D9
  4. LCD D4 pin to digital pin D4
  5. LCD D5 pin to digital pin D5
  6. LCD D6 pin to digital pin D6
  7. LCD D7 pin to digital pin D7
  8. LCD LEDK pin to PWM digital pin D10 ( PWM제어로 전압을 조절하여 LCD의 밝기를 조절합니다.)
  9. Keypad pin to analog pin A0 (5개의 스위치 버튼 중 어떤 것이 눌렸는지 알아내는데 사용)

Hello World

가장 간단한 예제인 hello world 를 LCD 에 출력해보겠다. 아두이노 IDE 에는 각 라이브러리 모듈 별로 예제가 포함되어 있다. 여기에 있는 예제를 그대로 사용하면 된다.
하지만 여기서 유의해야할 점이 있다. 이들 예제의 기준은 모두 정품(!) 쉴드를 기준으로 하고 있기 때문에, 내가 구입한 유사 제품과는 다를 수 있다.

기존의 Hello world 예제는 다음과 같다. 이 예제를 그대로 올리면 아무 것도 출력되지 않을 것이다. 바로 핀(PIN) 번호가 바뀌었기 때문이다.

/*
  LiquidCrystal Library - Hello World
 
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 This sketch prints "Hello World!" to the LCD
 and shows the time.
 
  The circucomputer:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 
 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe
 
 This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */
 
// include the library code:
#include <LiquidCrystal.h>                             //  LCD 제어를 하기 위한 라이브러 추가
 
// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);                                         // 주석 처리
 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);                                              // 추가한 부분
 
void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
}
 
void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis()/1000);
}

LCD 의 첫 줄에는 Hello world 를 출력하고, 두번째 줄에는 시간을 카운트하는 프로그램이다.
LCD 라이브러리에서는 여러가지 함수들을 제공하고 있다.

여러가지 형태의 LCD 제어 타입을 설정하고, 제어 핀과 데이터 핀을 설정한다. 프로토 타입은 다음과 같다.

LiquidCrystal (RS, ENABLE, D4, D5, D6, D7);

5개의 인자들은 모두 핀 이름을 나타낸다. 핀 배선에 따라 인자들은 얼마든지 달라질 수 있다. 여기서는 8(RS), 9(E), 4(D4), 5(D5), 6(D6), 7(D7) 핀을 사용한다.

핀이름 설명
RS(Register Select) LCD 의 제어 명령과 데이터 입력 제어 신호를 설정한다. 신호가 Low(0) 이면 명령제어 입력 선택(IR 선택), 신호가 High(1)이면 데이터 입력 선택(DR 선택)
E(Enable) LCD 를 동작시키는 핀이다. 신호가 Low(0) 이면 LCD 가 동작하지 않는다. 신호가 High(1) 이면 LCD 가 동작한다
DB4 - DB7 마이크로 프로세서와 LCD 간의 데이터를 주고 받는 단자이다. 8비트 제어와 4비트 제어 방법이 있으며 4비트 제어시 DB4-DB7 의 4개 핀을 사용한다
lcd.begin(16, 2);     //  LCD 의 크기를 설정한다. 우리는 16 * 2 LCD 를 사용한다.
lcd.print("Hello!");       // 출력할 문자를 지정한다. 문자의 형태는 BASE, BIN, OCT, DEC, HEX 로 할 수 있다. 

커서 위치를 행(col), 열(row) 위치로 이동시킨다. 커서가 위치한 곳에서부터 새로운 문자가 표시된다.

ex) lcd.setCursor(0,1);    // 아래 줄, 맨 처음에 커서를 옮김

ex) lcd.clear();              // LCD 의 화면을 깨끗이 지우고 커서는 왼쪽 맨위(0,0)로 위치시킨다.
ex) lcd.home();      // 커서의 위치는 0,0(왼쪽 맨위)로 이동 시킨다. 표시되어 있는 문자는 그대로 표시된다. lcd.clear() 은 표시된 모든 문자를 지우고 0,0 으로 이동한다.

LCD 에 '_' 커서가 나타나게 할 때는 cursor(), 커서를 표시하지 않을 경우는 noCursor() 를 사용한다.

lcd.cursor();           // 커서가 표시됨
lcd.noCursor();        // 커서가 표시되지 않음

LCD 에 커서가 깜박이거나 깜박이지 않게 한다.

lcd.blink();              // 커서가 깜박임
lcd.noBlink();        // 커서가 깜박이지 않음

LCD 에 출력된 문자를 보이지 않도록 할 경우 noDisplay() 을 사용하고, noDisplay() 에 의해 보이지 않고 있는 문자들을 보이도록 할 경우에는 display() 을 사용한다.

lcd.noDisplay();           // LCD 에 출력되어 있는 문자가 표시되지 않음
lcd.display();             // 문자들을 다시 보이도록 함

LCD 에 출력되어 있는 문자를 오른쪽으로 이동시키려면 scrollDisplayRight(), 왼쪽으로 이동시키려면 scrollDisplayLeft() 를 사용한다.

lcd.scrollDisplayRight();        // LCD 에 문자들을 오른쪽으로 1칸 이동 시킴
lcd.scrollDisplayLeft();          // LCD 에 문자들을 왼쪽으로 1칸 이동 시킴

현재 문자가 쓰여지고 있는 방향으로 1칸씩 자동으로 이동한다.

lcd.autoscroll();     // LCD 에 문자들을 오른쪽으로 1칸 이동

LCD 에 문자가 쓰여지는 방향을 설정한다. 기본은 왼쪽에서 오른쪽으로 쓰여진다.

lcd.leftToRight();    // LCD 에 문자들을 오른쪽으로 쓰여지도록 설정
rightToLeft();         // LCD에 문자들을 왼쪽으로 쓰여지도록 설정

LCD 에 출력할 사용자 문자를 만드는 명령어, 5 * 8 픽셀의 문자 8개(1~8)까지 만들 수 있다. 사용자 문자는 8바이트 어레이로 정의한다. 각 바이트는 5개의 픽셀의 상태를 5비트로 만든다. 만들어진 사용자 문자는 lcd.write(n) 명령에 의해 LCD 에 출력한다.

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
 
byte userFont1[8] = { B00000, B10001, B00000, B10001, B01110, B00000 };
 
void setup()
{
lcd.createChar(1, userFont1);
lcd.begin(16, 2);
lcd.write(1);
}
 
void loop()
{
}
lcd.write(0);          // LCD 에 문자를 씀. 사용자 문자가 출력됨

입력값을 받아 LCD 에 출력하기

6개의 버튼 중 가장 오른쪽에서 있는 버튼이 리셋으로 사실상 총 5개의 스위치 버튼을 사용할 수 있다. 5개의 버튼 중 어떤 것이 눌렸는지 알아내는 루틴을 알아보자.
알아내는 방법은 P0 에 걸리는 전압을 기준으로 한다.

int adc_key_val[5] ={30, 150, 360, 535, 760 };         // 전압을 총 5 단계로 나눠 구분한다
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
 
void setup() 
{
  Serial.begin(9600);
}
 
void loop()
{
 
  adc_key_in = analogRead(0);                      // 핀 P0 에 걸리는 전압을 읽는다
  key = get_key(adc_key_in);                        // 몇번 핀인지 리턴한다
  if (key != oldkey)                           // 계속 누르고 있는가?
  {
     delay(50);                                   // wait for debounce time
     adc_key_in = analogRead(0);   // 핀 P0 에 걸리는 접압을 읽는다
     key = get_key(adc_key_in);    // 몇번 핀인지 리턴한다
     if (key != oldkey)
     {
       oldkey = key;
 
       if (key==0)
       {
          Serial.println("push 0 key");
       }
 
       if (key==1)
       {
          Serial.println("push 1 key");
       }
 
       if(key==2)
       {
          Serial.println("push 2 key");
       }
 
       if(key==3)
       {
          Serial.println("push 3 key");
       }
 
       if(key==4)
       {
          Serial.println("push 4 key");
       }       
    }
  }  
 
}
 
int get_key(unsigned int input)         // 전압에 따라 키 번호를 리턴하는 함수
{
 int k;   
 for (k = 0; k < NUM_KEYS; k++)
 {
  if (input < adc_key_val[k])           // 총 5개의 전압을 차례대로 비교한다
  {          
    return k;
  }
 }   
        if (k >= NUM_KEYS)
        k = -1;     // No valid key pressed
       return k;
}

위 프로그램으로 각각의 스위치 키 값을 알아냈다.

이름 키값
Select 4
3
1
2
0

위 정보를 가지고 버튼을 누를 때마다 LCD 에 버튼의 이름이 출력되도록 해보자.

#include <LiquidCrystal.h>
 
LiquidCrystal lcd(8,9,4,5,6,7);
 
 
int adc_key_val[5] ={30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
 
void setup() 
{
  Serial.begin(9600);
 
  lcd.begin(16,2);
 
  lcd.clear();
  lcd.print("PIN TEST!!");
 
  lcd.setCursor(0,1);
}
 
void loop()
{
 
  adc_key_in = analogRead(0);   // read the value from the sensor
  key = get_key(adc_key_in); // convert into key press
  if (key != oldkey) // if keypress is detected
  {
     delay(50);  // wait for debounce time
     adc_key_in = analogRead(0);   // read the value from the sensor
     key = get_key(adc_key_in);    // convert into key press
     if (key != oldkey)
     {
       oldkey = key;
 
       lcd.setCursor(0,1);        
 
       if (key==0)
       {
         lcd.print("         ");
         lcd.setCursor(0,1);
          Serial.println("push 0 key");
          lcd.print("RIGHT!!");
       }
       else if (key==1)
       {
         lcd.print("         ");
         lcd.setCursor(0,1);
          Serial.println("push 1 key");
          lcd.print("HIGH!!");
       }
       else if (key==2)
       {
         lcd.print("         ");
         lcd.setCursor(0,1);
          Serial.println("push 2 key");
          lcd.print("LOW!!");
       }
       else if (key==3)
       {
         lcd.print("         ");
         lcd.setCursor(0,1);
          Serial.println("push 3 key");
          lcd.print("LEFT!!");
       }
       else if(key==4)
       {
         lcd.print("         ");
         lcd.setCursor(0,1);
          Serial.println("push 4 key");
          lcd.print("SELECT!!");
       }
 
       lcd.setCursor(0,1);
    }
  }  
 
}
 
// Convert ADC value to key number
int get_key(unsigned int input)
{
 int k;   
 for (k = 0; k < NUM_KEYS; k++)
 {
  if (input < adc_key_val[k])
  {          
    return k;
  }
 }   
        if (k >= NUM_KEYS)
        k = -1;     // No valid key pressed
       return k;
}

가변저항의 다이얼을 돌리면 밝기가 변하도록 하자. 먼저 아래 그림과 같이 회로를 만든다.

디지털 시계

시계를 구동하기 위해서는 타이머를 이용해야 한다. 여기서는 타이머2 라이브러리 MsTimer2 를 사용한다.
http://playground.arduino.cc/Main/MsTimer2 에서 다운받을 수 있다. 압축을 풀고 아두이노 IDE 가 설치된 라이브러리 디렉토리에 복사하면 설치가 끝난다.

#unzip MsTimer2.zip
#cp -arf MsTimer2 usr/local/program/arduino/libraries/

이제 아두이노 IDE 를 재시작하면 '스케치 → 라이브러리 가져오기' 메뉴에 MsTimer2 가 등록되어 있을 것이다.

타이머가 오버플로어 인터럽트가 발생하는 주기(ms) 와 발생 시 호출하는 함수(핸들러)를 설정한다.

ex) MsTimer2(30, DotDisplay);      // 30ms 마다 DotDisplay 함수를 호출

타이머2 를 시작한다. 오버플로어 인터럽트가 발생하도록 설정한다.

ex) MsTimer2::start();

타이머2를 정지시킨다. 오버플로어 인터럽트가 발생하지 않도록 설정한다.

ex) MsTimer2::stop();
#include <MsTimer2.h>                 // 타이머 헤더 파일 추가
#include <LiquidCrystal.h>
 
...
 
void setup()
{
 
  lcd.begin(16,2);
  lcd.setCursor(0,0);
 
  lcd.print("*Clock1*");
 
  MsTimer2::set(10, clock);         // 10ms 마다 타이머 인터럽트가 발생하여 핸들러 함수(clock) 가 호출됨
  MsTimer2::start();                    // 타이머 인터럽트 시작
}
 
void loop()
{   
...
       else if (key==1)                    // 윗쪽 화살표 버튼이 눌릴 때마다 시간이 증가
       {
         lcd.print("         ");
         lcd.setCursor(0,1);
          Serial.println("push 1 key");
          hours++;
          seconds = 0;
          if(hours > 23) hours = 0;
          //lcd.print("HIGH!!");
       }
       else if (key==2)                      // 아랫쪽 화살표 버튼이 눌릴 때마다 시간이 감소
       {
         lcd.print("         ");
         lcd.setCursor(0,1);
          Serial.println("push 2 key");
          //lcd.print("LOW!!");
          minutes++;
          seconds = 0;
          if(minutes > 59) minutes = 0;
       }
...
 
  lcd.setCursor(0,1);
  displayDigits(hours);               // 시간출력
  displayDigits(minutes);            // 분 출력
  displayDigits(seconds);           // 초 출력
  delay(200);
}
 
void displayDigits(int digits)
{
  if(digits < 10) lcd.print("0");        // 한자리 수 일때는 앞에 0 을 붙임
  lcd.print(digits);
  lcd.print(":");
}
 
void clock()                            // 타이머 인터럽트 핸들러
{
  count++;
 
  if(count == 100){                  // 10ms X 100 = 1초 일때
    count = 0;
    seconds++;
    ledState = !ledState;
    digitalWrite(3, ledState);    // 1초마다 LED 를 켜거나 끈다
  }
 
  if(seconds == 60){               // 60초 일때
    minutes++;
    seconds = 0;
 
    if(minutes == 60){               // 60분 일때
      hours++;
      minutes = 0;
 
      if(hours == 24){               // 24시간 일때
        hours = 0;
      }
    }
  }
}

LCD 에 시간을 표시하고 1초마다 LED 를 On/Off 하는 프로그램이다
clock.ino

알람시계

이번에는 알람을 맞추고 시간이 되면 피에조 부저를 울리는 시계를 만들어보겠다.

alarm_clock.ino

  if(alarm_set == 0x01)              // 알람이 설정되면 LCD 의 윗줄에 "AL-00:00" 으로 설정된 시간이 표시된다
  {                // 알람 설정이 안된 경우는 "AL-Clock" 이 출력된다. 아랫줄에는 현재 시간이 출력
    digitalWrite(led, HIGH);
    lcd.setCursor(0,0);
    lcd.print("AL-");
    displayDigits(alarm_hour);
    displayDigits(alarm_min);
  }
  else
  {
    digitalWrite(led, LOW);
    lcd.setCursor(0,0);
    lcd.print("AL-CLOCK");
  }
 
  if((alarm_set == 1) && (alarm_hour == hours) && (alarm_min == minutes) && (seconds == 0))    
  {                         // 알람이 설정되고 알람시간과 현재시간이 시, 분, 초 까지 일치하면 알람이 울린다
    alarm_ring = 1;
  }
...
void alarm_proc()        // 알람이 설정 사용자 함수. 시간 설정과 같은 방법이며 설정 값이 변경되는 변수가 다르다
{
  char lcd_text[16];
 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("AlarmSet");
  delay(100);
 
  while(1) // 중괄호 안의 블록을 무한 반복한다. break 명령을 만나면 while 블록을 빠져나간다. 저장이나 취소 버튼을 누르면 break 명령어를 만나 블록을 빠져 나갈 수 있다
  {
    lcd.setCursor(0,1);
    displayDigits(alarm_hour);
    displayDigits(alarm_min);
    displayDigits(alarm_sec);
    delay(100);
 
    if(check_key() == 3)
    {
      delay(100);
      alarm_hour++;
      if(alarm_hour > 23) alarm_hour = 0;
    }
 
    if(check_key() == 0)
    {
      delay(100);
      alarm_min++;
      if(alarm_min > 59) alarm_min = 0;
    }
 
    if(check_key() == 1)
    {
      delay(100);
      alarm_set = 1;
      break;
    }
 
    if(check_key() == 2)
    {
      delay(100);
      alarm_set = 0;
      break;
    }
  };
 
  lcd.clear();
} 

“시”, “분” 버튼을 이용하여 시간을 맞출 수 있다. 알람을 설정할 경우에는 먼저 “설정/저장” 버튼을 누르면 LCD 에 “AlarmSet” 이 출력되고, “시”, “분” 버튼으로 알람 설정 시간을 맞춘 후, “설정/저장” 버튼을 누르면 알람이 설정된다. 알람이 설정되면 LED 가 켜진다.
알람이 울릴 경우는 부저소리가 나며, “취소/해제” 버튼을 누르면 부저소리가 멈춘다. 알람 설정을 취소나 설정 해제를 할 경우에는 “취소/해제” 버튼을 누르면 된다.
알람이 취소되면, LED 가 꺼진다.

  • computer/embedded/아두이노_그대로_따라하기_-_6.lcd_제어하기.txt
  • Last modified: 4 years ago
  • by likewind