다음 연재글 참고
전체 포스팅한 자료는 아래와 같다.
아두이노에서 멀티태스킹 구현하기 1 - Multi-tasking the arduino : Blink without delay
아두이노에서 멀티태스킹 구현하기 2 - Multi-tasking the arduino : Blink without delay
아두이노에서 멀티태스킹 구현하기 3 - Multi-tasking the arduino : Blink without delay
아두이노에서 멀티태스킹 구현하기 3.5 - Multi-tasking the arduino 라이브러리 링크 페이지
아두이노에서 멀티태스킹 구현하기 4 - Multi-tasking the arduino
이전에 하던 작업을 깨끗하게 마무리 해보자. 일부 서보모터 제어코드에 동일한 원칙을 적용하고 몇 가지 추가적인 작업을 수행해 보자. 아래 그림과 같이 브레드 보드에 두 개의 서보모터를 연결하고, 가지고 있다면 세 번째 LED도 연결하자.
아래 설명의 코드와 이미지 출처는 https://learn.adafruit.com/multi-tasking-the-arduino-part-1/ 임을 밝혀둔다.
아래 코드는 표준 서보모터를 제어하는 코드다. 여기서는 두려움에 떠는 delay() 함수를 호출한다는 것에 주의하자. 깨끗한 상태 머신을 만들기 위해 필요한 부분을 가져갈 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// Sweep
// by BARRAGAN <http://barraganstudio.com>
// This example code is in the public domain.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created
int pos = 0; // variable to store the servo position
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
|
cs |
아래의 Sweeper 클래스는 스윕 액션을 캡슐화하지만 타이밍에 millis( ) 함수를 사용한다. 이것은 Flasher 클래스가 LED에 대해 수행하는 것과 매우 비슷하다. 또한 서보를 특정 핀과 연결하기 위해 Attach( ) 및 Detach( ) 함수를 추가해야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
class Sweeper
{
Servo servo; // the servo
int pos; // 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)
{
updateInterval = interval;
increment = 1;
}
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);
Serial.println(pos);
if ((pos >= 180) || (pos <= 0)) // end of sweep
{
// reverse direction
increment = -increment;
}
}
}
};
|
cs |
얼마나 작업을 해야 할까 ?
아래의 코드를 보면
이제 우리는 필요한 만큼의 Flashers와 Sweepers를 인스턴스화 할 수 있다. Flashers 각 인스턴스에는 2 줄의 코드가 필요하다.
- 인스턴스를 선언하는 한 줄 : Flasher led1(11, 123, 400);
- 루프에서 업데이트를 호출하는 한 줄 : led1.Update();
스위퍼의 각 인스턴스에는 다음과 같이 3 줄의 코드 만 있으면 된다.
- 인스턴스를 선언하는 하나 : Sweeper sweeper1(15);
- 하나를 설정에서 핀에 연결 : sweeper1.Attach(9);
- 그리고 루프에서 업데이트 할 하나의 호출 : sweeper1.Update();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <Servo.h>
class Flasher
{
// Class Member Variables
// These are initialized at startup
int ledPin; // the number of the LED pin
long OnTime; // milliseconds of on-time
long OffTime; // milliseconds of off-time
// These maintain the current state
int ledState; // ledState used to set the LED
unsigned long previousMillis; // will store last time LED was updated
// Constructor - creates a Flasher
// and initializes the member variables and state
public:
Flasher(int pin, long on, long off)
{
ledPin = pin;
pinMode(ledPin, OUTPUT);
OnTime = on;
OffTime = off;
ledState = LOW;
previousMillis = 0;
}
void Update()
{
// check to see if it's time to change the state of the LED
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; // 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)
{
updateInterval = interval;
increment = 1;
}
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);
Serial.println(pos);
if ((pos >= 180) || (pos <= 0)) // end of sweep
{
// reverse direction
increment = -increment;
}
}
}
};
Flasher led1(11, 123, 400);
Flasher led2(12, 350, 350);
Flasher led3(13, 200, 222);
Sweeper sweeper1(15);
Sweeper sweeper2(25);
void setup()
{
Serial.begin(9600);
sweeper1.Attach(9);
sweeper2.Attach(10);
}
void loop()
{
sweeper1.Update();
sweeper2.Update();
led1.Update();
led2.Update();
led3.Update();
}
|
cs |
이제 간섭이 없이 논스톱으로 실행되는 5 개의 독립적인 작업을 가지게 되었다. loop ()는 단지 5 줄의 코드다. 다음으로 이러한 작업 중 일부와 상호 작용할 수 있도록 버튼을 추가 할 것이다.
아래 그림을 구현하는 일이다.
아래 코드는 루프의 각 단계에서 단추 상태를 확인한다. 버튼을 누르면 Led1 및 sweeper2가 업데이트 되지 않는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include <Servo.h>
class Flasher
{
// Class Member Variables
// These are initialized at startup
int ledPin; // the number of the LED pin
long OnTime; // milliseconds of on-time
long OffTime; // milliseconds of off-time
// These maintain the current state
int ledState; // ledState used to set the LED
unsigned long previousMillis; // will store last time LED was updated
// Constructor - creates a Flasher
// and initializes the member variables and state
public:
Flasher(int pin, long on, long off)
{
ledPin = pin;
pinMode(ledPin, OUTPUT);
OnTime = on;
OffTime = off;
ledState = LOW;
previousMillis = 0;
}
void Update()
{
// check to see if it's time to change the state of the LED
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; // 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)
{
updateInterval = interval;
increment = 1;
}
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);
Serial.println(pos);
if ((pos >= 180) || (pos <= 0)) // end of sweep
{
// reverse direction
increment = -increment;
}
}
}
};
Flasher led1(11, 123, 400);
Flasher led2(12, 350, 350);
Flasher led3(13, 200, 222);
Sweeper sweeper1(15);
Sweeper sweeper2(25);
void setup()
{
Serial.begin(9600);
sweeper1.Attach(9);
sweeper2.Attach(10);
}
void loop()
{
sweeper1.Update();
if(digitalRead(2) == HIGH)
{
sweeper2.Update();
led1.Update();
}
led2.Update();
led3.Update();
}
|
cs |
위 코드는 3 개의 LED가 자체 속도로 깜박인다. 2 명의 Sweeper 는 자신의 비율로 청소한다. 그러나 버튼을 누르면 sweeper2와 led1은 버튼을 놓을 때까지 멈추게 된다. 루프에 지연이 없으므로 버튼 입력에 거의 즉각적으로 반응하여 실행된다.
결 론
이 가이드에서는 Arduino가 사용자 입력과 같은 외부 이벤트에 응답하면서 여러 독립적인 작업을 수행하는 것이 실제로 가능하다는 것을 보여주었다. 우리는 delay ( ) 대신 millis ( )를 사용하여 시간을 정하는 방법을 배웠고 다른 작업들을 하기 위해 프로세서를 놓아주는 방법을 알 수 있었다.
우리는 태스크를 다른 상태 머신과 독립적으로 동시에 실행할 수있는 상태 머신으로 정의하는 방법을 배웠다. 그리고이 상태 머신을 C ++ 클래스로 캡슐화하여 코드를 간단하고 간결하게 유지하는 방법을 배웠다.
이 기술은 Arduino를 슈퍼 컴퓨터로 만들지 않지만, 작지만 놀랍도록 강력한 작은 프로세서를 최대한 활용할 수 있도록 도와준다.
이 연재의 2 부에서는 이러한 기술을 토대로 Arduino가 외부 이벤트에 반응하고 여러 작업을 관리하는 다른 방법을 알아보자.
'개발자 > Arduino' 카테고리의 다른 글
아두이노 온도 습도 센서의 사용 (DHT11센서) 사용하기 (0) | 2017.08.17 |
---|---|
아두이노에서 멀티태스킹 구현하기 4 - Multi-tasking the arduino (0) | 2017.04.21 |
아두이노 멀티태스킹 구현하기 3.5 - Multi-tasking the arduino 라이브러리 링크 페이지 (0) | 2017.04.21 |
아두이노에서 멀티태스킹 구현하기 3 - Multi-tasking the arduino : Blink without delay (2) | 2017.03.20 |
아두이노 멀티태스킹 구현하기 1 - Multi-tasking the arduino : Blink without delay (7) | 2017.03.16 |
아두이노 우노 기구도면 Mechanical Drawing 아두이노 사이즈 도면 (1) | 2016.09.07 |
ADXL345 3축 가속도 센서 모듈, GY-291 테스트 방법 (0) | 2015.11.24 |
아두이노 Due Pinout Diagram 여러가지 (0) | 2015.10.01 |
더욱 좋은 정보를 제공하겠습니다.~ ^^