반응형

학습 목표: 타이머를 균일하게 분할하기

아두이노로 여러 동작을 동시에 표현할 때에는 delay를 쓰지 않는다.
예)동시에 LED깜빡이고 LCD 표현하고 키 입력받고 등등

delay를 사용하면 그 만큼 다음 동작이 지연된다.
예)LED 켜고 delay 후 LED 끄고 LCD 표현하고 delay 후 입력받고 등등

 

타이머 분할로 모든 동작을 일정시간마다 실행하려면 다음과 같이 코딩한다.

잘못된 코드 예1) 참고만 하세요.
unsigned long ms = 0;
unsigned long prev_ms;

void loop(void) {
  ms = millis();

  if (ms - prev_ms >= 1000) {
    prev_ms = ms;
    // 일정 시간마다 실행할 코드 추가
  }
}

먼저 전역 변수를 선언한다.

시간은 부호가 없으므로 unsigned long 으로 설정하고 변수도 같은 형식으로 설정한다.

루프문 첫줄에 밀리초를 변수에 저장하는 코드를 입력한다. millis()는 내장 함수이다.

그 다음 현재 밀리초와 이전 밀리초의 값 차이를 비교하는데

문제는 동작 코드가 많으면 루프 반복 시간이 느려져서 ms 값이 불규칙하게 갱신 된다는 것이다.

예) 1초마다 동작을 할 때

· 1번째 비교

아두이노 부팅 후 1234ms 가 됐을 때 prev_ms0이었으니 그 차이는 1234가 되어 if 문 내의 코드가 실행된다.

그리고 prev_ms에는 1234값이 저장 된다.

 

· 2번째 비교

루프가 늦어져 그 다음에 2237ms가 됐을 때 if문이 실행됐다고 하자.

if (2237 - 1234 >= 1000)

2237-1234 = 1003 차이므로 실행 된다.

prev_ms에는 2237값이 저장 됐을 것이다.

 

· 3번째 비교

그 다음 또 늦어져 3236ms가 됐을 때 비교문은 다음과 같다.

if (3236 - 2237 >= 1000)

3236 - 2237 = 999 ?!

원하는 것은 1234ms -> 2234ms -> 3234ms 처럼 1000ms 단위로 실행되어야 하므로 3236ms에서는 실행되어야 한다.

하지만 값차이가 999ms가 되어 실행이 되지 않는다!

처음에는 ms 단위니까 인식하기 힘들지만 누적이 되면?? 초단위로 지연될 것이다.

이런 문제점은 이전 밀리초 변수를 설정값 단위로 증가시키면 해결된다.

 

수정된 코드 예2)
unsigned long ms = 0;
unsigned long prev_ms;

void loop(void) {
  ms = millis();

  if (ms - prev_ms >= 1000) {
    if (ms - prev_ms < 2000 ) prev_ms = ms - (ms - prev_ms - 1000); // 정리하면 prev_ms += 1000;
     else prev_ms = ms;
     // 일정 시간마다 실행할 코드 추가
  }
}

이렇게 사용하면 이전 밀리초는 항상 1000 단위로 저장되어 있을 것이다. 두번째 비교문의 숫자는 첫번째 비교문에 있는 숫자의 2배이다.

prev_ms 값 변화

1234ms -> 2234ms -> 3234ms

3236ms가 됐을 때 코드가 실행될 것이다.

아두이노와 실제 시계를 1분간 비교했을 때 1초씩 60번, 60초가 정확한 것을 알 수 있다.

인용시 본문 URL 표기할 것.

반응형

관련글