프로젝트

나도 메이커! 메이커스 여러분들의 작품/프로젝트를 공유하는 공간입니다.

LCD와 피에조부저, 스위치를 사용하여 알람시계만들기

2014-08-18 10:15:44

개요

개요

각 센서들과 LCD를 이용하여 간단한 LCD알람시계를 만들어 보자.
100줄 내외의 소스코드와 몇개의 센서와 LCD를 통해 구현이 가능하다.
시간은 swRTC라이브러리를 이용하여 간단하게 구현이 가능하고 나머지 LCD나 스위치, 피에조부저의 사용법은 튜토리얼을 통해 간단히 익히고 사용 할 수 있다.

LCD에서는 현재 시간과 알람시간을 지정했을 경우 지정된 알람시간이 뜨게되고 현재시간이 알람시간과 동일할 경우에 피에조부저에서 소리가 나며 알람이 울리게 된다.
스위치를 1초간 누르거나 현재시간에서 1분이 경과할 경우 피에조부저의 알람은 꺼지게 된다.

원리는 일반 디지털 알람시계와 비슷하기 때문에 만들면서 디지털시계에 대한 지식도 공부할 수 있을 것이라 생각한다.


동영상

필요한 사전지식

LCD사용
피에조 부저
스위치
swRTC 라이브러리




부품 목록

NO 부품명 수량 상세정보
1 아두이노 보드 1  
2 브레드 보드 1  
3 LCD 1  
4 가변 저항기 1  
5 피에조 부저 1  
6 스위치 1  
7 케이블 약 20개  


부품명 아두이노 보드 브레드 보드 LCD 가변 저항기 피에조 부저
부품사진
부품명 스위치 케이블      
부품사진      








하드웨어 making

브레드 보드



전자회로도

소프트웨어 coding

/*
 LCD 연결해서 글자 출력하기
 
 이 스케치는 KocoaFab에서 만들었습니다.
 이 스케치는 누구든 무료로 사용할 수 있습니다.
*/

#include <LiquidCrystal.h>
#include <core_build_options.h>
#include <swRTC.h>

LiquidCrystal lcd(12,11,5,4,3,2);        //RS 핀, E핀, 데이터 핀 4개
String lcdString = "";                   //객체 선언 : 출력 할 글자 저장

swRTC rtc; 

int piezo = 6;
int switchPin = 9;
int temp;

//AM PM을 구분해 주는 함수
void Set_AMPM(int hour) {
  if(hour >=12) 
    lcd.print("PM");
  else 
    lcd.print("AM");

  lcd.print(hour%12, DEC);     //시간 출력
}

//10보다 작은수를 출력할때 앞에 0을 출력하게 하는 함수
void Set_lowThanTen(int time) {
  if(time < 10) {
    lcd.print("0");
    lcd.print(time%10);
  }
  else
    lcd.print(time);
}

//유효한 알람시간인지 체크하는 함수
int checkTheAlarmClock(int time) {
  if(time/100 < 24 && time %100 < 60) {
    Serial.println("Success");
    return time;
  }
  else {
    Serial.println("Failed");
    return 0;
  }  
}

//알람이 울릴시간인지 체크하는 함수
void checkTheAlarmTime(int alarmHour, int alarmMinute) {
  if(alarmHour == rtc.getHours() && alarmMinute == rtc.getMinutes()) {
        analogWrite(piezo, 128);
    }
}

void setup() {                   
  lcd.begin(16,2);         //LCD 크기 지정, 2줄 16칸
  lcd.clear();             //화면 초기화
  
  rtc.stopRTC();           //정지
  rtc.setTime(14,05,0);    //시간, 분, 초 초기화
  rtc.setDate(24, 8, 2014);  //일, 월, 년 초기화 
  rtc.startRTC();          //시작
  
  pinMode(piezo, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP); 
  Serial.begin(9600);      //시리얼 포트 초기화 
  Serial.begin(9600);                    //시리얼 통신 초기화
}

