보고서 09 12 7 -...
Post on 15-Sep-2018
219 Views
Preview:
TRANSCRIPT
분 야 서보모터제어시스템 설계
초소형 DC 서보 모터를 이용한
정역 속도제어기 구현
소 속 공주대학교
전 공 전 자 공 학
이 름 이 승 용
작 성 일 2009. 12. 10
목 차
Ⅰ. 서 론 ---------------------------------------------------- 1
Ⅱ. 본 론 ---------------------------------------------------- 1
Ⅲ. 결 론 ---------------------------------------------------- 6
참고문헌 --------------------------------------------------------- 6
#첨 부 ------------------------------------------------------- 7
- 1 -
Ⅰ. 서 론
이 시스템은 초소형 DC 서보 모터를 이용한 정역 속도 제어기 구현에 목적이 있다. 피드백 제어
기로는 비례적분 제어기(Proportional-Integral Controller)을 사용한다.
그림 1은 초소형 DC 서보 모터를 사용한 속도제어 시스템 구성도를 나타내고 있다.
그림 1. 초소형 DC 서보 모터를 사용한 속도제어 시스템 구성도.[1]
Ⅱ. 본 론
1. 하드웨어 구성
표 1은 시스템 구성에 사용되는 주요 모듈 및 소자를 나타낸다.
항 목 사 양 사용전압
OK-TFT Ver 1.0 ATMEGA2561, TFT 모듈 포함 +3.3V, +5V
DC Servo MOTORRA20GM 03TYPE 기어비 : 1/10
(로타리 엔코더 내장)+15V
DC Motor Driver Ver 1.0 L298N(DUAL FULL-BRIDGE DRIVER) 포함 +5V, +15V
표 1. 주요 모듈 및 소자.
그림 2. OK-TFT 키트와 DC Motor Driver 보드 및
직류 서보모터의 접속도.
- 2 -
그림 2를 보면 OK-TFT Kit의 여분의 병렬 포트를 이용해서 DC Motor Driver 보드와 연결한
다.
그림 3은 DC Motor Driver Board에서 각 커넥터로 연결된 병렬포트와 로터리의 엔코더 라인
의 색을 보여준다. 또 L298N에서 SENA 부분에서는 과전류 측정을 위해 2W/1Ω의 저항 2개를
병렬 연결하여 사용한다. 또 로타리 엔코더에서 나오는 펄스를 이용한 속도 측정을 위해
PD2(INT)를 이용한다.
그림 3. DC Motor Driver Board 회로도.[2]
1) 모터 특성
이 시스템에서 사용한 초소형 DC 서보 모터 특성은 그림 4와 같다.
그림 4. 초소형 DC 서보모터의 RPM 그래프.
- 3 -
이 실험은 PWM 주파수 2.853kHz에서 듀티비를 10% 씩 증가시키면서 측정한 결과이다. 이
상적인 DC 서보 모터 RPM(그림 4의 점선)과 많은 차이를 보인다.
2) 로타리 엔코더 특성
그림 5 로타리 엔코더에 1회전 당 생성되는 3개의 펄스
그림 5는 로타리 엔코더에서 나오는 펄스를 오실로스코프로 측정한 결과이다. 이 시스템에
사용되는 초소형 DC 서보 모터의 로타리 엔코더는 모터가 1회전 당 3개의 펄스를 생성 한다.
RPM이 증가하면 펄스 주기가 짧아진다. RPM은 60초당 3개의 펄스가 생성된 시간을 나누어
서 구한다.
2. 소프트웨어 구성
1) 인터럽트 처리 루틴
그림 6은 모터의 속도를 측정을 위한 인터럽트 루틴의 흐름도이다.
그림 6. 인터럽트 루틴 흐름도.
- 4 -
처음 펄스 상승 에지시 TCNT4 값 저장 후 15번째 펄스의 상승 에지시 TCNT4 값을 저장
한 후 처음 펄스 상승 에지와의 차를 이용해서 현재 RPM를 구한다. 여기서 사용되는 속도 측
정 방법은 T-Method이다.
2) Main 루틴
인터럽트 루틴에서 구한 상승 에지들의 TCNT4의 값을 이용 Main 루틴에서는 PI 제어를
이용한 속도 추종을 한다.
그림 7은 Main 루틴의 흐름도를 나타내고 있다. P GAIN과 I GAIN은 시행착오법
(Trial-and-error method)을 이용해서 구한다.
그림 7. Main 루틴 흐름도.
- 5 -
3) 화면 구성
그림 8은 화면 구성이다. 현재 RPM과 지령 RPM이 표시되고 RPM 변화를 속도 그래프로
보여준다. 지령 RPM은 버튼으로 0~±9000 까지 조정한다.
속도
그래프
듀티비
표시현재(추종) RPM
지령 RPM
지령 RPM 조절
버튼(±500)
그림 8 화면 구성
4) 실제 구현 사진
그림 9 실제 구현 사진
- 6 -
Ⅲ. 결 론
초소형 DC 서보 모터를 이용해서 정역 속도 제어기를 구현 해봤다. Open-loop 제어 때부터 여기
서 사용된 DC 서보 모터가 일반적인 DC 서보모터와의 RPM 증가 곡선에서 많은 차이를 보였다. 최
종적인 정역 속도 제어기에서도 0~±1000 RPM의 지령 RPM 설정 시 추종하지를 못한다. 1500RPM
이상으로 설정했을 때는 정상적인 속도 추종을 하게 된다. 감지 저항을 이용해서 흐르는 전류값 측
정은 구현 하지 못했다.
이 정역 속도제어기를 작은 미니카에 적용한다면 좋을 것 같다.
단순히 정역 속도제어만 해봤지만 앞으로의 연구과제로 위치제어도 해보고 싶다.
참고문헌
[1] 윤덕용, 2005, 『Atmega128를 활용한 졸업작품 만들기』, OHM사, p461
[2] 윤덕용, http://cpu.kongju.ac.kr, DC Motor Driver 및 Step Motor Driver 보드 1.0의 사용설명
서
- 7 -
# 첨 부
1. 프로그램 소스#include "header/Font.h"
#include "header/TFT28.h"
#include <avr/interrupt.h>
#define FORWARD 0x04 // PORTE2
#define REVERSE 0x02 // PORTE1
#define STOP 0xF8 // PORTE3
#define Kp 0.02 // P gain
#define Ki 0.90 // I gain
#define Ts 0.004 // Speed sampling time[sec]
//////////////////////////////////////////////////////////////// 전역 변수 선언 /////////////////////////////////////////////////////////////
U08 PulseCount = 0;
S16 RPM = 0; // RPM
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 엔코더의 펄스 수 카운트 루틴
ISR ( INT2_vect ) // 인터럽트 처리
{
if ( 15 == PulseCount ) // 15번째 펄스 상승
{
TCCR4B = 0x0000; // Normal 모드로 돌림(카운터/타이머 기능 정지)
//////////////////////////////////////////////// RPM 계산 부분 ////////////////////////////////////////////////////////////////////////////
// 실수로 계산 되므로 float으로 캐스팅 후 U16로 다시 캐스팅
// RPM 구하는 공식 ; ( 60(초) / ( ( 15 펄스의 카운트 수 / 5 ) * 카운트 시간 ) )
RPM = ( S16 ) ( ( ( 60.0 / ( ( TCNT4 / 5.0 ) * ( 16.0 * 0.000001 ) ) ) ) );
- 8 -
if ( PORTE & REVERSE ) RPM = -RPM;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PulseCount = 0;
} // if ( 15 == PulseCount ) End
else
{
if ( 0 == PulseCount ) // 처음 펄스 상승
{
////////////////////////////////////// Timer/Counter 4 CTC Mode 세팅 ////////////////////////////////////////////////
// B상에서 나오는 세 펄스의 주기를 측정을 위한 Timer ; 내부 기능만 사용
TCNT4 = 0; // 초기값 0
//TCCR4A = 0x00; // default setting
TCCR4B = 0x0C; // CTC Mode(4) f/256 Setting
//TCCR4C = 0x00; // default setting
OCR4A = 62499; // TOP 값
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
} // if ( 0 == PulseCount ) End
PulseCount++;
} // else End
EIFR |= 0x20; // Interrupt 2 Clear
} // ISR ( INT2_vect ) End
- 9 -
int main ( void )
{
//////////////////////////////////////////////////////////////// 지역 변수 선언 /////////////////////////////////////////////////////////////
U08 key; // 키 입력 코드 값
U08 DutyRatio; // 듀티비 저장
S16 ReferenceRPM = 0; // 기준(지령) RPM
U08 cnt = 20;
U08 pr = 0;
U16 tempX1 = 20, tempY1 = 315;
U16 tempX2 = 20, tempY2 = 315;
volatile S16 PWM;
volatile float Werr0 = 0, Werr1, PIconstant, PI = 0;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PIconstant = Kp + Ki * Ts; // PI 상수 계산
//////////////////////////////////////////////////////////// MCU 및 TFT-LCD 초기화 //////////////////////////////////////////////////////////
MCU_Initialize ();
TFT_Initialize ();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////// 화면 세팅 /////////////////////////////////////////////////////////////////
TFT_clear_screen ();
TFT_screen_mode ( 'P' );
- 10 -
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////// 초기 화면 출력 /////////////////////////////////////////////////////////////
TFT_string ( 2, 6, WHITE, BLACK, "Servo Motor Control System" );
TFT_string ( 2, 12, WHITE, BLACK, "Duty Ratio : " );
TFT_string ( 2, 18, WHITE, BLACK, "Servo RPM :" );
TFT_string ( 16, 18, GREEN, BLACK, "+0000 RPM" );
TFT_string ( 2, 24, WHITE, BLACK, "Ref. RPM : " );
TFT_string ( 16, 24, CYAN, BLACK, "+0000 RPM" );
Blocks ( 20, 215, 210, 315, PINK, BLACK ); // 화면 지움
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PORTE 3
/////////////////////////////////////////////////////////// PWM 및 모터 방향 설정(TIMER/COUNTER 3) //////////////////////////////////////////
TCCR3A = 0x82; // Fast PWM mode(14)
TCCR3B = 0x1A; // 분주비 : 1/8
TCCR3C = 0x00;
ICR3 = 700; // TOP값 : f = 2MHz / 1 + ( 700 ) = 2853.07Hz = 2.853kHz
OCR3A = 0; // 초기값
PORTE &= 0xF8; // 회전 방향 설정(정지)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- 11 -
//////////////////////////////////////////////////////////////// INT 2 기능 세팅 ////////////////////////////////////////////////////////////
// 엔코더 B상에서 발생되는 펄스 상승 에지시 발생
EICRA = 0x30; // 상승(Rising) 에지시 INT 2 발생
EIMSK = 0x04;
EIFR = 0xFF; // 모든 인터럽트 플래그 클리어
sei (); // global Interrupt enable
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
while ( 1 )
{
//////////////////////////////////////////////////////////// 키 입력 처리 ///////////////////////////////////////////////////////////////
key = Key_input ();
switch ( key )
{
// 기준(지령) RPM 변경
case 0xD0 : // Key2
if ( 9000 > ReferenceRPM ) ReferenceRPM += 500;
break;
case 0xE0 : // Key1
if ( -9000 < ReferenceRPM ) ReferenceRPM -= 500;
break;
} // switch ( key ) End
TFT_xy ( 16, 24 );
TFT_color ( CYAN, BLACK );
- 12 -
TFT_signed_decimal ( ReferenceRPM, 4, 4 );
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if ( 0 == ReferenceRPM ) // 추종해야할 속도가 0이면 All Zero
{
DutyRatio = 0;
PI = 0;
RPM = 0;
} // if ( 0 == ReferenceRPM ) End
else
{
////////////////////////////////////////////////// 듀티비 계산 부분 /////////////////////////////////////////////////////////////////////
DutyRatio = ( U16 ) ( ( ( ( float ) OCR3A ) / ( ( float ) ICR3 ) ) * 100.0 ); // 듀티비 계산
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// PI 제어 ///////////////////////////////////////////////////////////////////////
Werr1 = ( float ) ( ReferenceRPM - RPM );
PI = PI + PIconstant * Werr1 - Kp * Werr0;
Werr0 = Werr1;
// PI Limiter
if ( PI > 700.0 ) PI = 700.0;
else if ( PI < -700.0 ) PI = -700.0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
} // Else End
PWM = ( signed int ) PI;
PORTE &= STOP; // 정지
- 13 -
if ( PWM >= 0 ) PORTE |= FORWARD; // 정방향
else PORTE |= REVERSE; // 역방향
OCR3A = abs ( PWM );
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////// 각 값들 출력 ///////////////////////////////////////////////////////////////////
TFT_xy ( 17, 12 );
TFT_color ( PINK, BLACK );
TFT_unsigned_decimal ( DutyRatio, 3, 3 );
TFT_string ( 20, 12, PINK, BLACK, " %" );
TFT_xy ( 16, 18 );
TFT_color ( GREEN, BLACK );
TFT_signed_decimal ( RPM, 4, 4 );
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////// RPM 그래프 출력 ////////////////////////////////////////////////////////////
if ( pr == 10 )
{
if ( cnt >= 210 )
{
cnt = 20;
Blocks ( 20, 215, 210, 315, PINK, BLACK ); // 화면 지움
tempX2 = tempX1 = 20;
tempY2 = tempY1;
- 14 -
} // if ( cnt >= 210 ) End
tempX2 = cnt;
tempY2 = 315 - ( abs ( PWM ) * 7 / 50 );
if ( PWM < 0 ) Line ( tempX1, tempY1, tempX2, tempY2, RED ); // 역방향일 때(RED)
else Line ( tempX1, tempY1, tempX2, tempY2, YELLOW ); // 정방향일 때(YELLOW)
tempX1 = tempX2;
tempY1 = tempY2;
cnt = cnt + 1;
pr = 0;
}
pr++;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
} // while ( 1 ) End
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
} // int main ( void ) End
top related