Arduino Multi-tasking
22 Jan 2019 | IoT포스팅
다중 작업 처리(Multi-tasking)
아두이노는 운영체제가 없고 강력한 프로세스 하나의 일만 처리한다. 보통 delay() 함수를 사용해 프로그램을 잠시 기다리는 방법을 사용한다. 하지만, delay()를 사용하는 것은 함수가 수행되는 동안에는 어떤 입력도 받을 수 없고, 출력도 할 수 없다. 100% 프로세서에 물려있다고 할 수 있다. 그래서 아두이노 프로세서는 Blink 하는 동안 아무일도 할 수 없다. 해결책으로 delay()대신 millis()함수를 사용하여 시간을 감시해보자. 그래서 우리는 첫번째로 delay()를 사용하지 않는 프로그램을 만들어 보려고한다. 우리는 이것을 Blink without delay라고 부르자.
long previousMillis = 0;
long interval = 1000;
void loop()
{
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval)
{
previousMillis = currentMillis;
원하는 기능 함수
}
}
interval에 시간을 주어 원하는 시간마다 원하는 기능을 체크하는 코드이다.
이번에는 On time 과 Off time 이 다르게 성정되어 동작하는 프로그래밍을 해보자.
우리는 이것을 FlashWithoutDelay 라고 부르자.
int State = LOW;
long previousMillis = 0;
long interval = 1000;
void loop()
{
unsigned long currentMillis = millis();
if((State == HIGH) && (currentMillis - previousMillis >= OnTime))
{
State = LOW; // Turn it off
previousMillis = currentMillis;
원하는 기능 함수
}
else if ((State == LOW) && (currentMillis - previousMillis >= OffTime))
{
State = HIGH; // turn it on
previousMillis = currentMillis;
원하는 기능 함수
}
}
구현이 복잡해 보이겠지만 위의 코드를 통해 $State Machine$이라는 중요한 개념을 알게된다.
$State + Machine = State Machine$
LOW 인지 HIGH 인지를 추적하는 변수($State$)가 있다.
그리고 마지막 변경이 언제 일어 났는지를 추적하는 변수($previousMillis$)가 있다.
이 두가지 변수가 $State Machine$의 주요 부분이다.
추가로 2가지의 기능을 만든다고 하면 추가의 시간 간격 관리를 해줘 프로그래밍하면 된다.
코드를 반복해서 쓰는 것이 반복처럼 보이니 클래스를 만들어 반복해서 쓰도록 하자.
하지만, 이 프로잭트에서는 클래스까지는 필요가 없다. 함수까지만 쓰도록 하자.
#define R0 10000
#define T0 25 //room temperature
#define B 4200 //the coefficient of the thermistor
#define SERISR 10000 //seris resistor 10K
int LledPin = 13;
int TledPin = 9;
int CledPin = 7;
int AledPin = 2;
long previousMillis1 = 0;
long previousMillis2 = 0;
long previousMillis3 = 0;
long previousMillis4 = 0;
long interval = 1000;
void CheckOut(long currentMillis, int ledPin, long previousMillis, float data, int value)
{
if((data > value) && ((currentMillis - previousMillis) > interval))
{
previousMillis = currentMillis;
digitalWrite(ledPin, HIGH);
}
else if((data <= value) && ((currentMillis - previousMillis) > interval))
{
previousMillis = currentMillis;
digitalWrite(ledPin, LOW);
}
}
void setup() {
Serial.begin(9600);
// 9번 핀을 출력으로 설정
pinMode(LledPin, OUTPUT);
pinMode(TledPin, OUTPUT);
pinMode(CledPin, OUTPUT);
pinMode(AledPin, OUTPUT);
}
void loop() {
// 조도 센서 값
int Ldata = analogRead(A0);
// 온도 센서 값
float thermistorRValue = 0;
thermistorRValue = 1023.0 / analogRead(A1) - 1;
thermistorRValue = SERISR / thermistorRValue;
float temperature = 0;
temperature = thermistorRValue / R0; // R/R0
temperature = log(temperature);
temperature = temperature / B;
temperature = temperature + 1.0 / (T0 + 273.15);
temperature = 1.0 / temperature;
temperature -= 273.15 ;// kelvins to C
float Tdata = temperature;
// MQ-7 일산화 탄소 센서 값
int MQ7data = analogRead(A2);
// MQ-3 알코올 센서 값
int MQ3data = analogRead(A3);
unsigned long currentMillis = millis();
CheckOut(currentMillis,LledPin,previousMillis1,Ldata,800);
CheckOut(currentMillis,TledPin,previousMillis2,Tdata,27);
CheckOut(currentMillis,CledPin,previousMillis3,MQ7data,2);
CheckOut(currentMillis,AledPin,previousMillis4,MQ3data,-1);
}