2022-07-05(현재 시간표시)

유슬기·2022년 7월 6일
0

알람약상자

목록 보기
3/6

방법


  1. 시간을 기억해주는 D2S3231 모듈 사용
    • 장점: 아두이노 전원이 끊겨도 D2S3231의 배터리에 의해 시간이 끊기지 않음
    • 단점: 모듈 필요
  2. millis()를 이용해 시간 흐르게 하기
    • 장점: 모듈 필요 X
    • 단점: 아두이노 전원이 끊기면 시간이 끊김(재설정 필요)

✔D2S3231 모듈이 없으므로 millis()를 이용하기로 한다.

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;
  }
profile
재밌는 걸 만들자!

0개의 댓글