본문 바로가기
코딩/아두이노

아두이노 delay 없이 1초마다 작동하는 코드

by DIYver 2022. 7. 18.

아두이노를 사용함에 있어서 고수가 되어 갈 수록 delay() 사용을 지양해야 한다.

이번에는 delay() 함수 없이 1초마다 실행하는 코드를 올려본다.

아래 코드를 복붙해서 아두이노 코딩에 쓰면 되고, loop() 함수 안에 조건문 안쪽에다 1초 마다 실행시킬 명령을 넣으면 된다.

unsigned long pre_timer = 0;
int repeat_time = 1000;

void setup() {

}

void loop() {
  if(millis() > pre_timer + repeat_time)
  {
	pre_timer = millis();
    
    //1초마다 실행되는 명령
  }
  
}

unsigned long 타입으로 타이머를 기록하므로 적어도 30일 동안 아두이노가 켜져있어도 정상 작동하게 된다.
하지만 너무 오랜시간 작동하게되면 unsigned long 타입의 크기를 넘어가게 되므로
장시간 사용을 하려면 추가적으로 손봐야 한다.

일반적으로는 전원 공급하고 30일 넘게 작동하지는 않으므로, 문제가 될 일이 없으니 위의 코드를 사용하면 된다.

 

pre_timer 에는 코드가 작동한 시점에서의 아두이노 가동시각을 저장하고
repeat_time 에 따라서 해당 반복시간마다 코드가 작동되게 되는 것이다.

이렇게 코드를 짜면 delay() 없이 정상적으로 1초 마다 명령을 실행시킬 수 있다.

만약 delay(1000); 을 사용하고 명령을 입력했다면,
명령 수행 기간동안의 지연이 축척되어서 정확하게 1초마다 작동하지 않게 된다.

반면, millis() 를 이용한 제시한 방법대로 사용하면, 아두이노 보드에 내장된 크리스탈 발진기의 진동수로 시간을 측정하므로 정밀하게 제어할 수 있게 된다.

현재 전세계에서 1초의 기준은 세슘-133 원자가 91억9263만1770번 진동하는 시간인데,
아두이노에서의 1초의 기준은 크리스탈 발진기가 16MHz 로 진동하므로,
1천 6백만번의 진동이 감지되어야 1초가 지났다고 판단한다.

따라서 오차가 거의 없이 시계마냥 정확하게 작동한다고 할 수 있다.
위의 코드를 사용하는 경우 명령중에 delay()가 있더라도 값이 작다면 큰 상관이 없다.

예를 들면 1초마다 led를 켜고 끄는 것을 반복한다 했을 때,
쉽게 생각하면 아두이노에 전원이 들어오고 매 홀수 초 때마다 LED가 켜지고, 짝수초일때 LED가 꺼지는 동작이라면,
delay() 가 1초를 잡아먹지 않는 이상 
millis() 가 홀수 초 일때, LED가 켜질 것이고, 짝수 초 일때, LED가 꺼질 것이다.

만약 중간 명령 코드에 delay(2000) 가 있어버리면 이제 골치아픈 일들이 발생하기 시작한다.
홀수 초 일때, LED가 켜지고 2초를 delay()에서 잡아먹고 있었다면, 
delay() 가 끝나는 시점에서 millis()는 다시 홀수 초를 가리키게 되고,
LED가 꺼지는 동작 없이 계속 켜지게 되는 오작동을 하게 된다.

따라서 delay()는 되도록 안쓰도록 하고,
신호 송수신의 안정성 때문에 어쩔 수 없이 사용해야 한다면 10ms 이하로 하여서 짧게만 사용하도록 해야한다.

댓글