본문 바로가기
  • 경제적 자유를 얻는 그날까지
엔지니어링/임베디드

[아두이노 기초] 타이머 제어

by 베니스상인 2020. 2. 18.

아두이노 우노의 타이머의 종류와 기능에 대해 알아보고 타이머를 이용하여  지난번 제어했던 초음파 센서를 주기적으로 읽도록 변경한다.

 

 

 

1. 회로도 구성

 

초음파센서의 제어에 대한 내용은 지난번 글을 다시 한번 확인한다.

 

https://swiftcam.tistory.com/132

불러오는 중입니다...

 

 

 

2. 기초개념

 

1) 아두이노 UNO 타이머

 

아두이노 UNO는 ATMege328p칩을 사용하기 때문에 3개의 타이머를 가지고 있다. 

 

타이머 종류 해상도 라이브러리 용도
Timer 0 8bit SimpleTimer.h delay 함수 사용
Timer 1 16bit TimerOne.h  
Timer 2 8bit MsTimer2.h tone 함수 사용

 

- 타이머는 정확한 시간을 측정하거나 정확한 시간에 동작 수행을 하기 위해 사용

- 타이머는 CPU 클럭을 사용한다(우노는 16MHz 클럭 사용)

- CPU 클럭은 너무 빠르기 때문에 보통 8, 64, 256, 1024 단위의 prescaler를 사용하여 카운트한다.

- 타이머는 보통 정확한 동작을 수행하기 위해 내부 인터럽트 기반으로 동작한다.

 

 

- 인터럽트 기반 타이머 동작의 예

 

예를 들어 1ms 마다 LED 함수를 호출하고 싶다고 하면 타이머 인터럽트를 사용하면 된다.

prescaler를 1024로 가정하면 1024 *1/16 =  64이다.

1ms는 1024 prescaler가 15.625번 카운트되면 1ms이 걸린다. 

 

아래 그림에서 타이머 0을 사용할 경우 Timer 0는 8bit 이므로 256이 넘어가면 타미어 카운트값이 overflow가 발생한다.  따라서 Timer 0의 시작값을 매번 251로 설정하면 15번이 카운트되고 overflow가 발생하면서 인터럽트 함수가 호출된다.

 

 

 

 

 

3. 소스코드

 

Timer 1은 1초 주기로 LED를 blink 하는데 사용하고 Timer2는 이전 초음파 센서 제어 예제에서 한 것처럼 1ms 주기로 Trigger 신호를 발생하고 수신하는 함수를 수행하도록 한다.

 

Timer 1을 사용하기 위해서는 TimerOne.h라는 라이브러리가 필요하다. 라이브러리는 아두이노 스케치의 라이브러리 관리에서 'Timer' 로 검색하여 찾아 설치한다. Timer2는 MsTimer를 찾아 설치한다.

 

 

MsTimer2.h 라이브러리 검색 및 설치

 

 

TimerOne.h 검색 및 설치

 

 

 

 

라이브러리를 설치했으면 아래와 같이 setup()d에서 Timer관련 설정하고 인터럽트 서비스 루틴을 등록해야 한다.

 

Timer 1은 1초마다 인터럽트가 발생하고 인터럽트 발생시 timerisr() 함수가 호출된다.

 

Timer 2는 1ms 마다 인터럽트가 발생하고 인터럽트 발생시 sensor_read() 함수가 호출된다.

 

  Timer1.initialize(100000); //1us unit
  Timer1.attachInterrupt(timer1_isr);


   MsTimer2::set(1, timer2_isr);
   MsTimer2::start();

 

 

timerisr()과 sensor_read()는 인터럽트가 발생시 수행되는 함수로 할 일을 정의하면 된다.

 

전체 소스는 아래와 같다.

 

 

 

AUNO_Basic_08_02_UltraSensor_Timer.ino
0.00MB

 

 

/*****************************************************/
/*  Project   : Arduino Basic Training Course
/*  Title     : 08_02_UltraSensor with Timer
/*  Descript  : Range measurement using ultra sensor
/*  Platform  : Arduion UNO
/*  IDE: Arduino Sketch 1.6/1.8 or vMicro
/*  Author    : Imported by Arduino example
/*  History   : Rev 1.0  2020.02.11  - Initial release 
/*
/*****************************************************/

#include 
#include 

#include 
#include 

// modify I2C address after finding your I2C address
LiquidCrystal_I2C lcd(0x27, 16, 2);


#define TRIG_PIN  4 
#define ECHO_PIN  3 
#define TIME      10
#define USEC_PER_CENTIMETER  2941.17647       // 1000000/340

#define LED_PIN   13

int tau = 0;
float Range = 0.0;

volatile bool     timer2_isr_done = 0;

void setup() {

  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  Serial.begin(9600);


  lcd.init();
  lcd.backlight();
  lcd.clear();
    
  lcd.setCursor(0,0);           
  lcd.print("UltraSensor Test");       

  Timer1.initialize(100000); //1us unit
  Timer1.attachInterrupt(timer1_isr);


 MsTimer2::set(1, timer2_isr);
 MsTimer2::start();
 
}


void loop() {


 if(timer2_isr_done) {

    timer2_isr_done = 0;

    Serial.print("Range = "); Serial.print(Range);  Serial.println("m");
    
    lcd.setCursor(0,1);           
    lcd.print(" Range : +");       
    lcd.print(Range);       
    lcd.print("m ");       
 }
  
}


void timer1_isr() {

  noInterrupts();

  digitalWrite(LED_PIN, digitalRead(LED_PIN)^1);
  interrupts();

}


void timer2_isr() {

  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(TIME);
  digitalWrite(TRIG_PIN, LOW);

  tau   = pulseIn(ECHO_PIN, HIGH);
  Range = (float)(tau/USEC_PER_CENTIMETER/2);

  timer2_isr_done = 1;

  
}

 

 

 

728x90

댓글