Michael Miller("Makuna")의 Rtc 라이브러리에 포함된 예제(DS1302_Simple)를 활용한 아두이노 시계의 코드를 싣는다. 택트 스위치를 누르면 인터럽트가 발동하여 12시-24시 표시를 전환하게 만드느라 이곳 저곳을 참조하여 코드 조각을 가져다가 일단은 돌아가게 만들어 놓았다.
// CONNECTIONS: // DS1302 CLK/SCLK --> 7 // DS1302 DAT/IO --> 6 // DS1302 RST/CE --> 5 // DS1302 VCC --> 3.3v - 5v // DS1302 GND --> GND #include <ThreeWire.h> #include <RtcDS1302.h> #include <LiquidCrystal.h> #define debounceTime 75 // <<- Set debounce Time (unit ms) int interruptPin1 = 3; // 2 or 3 volatile int state = LOW; char *dayArray[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; ThreeWire myWire(6,7,5); // IO, SCLK, CE RtcDS1302<ThreeWire> Rtc(myWire); LiquidCrystal lcd(8, 9, 10, 11, 12, 13); //RS, EN, data(4,5,6,7) void setup () { Serial.begin(9600); Serial.print("Compiled: "); Serial.print(__DATE__); Serial.print("\t"); Serial.println(__TIME__); lcd.begin(16, 2); lcd.clear(); pinMode(interruptPin1, INPUT_PULLUP); // pulled down using a 10K resistor attachInterrupt(digitalPinToInterrupt(interruptPin1), buttonPushed, FALLING); Rtc.Begin(); RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__); if (!Rtc.IsDateTimeValid()) { // Common Causes: // 1) first time you ran and the device wasn't running yet // 2) the battery on the device is low or even missing Serial.println("RTC lost confidence in the DateTime!"); Rtc.SetDateTime(compiled); } if (Rtc.GetIsWriteProtected()) { Serial.println("RTC was write protected, enabling writing now"); Rtc.SetIsWriteProtected(false); } if (!Rtc.GetIsRunning()) { Serial.println("RTC was not actively running, starting now"); Rtc.SetIsRunning(true); } RtcDateTime now = Rtc.GetDateTime(); if (now < compiled) { Serial.println("RTC is older than compile time! (Updating DateTime)"); Rtc.SetDateTime(compiled); } else if (now > compiled) { Serial.println("RTC is newer than compile time. (this is expected)"); } else if (now == compiled) { Serial.println("RTC is the same as compile time! (not expected but all is fine)"); } } void loop () { RtcDateTime now = Rtc.GetDateTime(); printDateTime(now); if (!now.IsValid()) { // Common Causes: // 1) the battery on the device is low or even missing and the power line was disconnected //Serial.println("RTC lost confidence in the DateTime!?!"); } delay(1000); // one seconds } void printDateTime(const RtcDateTime& dt) { char daystring[16]; char timestring[16]; String flag = "AM"; String stateStr = "24-hr system"; short DOW = dt.DayOfWeek(); sprintf(daystring, " %4u-%02u-%02u %s", dt.Year(), dt.Month(), dt.Day(), dayArray[DOW]); short Hour = dt.Hour(); if ( state ) { // 24-hr system lcd.clear(); sprintf(timestring, " %02u:%02u:%02u", dt.Hour(), dt.Minute(), dt.Second()); } else { // 12-hr system with AM/PM designation if (dt.Hour() > 12) { Hour = dt.Hour() - 12; flag = "PM"; } stateStr = "12-hr system with AM/PM designation"; sprintf(timestring, " %2d:%02u:%02u <%s>", Hour, dt.Minute(), dt.Second(), flag.c_str()); } Serial.print("State "); Serial.print(state); Serial.print(": "); Serial.println(stateStr); lcd.setCursor(0, 0); lcd.print(timestring); lcd.setCursor(0, 1); lcd.print(daystring); } void buttonPushed() { static unsigned long lastTime = 0; unsigned long Now = millis(); if((Now - lastTime) > debounceTime) { state=!state; Serial.print("Button pressed: state changed to "); Serial.println(state); RtcDateTime now = Rtc.GetDateTime(); printDateTime(now); } lastTime = Now; }
C++ 함수 선언부에서 참조를 통하여 파라미터를 전송하는 방법을 겨우 이해하는 수준이다. 따라서 추가로 장착한 버튼을 눌러 시간 설정을 고치도록 개선한 버전 2 코드를 만들려면 아직 갈 길이 멀다. 그 다음 목표는 알람 기능 추가하기.
12시-24시 전환은 3번 버튼이 담당한다. |
버튼을 이용한 시 변경 기능은 Accurate Clock Just Using an Arduino을 참조할 예정이다. paulsb가 공개한 이 프로젝트에서는 그러나 RTC 모듈이라는 외부 하드웨어를 전혀 사용하지 않기 때문에 전원을 새로 연결할 때마다 시각을 새롭게 맞추어야 한다. Makuna의 Rtc 라이브러리를 가져다가 RTC 모듈에 데이터를 써 넣고 읽어오는 기능을 만들어 넣는 일이 필요하다. paulsb의 코드는 시간과 관련한 특별한 객체를 전혀 사용하지 않아서 시간 증가 및 표현을 전부 계산을 통해 구현한다. 공부 목적으로 살펴볼 가치가 있다.
LCD 또는 7-세그먼트 표시기를 이용한 시계 만들기는 아두이노 입문자의 프로젝트로 널리 인식되고 있다. 매우 단순한 목표라고 생각할 수도 있으나 시간이라는 데이터 구조가 의외로 복잡하여 공부를 할 것이 많다. 1970년 1월 1일 0시라는 유닉스 세계의 epoch time이 정해진 이유(사실 명확한 것은 없음) 등에 대해서도 흥미로운 이야깃거리가 많을 것이다.
댓글 없음:
댓글 쓰기