void loop() {
  int day;
  lcd.setCursor(0,0);                    //커서를 0,0에 지정 
  
  //1초 단위로 갱신하며 현재시간을 LCD에 출력
  Set_AMPM(rtc.getHours()); 
  lcd.print(":");
  Set_lowThanTen(rtc.getMinutes());
  lcd.print(":");
  Set_lowThanTen(rtc.getSeconds());
  //날짜를 LCD에 출력
  lcd.print("[");
  Set_lowThanTen(rtc.getMonth());
  lcd.print("/");
  Set_lowThanTen(rtc.getDay());
  lcd.print("]");
  //세팅된 알람시간을 LCD에 출력
  lcd.setCursor(0,1);
  lcd.print("Alarm ");
  Set_AMPM(temp/100);
  lcd.print(":");
  Set_lowThanTen(temp%100); 
  
  //1초마다 LCD갱신
  lcdString = "";                      //문자열 초기화
  lcd.print("               ");        //전 글씨 삭제
  delay(1000);
  
  //알람이 울릴 시간인지 체크
  checkTheAlarmTime(temp/100, temp%100);
   
  //스위치버튼이 눌렸을 경우 피에조센서의 소리를 0으로 하고 알람시간을 초기화 한다 
  if(!digitalRead(switchPin)) {
    temp = 0;
    day = 0;
    analogWrite(piezo, 0);
    Serial.println("Alarm clock initialize");
    Serial.println("AM0:00");
  }
  //시리얼 통신을 통해 알람시간을 입력받고 시리얼 모니터에 출력 
  char theDay[4];
  int i = 0;
  if(Serial.available()) {
    while(Serial.available()) {
      theDay[i] = Serial.read();
      i++;
  }
    day = atoi(theDay);
    if(day/100 >= 12) {
      Serial.print("PM");
      Serial.print((day/100)-12);
    }
    else {
      Serial.print("AM");
      Serial.print(day/100);
    }
    Serial.print(":");
    if(day%100 < 10)
      Serial.print("0");
    Serial.println(day%100);
    temp = checkTheAlarmClock(day);
  }
}
구조를 보면 크게
1. setup함수내에서 날짜, 시간을 초기화하는 부분
2. 초기화된 날짜, 시간을 가지고 LCD에 날짜와 시간을 뿌려주는 부분
3. 알람시간의 유효성을 검사하고 알람이 울릴시간인지 체크하는 부분
4. 알람시간을 시리얼통신을 통해 사용자에게 입력받고 지정해주는 부분

이렇게 4부분으로 볼 수 있고  소스 내에 함수가 4개 존재한다.

첫 번째 함수는 24시간 함수를 AM PM으로 변환하여 12시간으로 변환하는 함수이고 (Set_AMPM())
두 번째 함수는 시간이 10보다 작을 경우 앞자리에 0을 출력하는함수이고 (Set_lowThanTen())
세 번째 함수는 지정된 알람시간이 시간규칙(시는 24시간, 분은 60분)을 위배하지 않았는지 체크하는 함수이고 (checkTheAlarmClock())
네 번째 함수는 알람이 울릴시간인지 체크하는 함수이다.(CheckTheAlarmTime())

세 번째, 네 번째 알람관련 함수들은 알람시계를 만들기 위하여 필요한 함수이고 첫 번째, 두 번째 함수는 보기 좋은 LCD시계를 만들기 위해 필요한 함수이다. 대부분이 if문이나 라이브러리의 멤버함수들로 꾸며져있기 때문에 어느정도 프로그래밍능력이 되는 사용자는 쉽게 만들 수 있다.
LCD또한 LCD.print()를 통해 한글을 제외하고 쉽게 문자를 LCD상으로 출력이 가능하기 때문에 쉽게 따라할 수 있을 것이다.

1. Setup함수 영역

시간을 구현하는 방법으로는 swRTC라이브러리를 사용하였고 사용자가 직접 초기시간을 지정해 줄 수 있다. 
아래 부분이 시간과 날짜를 지정해주는 rtc라이브러리의 멤버함수이다. setTime()함수와 setDate()함수를 통해 현재 날짜와 시간을 지정해 준다.
  rtc.stopRTC();           //정지
  rtc.setTime(14,05,0);    //시간, 분, 초 초기화
  rtc.setDate(24, 8, 2014);  //일, 월, 년 초기화 
  rtc.startRTC();          //시작


2. 시간출력 영역

아래 부분은 지정된 날짜와 시간으로 부터 계속적으로 시간과 날짜를 받아와서 LCD에 출력해주는 부분이다.
getHours(), getMinutes(), getSeconds(), getMonth(), getDay()함수가 모두 시간과 날짜를 불러오는 함수이다.
여담이지만 보통 라이브러리에서 get함수와 set함수가 세트로 대개 존재하는데 get함수는 특정 값을 불러오는 함수로 많이 쓰이고, set함수는 get함수로 불러올 값들을 지정해주는 함수로 많이 쓰인다.
예를 들어 프로그래밍으로 사람을 만들기 위해 사람이라는 클래스를 생성하였는데 생성한 객체의 사람의 이름을 지정하고 싶을때는 setName(ashley)이런식으로 set함수를 써서 사람 이름을 지정할 수 있다. 그리고 ashley라고 이름을 지은 객체의 이름 ashley를 출력하고 싶을때는 getName()을 쓰면 대개 ashley라는 객체의 이름을 가져올 수 있다. 대부분의 프로그래밍 방식에서 set함수가 존재하면 그와 비슷한 get함수가 존재하니 참고해 두면 좋다.
특정값을 불러오고 싶지만 불러올 방법이 없을때는 대부분 get함수를 사용해 보면 답이 나온다.
  Set_AMPM(rtc.getHours()); 
  lcd.print(":");
  Set_lowThanTen(rtc.getMinutes());
  lcd.print(":");
  Set_lowThanTen(rtc.getSeconds());
  //날짜를 LCD에 출력
  lcd.print("[");
  Set_lowThanTen(rtc.getMonth());
  lcd.print("/");
  Set_lowThanTen(rtc.getDay());
  lcd.print("]");
  //세팅된 알람시간을 LCD에 출력
  lcd.setCursor(0,1);
  lcd.print("Alarm ");
  Set_AMPM(temp/100);
  lcd.print(":");
  Set_lowThanTen(temp%100); 


