RTC MODULE
DS1302 RTC Module
RTC라는 것은 Real Time Clock 으로, DS1302 RTC 모듈은실제 시간을 기록해 두었다가 필요시 읽을 수 있도록 해줍니다. 전원이 차단되어도 계속해서 시간을 기록할 수 있도록 DS1302칩 옆에는 배터리가 있는 것을 알 수 있습니다.
DS1302 Library
DS1302 RTC Module을 사용하기 위해서 필요한 라이브러리를 설치했습니다.
제가 사용한 라이브러리의 출처 주소입니다.
주소 : https://playground.arduino.cc/Main/DS1302RTC/
다운 받은 zip파일을 이용해서 라이브러리를 설치하기 위해선
아두이노 IDE의 툴바에서 [스케치] - [라이브러리 포함하기] - [.ZIP 라이브러리 추가] 순으로 클릭하여, 다운 받은 파일을 선택해주시면 됩니다.
라이브러리 설치 및 예제 사용은 해당 글을 참고했습니다.
해당 글에 정리가 잘 되어 있어, 저는 예제 코드에 주석 위주로 정리하였습니다.
1. RTC Module Time Read
#include <DS1302RTC.h>
#include <TimeLib.h>
// DS1302 RTC 모듈의 핀들을 Arduino UNO 보드의 핀에 연결하기 위해 디지털 핀 번호를 지정합니다.
const int CLK = 2;
const int DAT = 3;
const int RST = 4;
// DS1302 rtc(ce_pin(RST), io_pin(DAT),sck_pin(CLK));
DS1302RTC rtc(RST, DAT, CLK);
void setup() {
// Serial 통신 threh 9600으로 설정
Serial.begin(9600);
Serial.println("DS1302 RTC Module Read Test");
Serial.println("---------------------------");
// RTC 모듈이 정지 상태인지 작동 상태인지 확인합니다.
// haltRTC()함수가 0을 리턴하면 작동 중지 상태이고, 1을 리턴하면 작동 중인 상태입니다.
if (rtc.haltRTC()) { // 만약 1 이면 정지된 상태
Serial.println("The DS1302 is stopped.");
rtc.haltRTC(0); // haltRTC() 함수를 매개변수를 0으로 호출합니다. 즉, 모듈을 실행시킵니다.
Serial.println("The DS1302 is started."); // 모듈이 실행된 후 작동하고 있다는 메세지 출력
delay(100);
} else { // 0 이면 실행 상태
Serial.println("The DS1302 is working.");
}
// RTC 모듈이 아두이노에게 전달하는 기준 시간데이터가 중간 중간 변경이 되지 않도록 쓰기 금지 모드를 제공하고 있습니다.
// RTC 모듈이 쓰기 가능 모드인지 확인 합니다.
// writeEN() 함수가 0을 반환하면 쓰기 금지 상태이고, 1을 반환하면 쓰기 가능 상태로 시간을 사용자가 설정할 수 있는 상태입니다.
if (rtc.writeEN() == 0) {
Serial.println("The DS1302 is write protected.");
} else {
Serial.println("The DS1302 can write.");
rtc.writeEN(false);
Serial.println("Write protected is started.");
}
Serial.println("-------------------------------");
Serial.println("-------------------------------");
delay(5000);
}
void loop() {
time_t t; // Time 라이브러리(TimeLib.h)에 선언된 타입으로, unsigned long 정수를 담는 변수입니다.
tmElements_t tm; // uint8_t(부호없는 8비트 정수) 타입의 초,분,시간,요일(일요일이 1),달, 연도를 갖고있는 구조체입니다.
Serial.print("rtc.get() 함수 실행 결과 : ");
Serial.println(rtc.get()); // get()함수는 기준 시점인 1970년 1월 1일 0시 0분 0초를 기준으로
// 모듈에 설정된 현재 시점 까지의 초를 계산하여 unsigned long type으로 반환합니다.
setSyncProvider(rtc.get); // 현재 Time 라이브러리에서 관리하는 시간데이터를 get()함수로 RTC 모듈에서 가져온 시간테이터(정수 값)와 동기화 시킵니다.
// setSyncProvider()함수는 외부 시간(RTC 모듈의 시간)을 가져와서 동기화 시킵니다.
// 동기화가 잘 이루어지면 내부적으로 "timeSet"이라는 열거형 데이터로 상태값을 설정합니다.
// 동기화가 잘 이루어졌는지 확인하는 부분입니다.
if(timeStatus() == timeSet){ // timeStatus()함수는 상태값을 읽어오는 함수입니다. "timeSet"을 리턴한다면 동기화가 잘된 것 입니다.
Serial.println("Sync is good!");
} else {
Serial.println("Sync is fail.");
setSyncProvider(rtc.get);
}
if(rtc.read(tm) == 0){ // read()함수는 tmElements_t 구조체를 인수로 받아서 시,분,초 등을 알아서 구분하여 해당 구조체에 저장해줍니다.
// read()함수는 실행이 성공하면 0을 반환하고, 실패하면 1을 반환함으로 리턴 값을 확인하는 부분이 필요합니다.
Serial.print(tmYearToCalendar(tm.Year)); // 읽어 온 연도 값에 항상 1970년을 더해야하기 때문에 tmYearToCalendar()를 통해서 이를 수행하고 있습니다.
Serial.print("(=");
Serial.print(tm.Year); // 1970년을 더하지 않은 연도의 값을 읽어옵니다.
Serial.print("+1970");
Serial.print(")");
Serial.print("/");
Serial.print(tm.Month);
Serial.print("/");
Serial.print(tm.Day);
Serial.print(" - ");
Serial.print(tm.Hour);
Serial.print(" : ");
Serial.print(tm.Minute);
Serial.print(" : ");
Serial.println(tm.Second);
}
Serial.println("-------------------------------");
// 현재 시간 데이터의 월과 요일명을 영문으로 제공하는 함수들입니다.
Serial.println(monthStr(month()));
Serial.println(monthShortStr(month()));
Serial.println(dayStr(month()));
Serial.println(dayShortStr(month()));
Serial.println("-------------------------------");
Serial.println("-------------------------------");
delay(5000);
}
2. RTC Module Time Write
#include <DS1302RTC.h>
#include <TimeLib.h>
// DS1302 RTC 모듈의 핀들을 Arduino UNO 보드의 핀에 연결하기 위해 디지털 핀 번호를 지정합니다.
const int CLK = 2;
const int DAT = 3;
const int RST = 4;
// DS1302RTC 객체 생성
DS1302RTC rtc(RST, DAT, CLK);
void setup() {
// Serial 통신 시작 설정
Serial.begin(9600);
Serial.println("DS1302 RTC Module Write Test");
Serial.println("----------------------------");
// RTC 모듈이 정지 상태인지 작동 상태인지 확인합니다.
// haltRTC()함수가 0을 리턴하면 작동 중지 상태이고, 1을 리턴하면 작동 중인 상태입니다.
if (rtc.haltRTC()) {
Serial.println("The DS1302 is stopped.");
rtc.haltRTC(0);
Serial.println("The DS1302 is started.");
delay(100);
} else {
Serial.println("The DS1302 is working.");
}
// RTC 모듈이 쓰기 가능 모드인지 확인 합니다.
// writeEN() 함수가 0을 반환하면 쓰기 금지 상태이고, 1을 반환하면 쓰기 가능 상태로 시간을 사용자가 설정할 수 있는 상태입니다.
if (rtc.writeEN() == 0) {
Serial.println("The DS1302 is write protected.");
} else {
Serial.println("The DS1302 can write.");
rtc.writeEN(false);
Serial.println("Write protected is started");
}
Serial.println("-------------------------------");
Serial.println("-------------------------------");
// RTC 모듈에 새로운 시간 데이터를 설정하는 부분입니다.
tmElements_t tm;
// 작성 중인 현재 시간을 기준으로 합니다.
// 2020년 1월 15일 수요일 오후 15시 03분 30초
tm.Year = CalendarYrToTm(2020); // 입력한 연도에서 1970을 빼주기 위해 CalendarYrToTm()함수를 이용합니다.
tm.Month = 1;
tm.Day = 15;
tm.Wday = 4; // 요일의 영문명을 설정합니다. 일요일 = 1, 월요일 = 2, 화요일 = 3...
tm.Hour = 15;
tm.Minute = 03;
tm.Second = 30;
// 작성한 구조체 tm을 인수로 하여, write()함수를 통해 RTC 모듈의 시간을 설정합니다.
// write()함수가 0을 반환하면 시간 설정이 성공한 것입니다.
if (rtc.write(tm) == 0){
Serial.println("Time is set.");
time_t t = makeTime(tm); // makeTime()함수로 입력한 정수 값들을 이용해 time_t 타입의 값을 생성합니다.
setTime(t); // Time라이브러리의 시간도 동일하게 setTime()함수를 이용해서 시간을 설정합니다.
}
// // 시간 변수 time_t타입을 인수로 하여, set()함수를 통해 RTC 모듈에 시간을 설정합니다.
// // 위의 구조체와 write()함수를 사용해 시간을 설정하는 것과 동일한 결과를 보여줍니다.
// time_t ts = makeTime(tm);
// if(rtc.set(ts) == 0){
// setTime(ts);
// }
// Time 라이브러리의 시간을 출력합니다.
Serial.print(year());
Serial.print("/");
Serial.print(month());
Serial.print("/");
Serial.print(day());
Serial.print(" - ");
Serial.print(hour());
Serial.print(":");
Serial.print(minute());
Serial.print(":");
Serial.println(second());
// RTC 모듈과 Time 라이브러리의 시간을 동기화 시킵니다.
setSyncProvider(rtc.get);
if(timeStatus() == timeSet)
Serial.println(" Ok!");
else
Serial.println(" FAIL!");
// 동기화 후의 시간 데이터를 출력합니다.
Serial.print(year());
Serial.print("/");
Serial.print(month());
Serial.print("/");
Serial.print(day());
Serial.print(" - ");
Serial.print(hour());
Serial.print(":");
Serial.print(minute());
Serial.print(":");
Serial.print(second());
delay(5000);
}
void loop() {
}