ysw's blog

    Arduino Multi-tasking

    22 Jan 2019 |

    포스팅

    다중 작업 처리(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);
    }
    


    가져온곳: https://fishpoint.tistory.com/2095?category=626454