✔D2S3231 모듈이 없으므로 millis()를 이용하기로 한다.
아두이노가 현재 프로그램을 돌리고부터의 시간
참조: https://www.arduino.cc/reference/ko/language/functions/time/millis/
millis()는 unsigned long 이므로 약 0에서 4,294,967,295 (2 ^ 32 - 1) 까지이다. 따라서 50일 후에 오버플로우가 된다. 그래서 timer0_millis 변수를 사용한다. 이는 라이브러리에서 선언된 변수로 이를 통해 millis()를 0으로 만들 수 있다. millis가 60초가 될 때마다 0으로 초기화하여 60초를 기준으로 시간을 제어하도록 한다.
timer0_millis를 사용하기 위해서 다음과 같이 선언 후 사용하면 된다.
extern volatile unsigned long timer0_millis;
void setup(){}
void loop(){
t = millis()/1000; //1초, 2초, 3초, ...
// ...
if (t >= 60) timer0_millis = 0; // 60초마다 0으로 초기화
}
millis()에 의해 시간이 흐른다. 이 흐른 시간을 업데이트 하고, 그 시간을 LCD에 표시하는 함수 두 개를 만들었다.
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
extern volatile unsigned long timer0_millis;
unsigned long t;
int year = 2022;
int month = 7;
int day = 5;
int hour = 22;
int minute = 43;
int second = 0;
void setup(){
lcd.init();
lcd.backlight();
}
void loop(){
t = millis()/1000;
//now date
updateDate();
showDate();
if (t >= 60) timer0_millis = 0;
}
void showDate() { //현재 시간 LCD에 표시
String y = String(year);
String mon = String(month);
String d = String(day);
String h = String(hour);
String m = String(minute);
String s = String(second);
if (mon.length() != 2) mon = "0" + mon;
if (d.length() != 2) d = "0" + d;
if (h.length() != 2) h = "0" + h;
if (m.length() != 2) m = "0" + m;
if (s.length() != 2) s = "0" + s;
String date = y + "-" + mon + "-" + d + " " + h + ":" + m + ":" + s;
lcdPrint(date, 0, 0);
}
void updateDate() { //현재 시간 갱신
second = t;
if (second == 60) {
minute += 1;
second = 0;
}
if (minute == 60) {
hour += 1;
minute = 0;
}
if (hour == 24) {
day += 1;
hour = 0;
}
if ((day == 30 + 1 && (month == 4 || month == 6 || month == 9 || month == 11))
|| (day == 31 + 1 && (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12))
|| (year%4 && day == 28 + 1 && month == 2)
|| (!year%4 && day == 29 + 1 && month == 2)) {
month += 1;
day = 1;
}
if (month == 12 + 1) {
year += 1;
month = 1;
}
}
void lcdPrint(String str, int x, int y) { //LCD에 글자 쓰기
for (int i = 0; i < str.length(); i ++) {
lcd.setCursor(x + i, y);
lcd.print(str[i]);
}
}
문제점 해결..
날짜 포맷을 정확히 맞추지 않으면 조금 이상하게 표시가 되더라..
2022-7-5 22:52:59 에서 시간 넘어갈 때
2022-7-5 22:53:0 / 2022-7-5 22:53:09
내가 원한 건 왼쪽인데 오른쪽처럼(빨간색 9) 더 길었던 시간의 잔해가 남았다.
lcd.clear()를 사용하여 LCD를 매번 지우고 새 시간을 썼더니 글자의 빛이 너무 약하고 이상하게 글자가 뒤쪽으로 갈 수록 잘 보이지 않았다. 가변저항 조절해도 마찬가지..
그래서 여러모로 형식이 맞춰져 있는 게 추후 제어에도 편할 듯 하여 2022-07-05 22:52:00 과 같은 형식으로 맞추게 되었다.
그래서 showDate() 함수 안에 추가하게 된 코드
if (mon.length() != 2) mon = "0" + mon;
if (d.length() != 2) d = "0" + d;
if (h.length() != 2) h = "0" + h;
if (m.length() != 2) m = "0" + m;
if (s.length() != 2) s = "0" + s;
나중에 사용자가 시간 제어할 때 년도는 1111부터 9999까지만 가능하게 할 거라서 year는 추가 안 함.
현실에 맞게..
그리고 아래 코드는 윤달과 각 달의 일수가 다른 점을 반영한 것.. (updateDate() 안의 코드)
if ((day == 30 + 1 && (month == 4 || month == 6 || month == 9 || month == 11))
|| (day == 31 + 1 && (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12))
|| (year%4 && day == 28 + 1 && month == 2)
|| (!year%4 && day == 29 + 1 && month == 2)) {
month += 1;
day = 1;
}