안녕하세요 허니컴의 무이메이커스입니다.
저번시간은 아두이노를 사용하면서 Delay()로 인해 발생할 수 있는 문제점과 해결책을 알아보았습니다. 오늘은 FreeRTOS헤더파일 없이 멀티태스킹을 진행해보겠습니다.
< 문제점 >
아두이노는 싱글스레드로 동작합니다. 스레드는 프로세서를 수행하는 하나의 흐름을 말합니다.
스레드가 하나라는 것은 한번에 한가지 일만 할 수 있다는것을 의미합니다.
그렇기 때문에 delay()를 사용하게되면 코드전체가 뒤로 밀리는 현상이 발생합니다.
또, delay()가 사용되어야만 하는 모듈과 다른주기적인 동작이 병행되어야 할 때에도 문제가 발생합니다. 때문에 이번시간에는 아두이노를 이용해 멀티태스킹을 진행해보도록 하겠습니다.
< 아두이노 멀티태스킹 회로도 >
- 사용부품 : 360도 Servo motor2개, LED2개
< 아두이노 멀티태스킹 연결방법 >
5V |
2개 servo motor의 + |
GND |
2개 servo motor의 -, 2개 LED의 - |
13 |
LED1의 + |
12 |
LED2의 + |
10 |
servo motor1의 신호선 |
9 |
servo motor2의 신호선 |
< 아두이노 멀티태스킹 소스코드 >
#include <Servo.h>
class Flasher
{
int ledPin;
long OnTime;
long OffTime;
int ledState;
unsigned long previousMillis;
public:
Flasher(int pin, long on, long off)
{
ledPin = pin;
pinMode(ledPin, OUTPUT);
OnTime = on;
OffTime = off;
ledState = LOW;
previousMillis = 0;
}
void Update()
{
unsigned long currentMillis = millis();
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
ledState = LOW; // Turn it off
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
ledState = HIGH; // turn it on
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
}
};
////////////////////////////////////////////////////////////////////////////
class Sweeper
{
Servo servo; // the servo
int pos = 90; // current servo position
int increment; // increment to move for each interval
int updateInterval; // interval between updates
unsigned long lastUpdate; // last update of position
public:
Sweeper(int interval, int incr)
{
updateInterval = interval;
increment = incr;
}
void Attach(int pin)
{
servo.attach(pin);
}
void Detach()
{
servo.detach();
}
void Update()
{
if((millis() - lastUpdate) > updateInterval) // time to update
{
lastUpdate = millis();
pos += increment;
servo.write(pos);
if ((pos >= 180) || (pos <= 90)) // end of sweep
{
increment = -increment;
}
}
}
};
Flasher led1(12, 100, 400);
Flasher led2(13, 350, 350);
Sweeper sweeper1(15, 2);
Sweeper sweeper2(25, 2);
void setup()
{
sweeper1.Attach(9);
sweeper2.Attach(10);
}
void loop()
{
led1.Update();
led2.Update();
sweeper1.Update();
sweeper2.Update();
}
< 소스&동작 설명 >
Flasher라는 class를 생성해 줍니다. 이 클레스는 LED를 조절할 때 쓰입니다.
이 class를 사용하려면 Flasher led1(핀번호, led 켜있는시간, led 꺼있는시간) 이렇게 인스턴스를 만든 후 loop문에서 led1.Update();로 동작시키면 됩니다.
서보모터를 동작하기 위해서도 마찬가지로 Sweeper라는 class를 생성한 후 Sweeper sweeper1(핀번호, 모터속도 증분)을 통해 인스턴스를 만듭니다. 마지막으로 loop문에 sweeper1.Update()로 동작합니다.
< 동작영상 >
........
시제품 제작 문의