delay와 시간

기본 예제로써 아두이노를 한번 쯤 해보셨다면, Blink 예제가 있습니다.
여기에는 delay 함수가 있습니다.
void loop() {
   digitalWrite(LED_BUILTIN, HIGH);
   delay(1000);
   digitalWrite(LED_BUILTIN, LOW);
   delay(1000);
}
이 delay 함수는 코드가 복잡해질 수록 잘 사용하지 않습니다. 혹시 이유를 추측해보실까요?
delay 함수의 기능이 매개변수 로 입력된 시간만큼 기다리는 것인데, 문제는 기다린다 에 있습니다.

문제가 되는 예시를 알아보기 위해서, LED 가 2개 연결된 아두이노가 있다고 가정합니다.
첫 번째 LED는 3초마다 꺼지고, 켜지고를 반복하고, 두 번째 LED는 2초 마다 꺼지고, 켜지고를 반복하게 하려면, 어떻게 해야할까요?

../_images/Step1_16.jpg

묘책이 떠오르셨나요? 아마 변수를 사용하서 어찌 저찌 할 수는 있습니다.
그렇다면, LED를 10개로 늘리고, 각기 다른 시간마다 On,Off가 반복 되게 하는 것은 좀 어렵겠죠?
이렇듯 delay를 사용해서 제어하는 것보다 좋은 방법이 있습니다.

millis()
millis 함수를 이용하는 것입니다. 이 함수는 아두이노가 켜진 뒤부터 얼마나 시간이 지났는지 밀리 초(ms) 단위로 알 수 있습니다.
 1long time;
 2
 3void setup()
 4{
 5   Serial.begin(9600); // 시리얼 통신 시작
 6}
 7
 8void loop()
 9{
10   time = millis(); // millis 함수의 반환 값을 time에 저장
11
12   time = time/1000; // 밀리초(ms) 단위를 초 단위로 변경
13
14   Serial.println(time); // 시리얼 모니터에 time 값 출력
15}

켜지고 나서 시간이 계속해서 지나감을 알 수 있습니다.
이 함수를 사용하면, 좀 더 효율적으로 여러 작업을 진행할 수 있습니다.

millis 함수를 이용해서
2개의 LED가 2초, 3초마다 반복해서 On, Off 되는 코드를 작성해봅니다.
※ LED는 디지털 12번핀, 13번핀에 연결되어 있다고 가정합니다.

작성하고 업로드 후, 동작을 확인합니다. 그리고 아래 코드랑 비교해봅니다.
 1long timeLED1, timeLED2;
 2bool isOnLED1, isOnLED2;
 3
 4void setup()
 5{
 6   // 핀 모드 설정
 7   pinMode(12, OUTPUT);
 8   pinMode(13, OUTPUT);
 9
10   // 기준 시간 설정
11   timeLED1 = millis();
12   timeLED2 = millis();
13
14   // LED 상태를 bool 변수에 저장
15   isOnLED1 = isOnLED2 = false;
16}
17
18void loop()
19{
20   // 기준 시간과 현재시간의 차이가 2초 이상인지 확인
21   if(millis()-timeLED1 > 2000)
22   {
23      // LED 상태에 따라 On Off 실행
24      if(isOnLED1)
25      {
26         digitalWrite(12,LOW);
27         isOnLED1 = false
28      }
29      else
30      {
31         digitalWrite(12,HIGH);
32         isOnLED1 = true;
33      }
34
35      // 기준시간에 현재시간을 저장
36      timeLED1 = millis();
37   }
38
39   // 기준 시간과 현재시간의 차이가 3초 이상인지 확인
40   if(millis()-timeLED2 > 3000)
41   {
42      // LED 상태에 따라 On Off 실행
43      if(isOnLED2)
44      {
45         digitalWrite(13,LOW);
46         isOnLED2 = false;
47      }
48      else
49      {
50         digitalWrite(13,HIGH);
51         isOnLED2 = true;
52      }
53
54      // 기준시간에 현재시간을 저장
55      timeLED2 = millis();
56   }
57}

millis()는 전원이 켜진 뒤 부터 계속해서 값이 증가합니다. 그러므로 long 변수를 만들고, 조건이 될 때마다 현재 시간을 저장해줘야 합니다.
이와 같은 코드로 LED가 많아질 수록 복잡하지 않게 코드를 작성할 수 있습니다.

이런 형태로 아두이노는 2가지 이상의 작업을 수행하는 것처럼 보이게 할 수 있습니다.
실제 아두이노는 계산, 연산하는 두뇌에 해당되는 부품(프로세스, CPU에 해당)이 1개 밖에 없기 때문에 한번에 한가지 작업만 실행할 수 있습니다.
따라서 한번에 여러가지 작업을 하는 것처럼 보일려면, 이런 시간관련 함수를 사용해야 합니다.