다음 연재글 참고
전체 포스팅한 자료는 아래와 같다.
아두이노에서 멀티태스킹 구현하기 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 |
취업, 창업의 막막함, 외주 관리, 제품 부재!
당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약,
아이디어는 있지만 구현할 기술이 없는 막막함.
우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.
이제 고민을 멈추고, 캐어랩을 만나세요!
코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.
제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!
귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.
캐어랩