지니어스키트 학습가이드

아두이노 시작의 첫단계, 기본은 충실하게, 그러나 가볍게!!

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

2015-01-21 10:45:53

개요

각 센서들과 LCD를 이용하여 간단한 LCD알람시계를 만들어 보겠습니다.

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




필요한 사전지식

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

부품 목록

NO 부품명 수량
1 오렌지보드 1
2 LCD 1
3 가변 저항 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 = 8;
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);
  }

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!

하야 2015-06-01 19:52:57

이 예제는 동작하지 않습니다.
프로젝트 진행하시는 분들 비슷한 예제인 아래를 참고해서 만드세요
http://kocoafab.cc/make/144

강상호 2016-09-12 14:17:34

감사합니다

아두초보 2017-04-14 18:22:21

예제의 틀린 곳을 나름대로 수정하였습니다. 참고하세요.
/* 알람시계만들기 */

#include
#include
#include

LiquidCrystal lcd(2,3,10,11,12,13);
String lcdstring = ""; //객체선언 : 출력할 글자 저장

swRTC rtc;

int piezo = 8;
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,DEC);
}
// 10보다 작은수는 앞에 0을 출력
void Set_lowThanTen(int time){
if(time<10){
lcd.print("0");
lcd.print(time);
}
else
lcd.print(time);
}
// 유효한 알람시간인지 체크
int checkTheAlarmClock(int time){
if(time/100<24 && time0<60){
Serial.println("Sucess");
return time;
}
else{
Serial.println("Failed");
return 0;
}
}
// 알람이 울릴시간인지 체크
void checkTheAlarmTime(int alarmHour,int alarmMinute){
if(alarmHour ==rtc.getHours() && alarmMinute == rtc.getMinutes()){
analogWrite(piezo, 255);
Serial.println("Buzzzzzz~~~~~");
}
}

void setup() {
// put your setup code here, to run once:
lcd.begin(16,2);
lcd.clear();

rtc.stopRTC();
rtc.setTime(11,30,0);
rtc.setDate(14,4,2017);
rtc.startRTC();

pinMode(piezo, OUTPUT);
pinMode(switchPin, INPUT_PULLUP);
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
int day;
lcd.setCursor(0,0);
Set_AMPM(rtc.getHours());
lcd.print(":");
Set_lowThanTen(rtc.getMinutes());
lcd.print(":");
Set_lowThanTen(rtc.getSeconds());
// day lcd print
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(temp0);

//1초마다 lcd갱신
delay(1000);
lcd.clear();

// 알람이 울릴 시간인지 체크
checkTheAlarmTime(temp/100,temp0);

// 스위치를 누르면 피에조소리를 0, 알람시간을 초기화
if(digitalRead(switchPin)==LOW){
temp = 0;
day = 0;
analogWrite(piezo,0);
lcd.clear();
lcd.print("Alarm clock initialize");
Serial.println("Alarm clock initialize");
Serial.println("AM00:00");
delay(1000);
}
// 시리얼 통신을 통해 알람시간을 입력받고 시리얼 모니터에 출력
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(day0<10){
Serial.print("0");
Serial.print(day0);
}
Serial.print(day0);
temp = checkTheAlarmClock(day);
}
}

아두초보 2017-04-14 18:33:37

소스파일을 올리는 과정에서 일부 코드가 다르게 올라갑니다. 원래 예제를 참고하세요!
(day%,time%,day% 등이 day0,time0,day0 등으로 바뀌네요)