본문 바로가기
아두이노 러닝보드/아두이노 러닝보드 프로그그램설계

아두이노 학습 키트를 이용한 디지털 알람 시계 만들기

by 모빌리티키즈 2024. 12. 18.
728x90
반응형

개요

이 레슨에서는 학생들이 아두이노 학습 키트를 사용하여 디지털 알람 시계를 만드는 방법을 배웁니다. 이 키트에는 DS1307 RTC, 버저, 버튼 스위치 및 LCD 디스플레이가 포함되어 있으며, 학생들은 점퍼 와이어를 사용하여 이 구성 요소를 아두이노에 연결한 후 코드를 작성하고 업로드합니다.

학습 목표

이 레슨을 완료한 후 학생들은 다음을 배웁니다:

  • I2C 통신 프로토콜에 대해 이해하고, 아두이노에서 이를 구현하는 방법.
  • DS1307 RTC와 LCD 디스플레이를 인터페이스하는 방법.
  • 아두이노와 버저를 사용하여 톤을 생성하는 방법.
  • 아두이노 IDE에서 외부 라이브러리를 사용하는 방법.
  • 프로그램에서 조건문과 루프를 사용하는 방법.

사전 요구 사항

  • 아두이노 디지털 출력에 대한 기본 지식 (예: LED 제어 방법).
  • 아두이노 디지털 입력에 대한 기본 지식 (예: 버튼 스위치 인터페이스 방법).

중요한 질문

  • 임베디드 시스템에서 사용되는 다양한 통신 프로토콜은 무엇인가요?
  • 직렬 통신과 병렬 통신의 차이점은 무엇인가요?
  • 아두이노에서 사용되는 가장 일반적인 직렬 프로토콜은 무엇인가요?
  • RTC가 마이크로컨트롤러 시스템에서 사용되는 이유는 무엇인가요?

필요한 재료

  • 아두이노 학습 키트 및 USB 케이블
  • 12개의 수-수 점퍼 와이어
  • 2개의 수-암 점퍼 와이어
  • PC 접속

배경 지식

I2C 직렬 통신

I2C (Inter-Integrated Circuit) 프로토콜은 여러 "슬레이브" 디지털 집적 회로("칩")가 하나 이상의 "마스터" 칩과 통신할 수 있도록 하는 프로토콜입니다. 이 프로토콜은 두 개의 와이어만으로 최대 128개의 장치 (7비트 주소 사용 시) 또는 최대 1024개의 장치 (10비트 주소 사용 시)와 통신할 수 있어 매우 인기가 있습니다.

 

프로토콜 세부 사항

  • 주소 프레임: 마스터가 슬레이브 장치를 지정하고 읽기 또는 쓰기 작업 여부를 나타냅니다.
  • 데이터 프레임: 실제 전송되는 데이터를 포함합니다.
  • 시작/종료 조건: 통신 시퀀스의 시작과 종료를 정의합니다.

실습 단계

  1. 구성 요소 연결
    • DS1307 RTC, 버저, 버튼 스위치 및 LCD 디스플레이를 아두이노에 점퍼 와이어로 연결합니다.
  2. 코딩
    • RTC를 관리하고, LCD에 시간을 표시하며, 버저를 사용하여 알람 소리를 생성하는 아두이노 코드를 작성합니다.

코드 예시

 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>

RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  Wire.begin();
  rtc.begin();
  lcd.begin();
  lcd.backlight();

  if (!rtc.isrunning()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop() {
  DateTime now = rtc.now();
  lcd.setCursor(0, 0);
  lcd.print(now.hour());
  lcd.print(':');
  lcd.print(now.minute());
  lcd.print(':');
  lcd.print(now.second());

  // 알람 기능을 위한 로직 추가

데이터 프레임 (Data Frames)

주소 프레임이 전송된 후, 데이터 전송이 시작됩니다. 마스터는 일정한 간격으로 클럭 펄스를 생성하고, R/W 비트에 따라 마스터 또는 슬레이브가 데이터를 SDA에 전송합니다. 데이터 프레임의 수는 임의이며, 대부분의 슬레이브 장치는 내부 레지스터를 자동으로 증가시켜 연속적인 읽기 또는 쓰기를 수행할 수 있습니다.

정지 조건 (Stop Condition)

모든 데이터 프레임이 전송된 후, 마스터는 정지 조건을 생성합니다. 정지 조건은 SCL이 높은 상태에서 SDA가 0->1(낮음에서 높음)으로 전환될 때 정의됩니다. 정상적인 데이터 쓰기 작업 중에는 SCL이 높을 때 SDA의 값이 변경되지 않아야 합니다.

DS1307 RTC

실시간 시계 (RTC)는 현재 시간을 기록하는 시스템으로, 전원이 끊겨도 정확한 시간을 유지할 수 있습니다. DS1307 모듈은 가장 저렴하고 일반적인 RTC 모듈 중 하나로, 초, 분, 시간, 일, 월, 연도를 정확하게 기록할 수 있습니다. DS1307은 I2C 인터페이스를 사용하는 8핀 장치로, 저전력 시계/캘린더 기능을 제공하며 56바이트의 배터리 백업 SRAM을 포함하고 있습니다.

주요 특징

  • 배터리 백업: 전원이 끊겨도 시계/캘린더를 계속 작동할 수 있습니다.
  • 정확한 시간 기록: 초, 분, 시간, 일, 월, 연도를 기록합니다.
  • 자동 조정: 각 월의 마지막 날짜를 자동으로 조정합니다.

핀 아웃 및 연결

DS1307 RTC 모듈은 총 8개의 핀으로 외부와 연결됩니다. 간단한 회로에서는 두 입력 X1과 X2가 32.768 kHz 크리스탈 오실레이터에 연결되며, VBAT는 3V 배터리의 양극 단자에 연결됩니다. Vcc는 I2C 인터페이스에 전원을 공급하며, 마이크로컨트롤러를 사용하여 5V를 제공합니다. 데이터 통신은 SCL과 SDA 핀을 사용하여 아두이노와 수행됩니다. 이 두 핀은 4.7KΩ 저항으로 풀업해야 합니다.

DS1307 핀연결
SCL 아두이노 A5 (5V)
SDA 아두이노 A4 (GND)
VCC 아두이노 5V
GND 아두이노 GND

LCD 디스플레이

LCD(액정 디스플레이)는 정보 표시를 위한 저렴한 전자 프로젝트에서 널리 사용됩니다. 키트에 포함된 LCD는 16개의 핀이 있으며, 첫 번째 핀은 그라운드(GND) 핀입니다. 두 번째 핀은 VCC로 아두이노 보드의 5V 핀에 연결됩니다. Vo 핀에는 디스플레이의 대비를 조절할 수 있는 포텐셔미터를 연결할 수 있습니다.

  • RS 핀: 명령 또는 데이터를 LCD에 전송할지 선택합니다. 낮은 상태(0V)에서는 명령을, 높은 상태(5V)에서는 데이터를 전송합니다.
  • E 핀: 레지스터에 쓰기를 활성화합니다.
  • D0-D7 핀: 데이터 핀입니다.
  • A와 K 핀: LED 백라이트용입니다.

LCD는 4비트 모드와 8비트 모드 모두 작동할 수 있습니다. 4비트 모드에서는 D4-D7만 아두이노에 연결되며, D0-D3는 연결하지 않아도 됩니다. 키트에서는 GND, VCC, Vo, A, K가 이미 적절한 소스에 연결되어 있습니다.

 

 절차

  1. 버저 연결: B_CONN(버저) 핀을 남성-여성 점퍼 와이어를 사용하여 아두이노의 D11 핀에 연결합니다.
  2. LCD 핀 연결: 남성-남성 점퍼 와이어를 사용하여 표 2에 따라 LCD 핀을 아두이노 핀에 연결합니다.
  3. 버튼 스위치 연결: S1, S2, S3, S4 핀을 아두이노 헤더의 A0, A1, A2, A3 핀에 각각 연결합니다.
  4. I2C 연결: SCL 핀을 아두이노 헤더의 A5 핀에, SDA 핀을 아두이노 헤더의 A4 핀에 연결합니다.
  5. 코드 작성: 아두이노 IDE를 열고 제공된 코드를 새로운 스케치에 복사한 후 저장합니다.
  6. 업로드: USB 케이블을 사용하여 키트를 PC에 연결하고 제공된 스케치를 키트에 업로드합니다.
  7. 시간 및 날짜 표시: 디스플레이에 시간과 날짜가 표시됩니다.
  8. 시간 및 날짜 조정: 버튼을 사용하여 시계의 날짜와 시간을 조정합니다.

 라이브러리 설치

DS1307 RTC 모듈을 위한 서드파티 라이브러리를 사용합니다. 이를 위해 라이브러리를 다운로드하여 아두이노 환경에 추가해야 합니다. 다음 링크에서 라이브러리를 다운로드합니다: RTClib GitHub. ZIP 파일을 다운로드한 후, 파일 이름에 공백이나 하이픈이 포함되어 있다면 이름을 변경합니다. 아두이노 IDE에서 Sketch 메뉴로 이동하여 "Include Library"를 선택한 다음 "Add .ZIP Library"를 선택합니다. 다운로드한 .zip 파일을 찾아 추가합니다. 이제 라이브러리를 사용할 준비가 되었습니다.

link: https://github.com/adafruit/RTClib

 

GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC Arduino library

A fork of Jeelab's fantastic RTC Arduino library. Contribute to adafruit/RTClib development by creating an account on GitHub.

github.com

 

///including the library 
#include <LiquidCrystal.h> //for lcd 
#include <Wire.h>          //for i2c protocol 
#include<EEPROM.h>         //for reading/writing in eeprom 
#include <RTClib.h>        //for accessing rtc 
 
//two object 
LiquidCrystal lcd(9, 8, 4, 5, 6, 7); 
RTC_DS1307 RTC; 
 
///declaration of global variables 
int temp,inc,hours1,minut,add=11,temp1=3,mode=0; 
int tSeconds=0, tMinutes=0, hours=0;                                                           
int centiseconds=0, sSeconds=0, sMinutes=0; 
int next=A0;    
int INC=A1; 
int set_mad=A2; 
int shw_dat=A3; 
int buzzer=11; 
int HOUR,MINUT,SECOND=0; 
 
 
void setup(){ 
  Wire.begin(); //initilize i2c module 
  RTC.begin();  //initilize rtc module 
  lcd.begin(16,2); //initilize lcd 
  //buttons pin as input 
  pinMode(INC, INPUT); 
  pinMode(next, INPUT); 
  pinMode(set_mad, INPUT); 
  pinMode(shw_dat, INPUT); 
  //buzzer pin as output 
  pinMode(buzzer, OUTPUT); 
  //initilize buttons state high 
  digitalWrite(next, HIGH); 
  digitalWrite(set_mad, HIGH); 
  digitalWrite(INC, HIGH); 
  digitalWrite(shw_dat, HIGH); 
 
   lcd.setCursor(0,0); 
   lcd.print("Real Time Clock"); 
   lcd.setCursor(0,1); 
   lcd.print("Instructable class");  
   delay(3000); 
 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
   //if rtc works then set date time ot the rtc as your pc time 
   if(!RTC.isrunning()) 
      { 
          RTC.adjust(DateTime(__DATE__,__TIME__)); 
      } 
} 
 
void loop() 
{ 
   
   int temp=0,val=1,temp4; 
   //read current date time 
   DateTime now = RTC.now(); 
 
   
   if(digitalRead(shw_dat) == 0) 
       {mode++;} 
 
   if(digitalRead(shw_dat) == 0 && mode==1)     //set Alarm time 
   { 
     lcd.setCursor(0,0); 
     lcd.print("    SET ALARM ??    "); 
     delay(2000); 
    
     while(1) 
       {  if(digitalRead(set_mad) == 0) 
         { 
            time(); 
            delay(1000); 
            lcd.clear(); 
            lcd.setCursor(0,0); 
            lcd.print(" ALARM TIME SET "); 
            lcd.setCursor(9,1); 
            lcd.print(HOUR=hours1,DEC); 
            lcd.print(":"); 
            lcd.print(MINUT=minut,DEC); 
            lcd.print(":"); 
            lcd.print(SECOND=now.second(),DEC); 
            CheckTime(); 
            delay(1000); 
          } 
        if(digitalRead(shw_dat) == 0) 
        break; 
      } 
   } 
 
  if(digitalRead(shw_dat) == 0 && mode==3)      //set CLOCK TIME 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
   { 
     lcd.clear(); 
     lcd.setCursor(0,0); 
     lcd.print("    SET TIMER     "); 
     while(1) 
       { 
         if(digitalRead(set_mad) == 0) 
         { 
            timerFunction(); 
         } 
        if(digitalRead(INC) == 0) 
            break; 
       } 
   } 
    
  if(digitalRead(shw_dat) == 0 && mode==4)      //set Stopwatch 
   { 
     lcd.clear(); 
     lcd.setCursor(0,0); 
     lcd.print("    STOPWATCH     "); 
 
     while(1) 
       { 
         if(digitalRead(set_mad) == 0) 
           { 
             stopwatchFunction(); 
           } 
         if(digitalRead(INC) == 0) 
            break; 
       } 
 
   } 
 
    
  if(mode>=5) 
      {mode=0;} 
       
  lcd.clear();  //refress lcd 
  lcd.setCursor(0,0); //write in first line hh:mm:ss 
  lcd.print(HOUR=now.hour(),DEC); 
  lcd.print(":"); 
  lcd.print(MINUT=now.minute(),DEC); 
  lcd.print(":"); 
  lcd.print(SECOND=now.second(),DEC); 
   
  lcd.setCursor(0,1);  //write in second line dd/mm/yyyy 
  lcd.print(now.day(),DEC); 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
  lcd.print("/"); 
  lcd.print(now.month(),DEC); 
  lcd.print("/"); 
  lcd.print(now.year(),DEC); 
   
  delay(1000); //wait some time 
} 
 
/*Function to set alarm time and feed time into Internal 
eeprom*/ 
void time()                             
{ 
  int temp=1,minuts=0,hours=0,seconds=0; 
    while(temp==1) 
     { 
     if(digitalRead(INC)==0) 
       { 
        HOUR++; 
        if(HOUR==24) 
          { 
             HOUR=0; 
          } 
        while(digitalRead(INC)==0); 
        } 
     lcd.clear(); 
     lcd.setCursor(0,0); 
     lcd.print("Set Alarm Time "); 
   
     lcd.setCursor(0,1); 
     lcd.print(HOUR); 
     lcd.print(":"); 
     lcd.print(MINUT); 
     lcd.print(":"); 
     lcd.print(SECOND); 
     delay(100); 
     if(digitalRead(next)==0) 
       { 
        hours1=HOUR; 
        EEPROM.write(add++,hours1); 
        temp=2; 
        while(digitalRead(next)==0); 
       } 
    } 
    while(temp==2) 
     { 
       if(digitalRead(INC)==0) 
         { 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
           MINUT++; 
           if(MINUT==60) 
             {MINUT=0;} 
           while(digitalRead(INC)==0); 
         }  
     
      lcd.setCursor(0,1); 
      lcd.print(HOUR); 
      lcd.print(":"); 
      lcd.print(MINUT); 
      lcd.print(":"); 
      lcd.print(SECOND); 
      delay(100); 
      if(digitalRead(next)==0) 
        { 
         minut=MINUT; 
         EEPROM.write(add++, minut); 
         temp=0; 
         while(digitalRead(next)==0); 
        } 
    } 
    delay(1000); 
} 
/* Function to chack medication time */ 
void CheckTime() 
{ 
  int tem[17]; 
  while(1) 
  { 
    DateTime now = RTC.now(); 
    lcd.setCursor(0,1); 
    lcd.print(HOUR=now.hour(),DEC); 
    lcd.print(":"); 
    lcd.print(MINUT=now.minute(),DEC); 
    lcd.print(":"); 
    lcd.print(SECOND=now.second(),DEC); 
    for(int i=11;i<17;i++) 
      { 
        tem[i]=EEPROM.read(i); 
      } 
    if(HOUR == tem[11] && MINUT == tem[12]) 
     { 
       for(int j=0;j<5;j++) 
        { 
          digitalWrite(buzzer, HIGH); 
          delay(500); 
          digitalWrite(buzzer, LOW); 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
          delay(500); 
        } 
    hours1=0; 
    minut=0; 
    add=11; 
    return; 
   } 
  } 
} 
 
void timerFunction()  //the timer function was made with the 
//help of this post: http://pastebin.com/f57045830 
{ 
  int set=0; 
    lcd.setCursor(4,1); 
    lcd.print("00:00:00"); 
    while(1) 
           { 
 
                   while(digitalRead(shw_dat)==1) 
                    { 
                      set=1; 
                   if(digitalRead(set_mad)==0)  //if 
//"Start/Stop" is pressed, the timer counts down 
                      { 
                        tSeconds++; 
                        lcdOutput(); 
                        delay(300); 
                        if(tSeconds==60) 
                        { 
                        tMinutes++; 
                        tSeconds=0; 
                        } 
                       } 
                 if(digitalRead(INC)==0)  //if "Start/Stop" is 
//pressed, the timer counts down 
                      { 
                        tMinutes++; 
                        lcdOutput(); 
                        delay(300); 
                        if(tMinutes==60) 
                        { 
                        hours++; 
                        tMinutes=0; 
                        } 
                      } 
                  if(digitalRead(next)==0 )  //if "Start/Stop" 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
//is pressed, the timer counts down 
                  { 
                        hours++; 
                        lcdOutput(); 
                        delay(300); 
                        if(hours==24) 
                        { 
                        hours=0; 
                        } 
                  }      } 
    if(digitalRead(shw_dat)==0 && set==1) 
      { 
       lcd.clear(); 
       lcd.setCursor(0,0); 
       lcd.print(" TIMER SET FOR  "); 
       lcd.setCursor(4,1); 
    
       lcd.print("00:00:00"); 
            while(digitalRead(INC)==1) 
            { 
            static unsigned long lastTick = 0; 
              if (tSeconds > 0) 
                { 
                if (millis() - lastTick >= 1000) 
                { 
                lastTick = millis(); 
                tSeconds--; 
                lcdOutput(); 
                } 
                } 
            if (tMinutes > 0) 
               { 
              if (tSeconds <= 0) 
              { 
                tMinutes--; 
                tSeconds = 60; 
              } 
              } 
            if (hours > 0) 
              { 
              if (tMinutes <= 0) 
              { 
                hours--; 
                  tMinutes = 60; 
                } 
              }  
 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
              if(hours == 00 && tMinutes == 00 && tSeconds == 
00)  //when timer ends, the alarm goes on 
                { 
              while(digitalRead(shw_dat) == 1)  //the alarm will 
//only go off until "Restart" is pressed 
              { 
                set=2; 
                lcd.setCursor(4, 1); 
                lcd.print("00:00:00"); 
                for(int i=0;i<5;i++) 
                { 
                digitalWrite(buzzer, HIGH); 
                delay(500); 
                digitalWrite(buzzer, LOW); 
                delay(500); 
                } 
              } 
            } 
          } 
      } 
    if(digitalRead(shw_dat) == 0 && set==2) 
               { 
                set=0; 
                mode=0; 
                break; 
                } 
    } 
} 
 
void lcdOutput()  //this is just used to display the timer on 
//LCD 
{ 
  lcd.setCursor(4, 1); 
  printDigits(hours); 
  lcd.setCursor(7, 1); 
  printDigits(tMinutes); 
  lcd.setCursor(10, 1); 
  printDigits(tSeconds); 
  delay(100); 
} 
 
void printDigits(int digits)  //this void function is really 
//useful; it adds a "0" to the beginning of the number, so that 
//5 minutes is displayed as "00:05:00", rather than "00:5 :00" 
{ 
  if(digits < 10) 
  { 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
    lcd.print("0"); 
    lcd.print(digits); 
  } 
  else 
  { 
    lcd.print(digits); 
  } 
} 
void stopwatchFunction() 
{ 
int count=1,sMin,sSec,sCen; 
 
    lcd.setCursor(4,1); 
    lcd.print("00:00:00"); 
 
  while(1) 
  { 
  if(digitalRead(shw_dat) == LOW ) 
    { 
      count=0; 
      loop(); 
 
    }    
  if(digitalRead(next) == LOW)  //if the "Start/Stop" button is 
//pressed, the time begins running 
  { 
 
  while(1) 
    { 
      int count=1; 
      delay(6); 
  lcd.setCursor(4, 1); 
  printDigits(sMinutes); 
  lcd.setCursor(7, 1); 
  printDigits(sSeconds); 
  lcd.setCursor(10, 1); 
  printDigits(centiseconds); 
    centiseconds++; 
    sCen=centiseconds; 
    if(centiseconds==100) 
    { 
      sSeconds++; 
      sSec=sSeconds; 
      centiseconds=0; 
      if(sSeconds==60) 
      { 
        sMinutes++; 
Subject: Electronics, Programming                                                                                     Grade Levels: 9th-12th  
Prepared By: Md. Khairul Alam 
        sMin=sMinutes; 
        sSeconds=0;        
        } 
    } 
    if(digitalRead(set_mad) == 0) 
      { 
        centiseconds = 0; 
        sSeconds = 0; 
        sMinutes = 0; 
        break; 
      } 
if(digitalRead(INC) == LOW && count ==1) 
    { 
      while(1) 
      { 
        lcd.setCursor(4, 1); 
        printDigits(sMinutes); 
        lcd.setCursor(7, 1); 
        printDigits(sSeconds); 
        lcd.setCursor(10, 1); 
        printDigits(centiseconds);  
 
        if(digitalRead(set_mad) == 0) 
          { 
            count=2; 
            centiseconds = 0; 
            sSeconds = 0; 
            sMinutes = 0; 
            break; 
          } 
        } 
      } 
    } 
   } 
 } 
}

추가 학습

  • 다양한 통신 프로토콜 (SPI, UART) 탐구.
  • 임베디드 시스템에서 RTC의 중요성 논의.

결론

이 레슨을 통해 학생들은 아두이노를 사용하여 디지털 알람 시계를 만드는 방법을 이해하게 되며, I2C 통신, 다양한 구성 요소 인터페이스, 조건문 및 루프 작성에 대한 지식을 습득하게 됩니다.

추가 질문이나 도움이 필요하시면 언제든지 말씀해 주세요! 📚🔧🚀

728x90
반응형