위의 코드를 읽다보면 get함수로 불러온 현재시간들을 Set_lowThanTen함수에 매개변수 값으로 넣어줬는데, Set_lowThanTen함수는 불러온 값들이 10보다 작을 경우에 앞에 0을 붙여주는 함수이다. LCD내에서 시간이 좀 더 보기 좋게 하도록 쓰이는 함수로 보면 된다.
예를 들면 오전 6시 1분을 표현하고 싶을때 AM6:1로 출력될 모습을 AM06:01로 앞에 0을 붙여서 출력하게 된다.
원리는 간단하게 10보다 작을 경우 0을 먼저 출력하고 그 다음에 출력할 시간을 표현하는 방법을 통해 구현한다.  
void Set_lowThanTen(int time) {
  if(time < 10) {
    lcd.print("0");
    lcd.print(time%10);
  }
  else
    lcd.print(time);
}


Set_AMPM함수는 오전, 오후를 표현해주는 함수로 시간이 12시간 이상일 경우에는 PM을 출력하고 12시간 전에는 AM을 출력한다.
출력한 다음에는 24시간 표현을 12시간으로 나타내기 위해 12를 빼준다.
void Set_AMPM(int hour) {
  if(hour >=12) 
    lcd.print("PM");
  else 
    lcd.print("AM");
lcd.print(hour-12, DEC); //시간 출력 }

3. 알람시간 유효성 검사 및 시간 체크 영역


checkTheAlarmClock은 지정한 알람시간이 유효한 시간인지를 검사하게 된다. 시 단위는 24보다 작고 분 단위는 60보다 작아야 success를 출력하고 두 조건 중 하나라도 불만족 할 경우에는 Failed를 출력한다.
int checkTheAlarmClock(int time) {
  if(time/100 < 24 && time %100 < 60) {
    Serial.println("Success");
    return time;
  }
  else {
    Serial.println("Failed");
    return 0;
  }  
}


CheckTheAlarmTime은 맞춰놓은 알람시간이 현재시간과 맞는지 비교하여 시와 분이 일치 할 경우 피에조 센서를 통해 알람이 울리게 한다.
void checkTheAlarmTime(int alarmHour, int alarmMinute) {
  if(alarmHour == rtc.getHours() && alarmMinute == rtc.getMinutes()) {
        analogWrite(piezo, 255);
        Serial.println("buzzzzzzzzzzzzzzzzzzz");
    }
}

4. 시리얼 통신을 통해 알람시간을 입력받는 영역


아래는 시리얼 통신으로 알람시간을 입력받는 부분으로 Serial.available()을 통해 데이터가 들어왔을 경우에만 실행된다. 
while문을 통해 입력된 알람시간을 theday라는 버퍼에 읽어 저장하고 시리얼통신으로 들어온 char형 변수를 숫자로 변환하기 위해 atoi()함수를 사용하여 알람시간을 숫자로 변환한다.
변환한 알람시간은  AM PM 형식으로 변환되고 알람시간은 temp라는 변수에 저장되어 checkTheAlarmTime()함수의 매개변수로 쓰인다.

알람시간을 입력할때에는 24시간방법으로 시분을 그대로 입력하게 된다. 
예를들어 2345를 입력하게 되면 23시 45분을 입력한 것과 같으며 0630을 입력하게 되면 6시 30분을 입력한 것과 같게 된다.
입력한 3~4자리 숫자는 /100을 하면 시부분만 따로 떼어 낼 수 있으면 %100으로 나머지를 구하면 분부분만 따로 떼어 낼 수 있다.
예를 들어 1530을 입력받으면 15시 30분을 나타내고 1530/100을 하면 15를 구해 시간을 구할 수 있다.
그 다음 1530%100을 하면 나머지 30을 구할 수 있으면 30은 분이 된다.
이 방법으로 입력된 숫자를 시간과 분으로 구분하여 사용하게 된다.
if(Serial.available()) {
    while(Serial.available()) {
      theDay[i] = Serial.read();
      i++;
    }
    day = atoi(theDay);
    if(day/100 >= 12) {
      Serial.print("PM");
      Serial.print((day/100)-12);
    }
    else {
      Serial.print("AM");
      Serial.print(day/100);
    }
    Serial.print(":");
    if(day%100 < 10)
      Serial.print("0");
    Serial.println(day%100);
    temp = checkTheAlarmClock(day);
  }

기술문서

  • 부품목록
  • 회로도
  • 브레드보드 레이아웃
  • 스케치

수박쨈

LCD, 피에조부저, 스위치, 가변저항기, 알람시계, 초중급