중급 예제

약간은 익숙하시거나 익숙해지셨나요? 그렇다면 조금더 깊이 다뤄볼까요?

MsTimer2라이브러리

2015-04-30 11:41:39

개요

 

아두이노는 간단한 기능을 구현하거나 임베디드 시스템 초보자들이 사용하기에는 더 없이 쉬운 하드웨어입니다.

하지만 분명 점차 사용하면서 초보단계를 걸쳐 중수 고수로 올라가게 되면 아두이노의 한계에 부딪혀 좌절할 때가 있습니다.

 

이런 제약사항은 여러가지가 존재할 수 있겠지만 그 중 하나는 아마도 두 가지 작업을 동시에 실행하고 싶을 때 안된다는 점인데요. 

뭐 센서값을 들어올 때까지 기다렸다가 들어오면 그 센서값을 출력하는 순차적인 작업은 간단히 하나의 loop()안에서 실행이 가능합니다.

현재 loop()안에서 간단히 실행되는 동시작업들은 대부분 우리눈에서 인지 불가능한 시간안에 순차적으로 일어나는 눈속임입니다.

대표적인 작업을 말하자면 'LED 다수를 동시에 껐다 켜기'를 말할 수 있을 듯 합니다. 우리눈에는 분명 LED다수가 동시에 켜지고 꺼지는 듯 하지만 사실은 소스 작성 순서대로 LED는 켜지고 꺼집니다. 둔한 우리 눈이 인지를 못할 뿐이죠.

 

 

하지만 LED에 패턴을 뿌리면서 센서를 읽고 동시에 시리얼 모니터에는 이 작업과는 별도로 여러가지 문자를 뿌려준다고 할 때 구현이 가능할까요?

분명 센서를 읽고 시리얼 모니터에 값을 뿌리는 과정에서 딜레이가 생겨 LED 패턴은 정확히 나타나지 못하고 밀려서 표현되거나 뚝뚝 끊겨서 표현될 것입니다.

 

이런 작업을 하려고 할 때 어떻게 해야 할까요?

물론 AVR내부의 타이머 레지스터(TCCR, OCR, TCNT등등)를 제어하여 인터럽트를 통해 해결할 수 있습니다. 하지만 이럴 경우 초보자들은 레지스터도 모르는 상황에서 인터럽트를 어지럽게 사용하다보니 막힌 문제를 해결하는 과정에서 또 막힐 수 있죠.

 

우리 아두이노 유저들은 이런 복잡한 작업들을 좋아하지 않습니다!

그래서 유저들이 직접 사용하기 쉬운 타이머인터럽트를 하나 개발하였고 이것을 Arduino의 여러 사이트에 배포하였습니다. 

이것이 바로 MStimer2라이브러리 입니다.

 

 

MStimer2라이브러리

 

MStimer2라이브러리는 아래 링크에서 내려받을 수 있습니다.

 

MStimer2라이브러리 받기

MStimer2라이브러리 영문 설명

 

아두이노에 라이브러리를 추가하는 방법은 아래링크에서 확인할 수 있습니다.

 

외부 라이브러리 추가하는 방법

 

MStimer2라이브러리를 보면 참 간단합니다. Set(), Start(), Stop()가 끝입니다.

MsTimer2::set(ms, ISR)

set()함수는 타이머 인터럽트를 사용할 때 필요한 타이머와 인터럽트 처리 함수를 설정합니다.

첫 번째 파라미터의 경우에는 타이머 시간을 나타냅니다. 단위는 ms로 나타낼 수 있습니다(일반 delay()함수와 똑같은 단위)

두 번째 파라미터는 인터럽트 루틴으로 정해진 타이머마다 실행될 함수이름을 작성하면 됩니다.

 

MsTimer2::start()

start()함수는 타이머 인터럽트를 실행시킵니다. 이 함수가 호출되고 나서부터 타이머 인터럽트가 작동됩니다.

 

MsTimer2::stop()

stop()함수는 타이머 인터럽트를 멈춥니다. 이 함수가 호출되고 나서부터 타이머 인터럽트의 작동이 중지됩니다.

 

 

예제 소스

 

1번 소스


void setup() {
  pinMode(13, OUTPUT);
}

void loop() { //13번 LED를 500ms마다 깜빡인다
  digitalWrite(13, HIGH);
  delay(500);
  digitalWrite(13, LOW);
  delay(500);
}

 

2번 소스

#include 

void flash() {
  static boolean output = HIGH;

  digitalWrite(13, output);
  output = !output;
}

void setup() {
  pinMode(13, OUTPUT);

  MsTimer2::set(500, flash); // flash함수를 500ms마다 호출한다
  MsTimer2::start();
}

void loop() {
}

 

위의 두개의 1번 2번 소스는 모두 똑같이 13번 LED를 500ms마다 깜빡이는 소스입니다.

하지만 두개를 실행시켜보면 차이를 느낄 수 있습니다.

 

1번 소스의 경우에는 500ms의 딜레이로 인해 그 시간 동안은 아두이노는 아무런 동작을 할 수 없습니다.

하지만 2번 소스의 경우에는 500ms마다 타이머 인터럽트로 인해 flash함수를 호출하기 때문에 어떠한 딜레이 없이 LED를 깜빡이면서 동시에 다른 작업을 할 수 있습니다.

 

예를 들어 13번 LED를 깜빡이면서 시리얼 모니터에 'BLINK'라는 글씨를 계속적으로 호출하려고 할 때 1번 소스의 경우에는 500ms의 딜레이에 걸려 글씨는 간헐적으로 출력됩니다.

하지만 2번 소스의 경우에는 타이머 인터럽트로 자동으로 flash함수를 호출하면서 BLINK라는 글씨를 딜레이 없이 출력이 가능합니다.

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!

타이머 인터럽트(MsTimer2), 아두이노, 기타

천상호 2016-09-21 20:40:15

그럼 mstimer 사용해서 전구 3개를 20초 간격으로 출력하게 할려면은 어떻게 해야되나요?
제가 해봤는데 불이 하나만 들어오고 나머지는 안들어오더라고요 .... 해결법좀 알려주세요

void flash(){
static boolean output = HIGH;
RedOn();
delay(2000);
GreenOn();
delay(2000);
YellowOn();
delay(2000);
}
void setup(){
MsTimer2::set(6000,flash);
MsTimer2::start();

}
전이렇게 설정했는데요 .. 불 3개가 mstimer 써서 주기적으로 들어오는법좀 알려주세요

asdasdad 2017-11-17 14:05:51

#include
int h,m,s;
void flash(){
s++;
if (s>=60){
m++;s=0;
if (m>=60){
h++;m=0;
if(h>=24){
h=0;
}
}
}
Serial.print(h);Serial.print(":");
Serial.print(m);Serial.print(":");
Serial.println(s);

}

void setup() {
Serial.begin(9600);
MsTimer2::set(2, flash);
MsTimer2::start();
}

void loop(){}

안녕하세여 2017-11-17 14:26:52

#include

int h,m,s;
void flash(){
s++;
if(s>=60){
m++;s=0;
if (m>=60){
h++;m=0;
if(h>=24) h=0;
}
}
Serial.print(h);Serial.print(":");
Serial.print(m);Serial.print(":");
Serial.println(s);
}

void setup(){
Serial.begin(9600);
MsTimer2::set(2, flash);
MsTimer2::start();
}

void loop(){
}