14. 타이머와 PWM 활용 - 스마트 폰으로 제어하는 아두이노 -
강의 개요 일정한 시간을 정해 놓고 그 시간이 흐른 후에 다음 일을 하거나 정확한 시간지연이 필요한 경우에 타이머/카운터를 사용 타이머/카운터는 일정한 개수만큼의 클럭 펄스를 계수하여 시간을 측정하므로, 정확한 시간 측정이 가능 요한 시간을 레지스터 등에 미리 설정하고, 다른 작업과 동시에 사용함으로써, MCU의 효율을 극대화 가능
14.1 클럭과 카운터 디지털 회로에서 클럭은 주어진 일을 순서대로 정확한 시간에 처리하기 위해 사용 카운터는 펄스의 상태가 0에서 1의 변경 또는 1에서 0으로 변경할 때마다 클럭 펄스의 수를 계수하는 장치 타이머는 일정한 시간을 정해 놓고 그 시간이 흐른 후에 다음 일을 하도록 하기 위한 장치 정확한 시간지연이 필요한 경우에 타이머/카운터 사용
마이크로컨트롤러의 타이머/카운터 일정한 개수만큼의 클럭(clock)을 세어 정해진 시간이 되면 인터럽트를 발생시키는 역할 소프트웨어 시간지연 함수 일정 시간 동안 MCU가 특별한 의미가 없는 임의의 명령 수행으로 시간을 보내게 만든 후 MCU의 동작을 정지 타이머 필요한 시간을 미리 레지스터에 설정하여 다른 작업과 병행하게 타이머가 동작 설정한 조건에서 인터럽트 발생하여 MCU의 효율 극대화 타이머 카운터 MCU 내부 클럭을 세는 장치 MCU의 외부에서 입력되는 클럭을 세는 장치 동기 모드 비동기 모드 MCU의 내부 클럭을 계수하여 일정시간 간격의 펄스를 만들어 내거나 일정시간 경과 후에 인터럽트를 발생 외부 핀을 통해서 들어오는 펄스를 계수하여 Event Counter로서 동작
14.2 PWM PWM(Pulse Width Modulation)은 타이머 기능 이용 PWM 주기와 펄스 폭의 비율을 퍼센트로 표시한 것으로 한 주기 동안 모터나 LED 등에 공급할 수 있는 전류나 전력의 양으로 생각할 수 있다.
아두이노 보드의 PWM 핀 UNO보드 : 6개(3, 5, 6, 9, 10, 11번) Mega보드 : 15개(2~13, 44~46번)
예제 14.1 PWM 신호를 생성하기 PWM 동작 모드에서 PWM핀을 통해 PWM신호를 만들어 출력하여 LED의 밝기를 조절 가능 LED 밝기는 PWM 신호의 듀티비(Pulse Duty)에 좌우
예제 14.1의 주요개념 analogWrite( )함수 사용 아두이노의 디지털입출력 핀 가운데 PWM 출력을 핀을 통하여 PWM신호를 만들어 출력 이때 디지털입출력 핀은 pinMode( )함수를 사용하여 입출력 모드지정을 하지 않아도 됨
예제 14.1의 스케치 int LED_pin = 5; int Light; PWM 출력용 핀으로 디지털입출력 핀 5번 지정 void setup() { } PWM 출력용 디지털입출력 핀은 입출력 모드선언이 필요 없음 void loop() { for(Light=0; Light<255; Light++) { analogWrite(LED_pin, Light); delay(10); for(Light=255; 0<Light; Light--) { 값을 0에서 255까지 증가 시키며, PWM 펄스를 발생시켜 LED ON 10ms 시간 지연 값을 255에서 0까지 감소 시키며,
14.3 타이머 ATmega2560의 타이머/카운터 동작 모드 사용 타이머 오버플로우 함수 사용 MsTimer2( ) 함수 타이머/카운터2를 사용하는 라이브러리 함수 아두이노 개발환경에서 기본적으로 제공되는 것이 아니므로 설치하여 사용 필요 MsTimer2 함수의 종류 MsTimer2::set(unsigned long ms, void(*f)( )) MsTimer2::start() MsTimer2::stop()
MsTimer2 함수 설치와 등록 방법 제공된 라이브러리(교재의 홈페이지에서 다운 가능)에서 "\Software\Example\MCU-Multi\libraries"의 "MsTimer2" 복사 "C:\arduino-1.0.3\MCU-Multi\libraries"경로에 있는 "libraries" 폴더 안에 붙여넣기 아두이노 IDE 다시 시작 ※ 사용되는 라이브러리, 프로그램과 안드로이드 폰에 설치 가능한 apk 파일은 출판사의 홈페이지 "www.bookdoo.co.kr"이나 한백전자 홈페이지 "www.hanabck.co.kr"을 통하여 다운 받아 사용할 수 있다.
MsTimer2.h의 구성 #ifndef MsTimer2_h #define MsTimer2_h #include <avr/interrupt.h> namespace MsTimer2 { extern unsigned long msecs; extern void (*func)(); extern volatile unsigned long count; extern volatile char overflowing; extern volatile unsigned int tcnt2; void set(unsigned long ms, void (*f)()); void start(); void stop(); void _overflow(); } #endif
예제 14.2 타이머를 이용하여 LED를 ON/OFF하기 Mega 보드 디지털입출력 핀 22 24 26 28 30 32 34 36 연결 모듈 LED0 LED1 LED2 LED3 LED4 LED5 LED6 LED7 LED 모듈
예제 14.2의 스케치 #include <MsTimer2.h> byte LED[8] = {22,24,26,28,30,32,34,36}; byte i = 0; void flash() { LED_display(i++); } flash()는 타이머2 오버플로우 인터럽트 발생시 실행되는 함수 void setup() { byte k; for(k=0; k<8; k++) pinMode(LED[k],OUTPUT); MsTimer2::set(1000, flash); MsTimer2::start(); LED[8]를 출력모드로 선언 타이머2를 사용하여 1000ms 마다 flash()함수를 실행하도록 설정 void LED_display(byte data) { digitalWrite(LED[k],bitRead(data, k)); LED_display( )함수 선언 입력받은 변수 값으로 LED에 표시 void loop() {
예제 14.3 타이머를 이용한 디지털 시계 만들기 타이머를 이용하여 디지털 시계의 기능 설계 Array-FND 모듈 연결 클럭을 이용하여 일정 카운트 기능을 수행시켜 타이머/카운터 2의 일반 모드 동작 사용 Array-FND 모듈이 2자리씩 2개만 표현 가능하므로 시계의 구성은 초와 분까지만 표시
아두이노 Mega보드와 Array-FND 모듈 연결 디지털입출력 핀 22 24 26 28 30 32 34 36 38 40 42 44 연결 모듈 A B C D E F G H C0 C1 C2 C3 Array-FND 모듈
예제 14.3의 스케치1 #include <MsTimer2.h> enum {C0,C1,C2,C3}; byte FND[8] = {22,24,26,28,30,32,34,36}; byte FND_CON[4] = {38,40,42,44}; byte FND_DATA_TBL[]= {0x3F,0X06,0X5B,0X4F,0X66,0X6D,0X7C,0X07,0X7F, 0X67,0X77,0X7C,0X39,0X5E,0X79,0X71,0X08,0X80}; volatile byte time_s = 0, time_m = 0; void flash(){ if (time_s >= 59) { time_m++; time_s =0; } else time_s++; if (time_m > 59) { time_m =0; flash()는 타이머2 오버플로우 인터럽트 발생시 실행되는 함수
예제 14.3의 스케치2 void setup() { byte z; for(z=0;z<8;z++) pinMode(FND[z],OUTPUT); for(z=0;z<4;z++) pinMode(FND_CON[z],OUTPUT); 1000ms period MsTimer2::set(1000, flash); MsTimer2::start(); } 1000ms 마다 flash()함수를 실행하도록 설정 void print_FND(byte selCx, byte data){ byte z, temp; temp = FND_DATA_TBL[data]; if(selCx == C1) temp |= 0x80; for(z=0;z<4;z++) { if(z == selCx) digitalWrite(FND_CON[z],LOW); else digitalWrite(FND_CON[z],HIGH); for(z=0;z<8;z++){ digitalWrite(FND[z],bitRead(temp,z)); 출력할 숫자를 불러온다. 숫자에 점을 추가
예제 14.3의 스케치3 void loop() { print_FND(C0, time_m/10); delay(1); print_FND(C2, time_s/10); print_FND(C3, time_s%10); } C0:10분단위 출력, 왼쪽 첫번째 FND C1에 1분단위 출력, 왼쪽 두번째 FND C2에 10초단위 출력, 왼쪽 세번째 FND C3에 1초단위 출력, 왼쪽 네번째 FND
예제 14.4 타이머로 부저 울리기 아두이노 보드 디지털입출력 핀 7 연결 모듈 Piezo AUDIO 모듈
예제 14.4의 스케치 #include <MsTimer2.h> byte Piezo = 7; void setup() { MsTimer2::set(3000, alarm); MsTimer2::start(); } 타이머2를 사용하여 3000ms마다 alarm()함수를 실행하도록 설정 void alarm() { long ra=440; for (long i=0; i<=100000; i=i+ra) { digitalWrite(Piezo, HIGH); delayMicroseconds(ra); digitalWrite(Piezo, LOW); delay(200); 타이머2 오버플로우 인터럽트 발생시 alarm() 실행 void loop() {
연습과제 타이머를 이용하여 8개의 LED가 1초 간격으로 켜지고, 8개의 LED가 모두 켜지면, 부저를 울리도록 하시오.