PWM 신호 생성은 모든 임베디드 엔지니어 무기고에서 중요한 도구이며 서보 모터의 위치 제어, 컨버터 / 인버터의 전력 전자 IC 전환 및 간단한 LED 밝기 제어와 같은 많은 애플리케이션에 매우 유용합니다. PIC 마이크로 컨트롤러에서 PWM 신호는 필요한 레지스터를 설정 하여 비교, 캡처 및 PWM (CCP) 모듈을 사용하여 생성 할 수 있습니다. PIC PWM 자습서에서이를 수행하는 방법을 이미 배웠습니다. 그러나 그 방법에는 한 가지 상당한 단점이 있습니다.
PIC16F877A은 우리가 CCP 모듈을 사용하는 경우에만 핀 RC1 및 RC2의 PWM 신호를 생성 할 수있다. 그러나 PWM 기능을 사용하려면 더 많은 핀이 필요한 상황이 발생할 수 있습니다. 예를 들어 제 경우에는 CCP 모듈이 절망적 인 로봇 팔 프로젝트를 위해 6 개의 RC 서보 모터를 제어하고 싶습니다. 이러한 시나리오에서는 타이머 모듈을 사용하여 PWM 신호를 생성하도록 GPIO 핀을 프로그래밍 할 수 있습니다. 이렇게하면 필요한 핀으로 많은 PWM 신호를 생성 할 수 있습니다. 멀티플렉서 IC를 사용하는 것과 같은 다른 하드웨어 해킹도 있지만 프로그래밍을 통해 동일한 결과를 얻을 수 있는데 하드웨어에 투자하는 이유는 무엇입니까? 따라서이 튜토리얼 에서는 PIC GPIO 핀을 PWM 핀으로 변환하는 방법을 배우고 테스트하기 위해 디지털 오실로스코프를 사용하여 proteus에서 시뮬레이션하고PWM 신호를 사용하여 서보 모터의 위치를 제어하고 전위차계를 변경하여 듀티 사이클을 변경합니다.
PWM 신호 란 무엇입니까?
세부 사항에 들어가기 전에 PWM 신호가 무엇인지 조금 살펴 보겠습니다. 펄스 폭 변조 (PWM) 는 제어 회로에서 가장 일반적으로 사용되는 디지털 신호입니다. 이 신호는 미리 정의 된 시간과 속도로 높음 (5v) 및 낮음 (0v)으로 설정됩니다. 신호가 높게 유지 되는 시간을 "on time"이라고 하고 신호가 낮게 유지되는 시간을 "off time" 이라고합니다 . PWM에는 아래에서 설명하는 두 가지 중요한 매개 변수가 있습니다.
PWM의 듀티 사이클
PWM 신호가 HIGH (on time)로 유지되는 시간의 비율을 듀티 사이클이라고합니다. 신호가 항상 ON이면 100 % 듀티 사이클이고 항상 꺼져 있으면 0 % 듀티 사이클입니다.
듀티 사이클 = Turn ON 시간 / (Turn ON 시간 + Turn OFF 시간)
변수 이름 |
을 참고하여 |
PWM_Frequency |
PWM 신호의 주파수 |
T_TOTAL |
PWM의 완전한 한 사이클에 걸린 총 시간 |
톤 |
PWM 신호의 정시 |
신사 |
PWM 신호의 꺼짐 시간 |
Duty_cycle |
PWM 신호의 듀티 사이클 |
이제 수학을 해봅시다.
이것은 주파수가 단순히 시간의 역수 인 표준 공식 입니다. 주파수 값은 응용 프로그램 요구 사항에 따라 사용자가 결정하고 설정해야합니다.
T_TOTAL = (1 / PWM_Frequency)
사용자가 Duty cycle 값을 변경하면 우리 프로그램은 그에 따라 T_ON 시간과 T_OFF 시간을 자동으로 조정해야합니다. 따라서 위의 공식을 사용하여 Duty_Cycle 및 T_TOTAL 값을 기반으로 T_ON 을 계산할 수 있습니다.
T_ON = (Duty_Cycle * T_TOTAL) / 100
하나의 전체 사이클 동안 PWM 신호의 총 시간은 켜짐 시간과 꺼짐 시간의 합계가됩니다. 위와 같이 오프 타임 T_OFF 를 계산할 수 있습니다.
T_OFF = T_TOTAL – T_ON
이러한 공식을 염두에두고 PIC 마이크로 컨트롤러 프로그래밍을 시작할 수 있습니다. 이 프로그램은 POT의 ADC 값에 따라 다양한 듀티 사이클을 기반으로 PWM 신호를 생성하기 위해 PIC 타이머 모듈과 PIC ADC 모듈을 포함합니다. 이러한 모듈을 처음 사용하는 경우 하이퍼 링크를 클릭하여 적절한 자습서를 읽는 것이 좋습니다.
GPIO 핀에서 PWM을 생성하도록 PIC 프로그래밍
이 튜토리얼 의 전체 프로그램 은 항상 웹 사이트 하단에서 찾을 수 있습니다. 이 섹션에서는 프로그램이 실제로 어떻게 작성되는지 이해해 보겠습니다. 모든 프로그램과 마찬가지로 구성 비트를 설정하는 것으로 시작합니다. 나는 그것을 설정하기 위해 메모리 뷰 옵션을 사용했습니다.
// CONFIG #pragma config FOSC = HS // 오실레이터 선택 비트 (HS 오실레이터) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT 비활성화 됨) #pragma config BOREN = ON // 저전압 리셋 활성화 비트 (BOR 활성화 됨) #pragma config LVP = OFF // 저전압 (단일 전원) 인-서킷 직렬 프로그래밍 활성화 비트 (RB3는 디지털 I / O 임), MCLR의 HV는 프로그래밍에 사용해야 함) #pragma config CPD = OFF // 데이터 EEPROM 메모리 코드 보호 비트 (데이터 EEPROM 코드 보호 해제) #pragma config WRT = OFF // 플래시 프로그램 메모리 쓰기 활성화 비트 (쓰기 방지 해제; 모든 프로그램 메모리는 EECON 제어에 의해 기록 될 수 있습니다) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) // #pragma config 문은 프로젝트 파일 포함 앞에 있어야합니다. // ON 및 OFF에 #define 대신 프로젝트 열거 형을 사용합니다. #포함
그런 다음 하드웨어에서 사용되는 클럭 주파수를 언급합니다. 여기서 제 하드웨어는 20MHz 크리스털을 사용합니다. 하드웨어에 따라 값을 입력 할 수 있습니다. 그 다음은 PWM 신호의 주파수 값입니다. 제 목표는 50Hz의 PWM 주파수를 필요로하는 취미 RC 서보 모터를 제어하는 것이기 때문에 0.05KHz를 주파수 값으로 설정했으며 애플리케이션 요구 사항에 따라이를 변경할 수도 있습니다.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0.05 // 단위: KHz (50Hz)
이제 Frequency 값이 있으므로 위에서 설명한 공식을 사용하여 T_TOTAL 을 계산할 수 있습니다. 결과는 밀리 초 단위의 시간 값을 얻기 위해 10 씩 감소됩니다. 제 경우에는 T_TOTAL의 값이 2 밀리 초가됩니다.
int T_TOTAL = (1 / PWM_Frequency) / 10; // 주파수에서 총 시간 계산 (밀리 초) // 2msec
그다음에 ADC PIC 튜토리얼에서 논의한 것처럼 전위차계의 위치를 읽기 위해 ADC 모듈을 초기화합니다. 다음으로 매번 호출되는 인터럽트 서비스 루틴이 있습니다. 타이머 오버플로는 나중에 다시 살펴볼 것입니다. 지금은 주 기능을 확인하겠습니다.
주요 기능 내에서 타이머 모듈을 구성합니다. 여기서는 0.1ms마다 오버플로되도록 Timer 모듈을 구성했습니다. 시간 값은 아래 공식을 사용하여 계산할 수 있습니다.
RegValue = 256-((Delay * Fosc) / (Prescalar * 4)) delay in sec 및 Fosc in hz
내 경우에는 프리 스칼라가 64이고 Fosc가 20MHz 인 0.0001 초 (0.1ms) 지연의 경우 레지스터 (TMR0)의 값은 248이어야합니다. 따라서 구성은 다음과 같습니다.
/ ***** 타이머 용 포트 구성 ****** / OPTION_REG = 0b00000101; // 외부 주파수와 64를 프리 스칼라로 사용하는 Timer0 // PULL UP도 활성화합니다 . TMR0 = 248; // 0.0001s의 시간 값을로드합니다. delayValue는 0-256 사이 일 수 있습니다 . TMR0IE = 1; // PIE1 레지스터에서 타이머 인터럽트 비트 활성화 GIE = 1; // 글로벌 인터럽트 활성화 PEIE = 1; // 주변 장치 인터럽트 활성화 / *********** ______ *********** /
그런 다음 입력 및 출력 구성 을 설정해야합니다. 여기서는 ADC 값을 읽기 위해 AN0 핀을 사용하고 PWM 신호를 출력하기 위해 PORTD 핀을 사용합니다. 따라서 출력 핀으로 시작하고 아래 코드 줄을 사용하여 낮게 만듭니다.
/ ***** I / O 용 포트 구성 ****** / TRISD = 0x00; // 포트 D의 모든 핀이 출력되도록 MCU에 지시 PORTD = 0x00; // 모든 핀을 0으로 초기화 / *********** ______ *********** /
무한 while 루프 내에서 듀티 사이클에서 온 타임 (T_ON) 값 을 계산해야합니다. 시간에 및 듀티 사이클은 우리가 내부에 반복적으로 수행하도록 POT의 위치에 따라 달라 동안 아래와 같이 루프. 0.0976은 100을 얻기 위해 1024를 곱해야하는 값이고 T_ON을 계산하기 위해 밀리 초 단위로 값을 얻기 위해 10을 곱했습니다.
while (1) { POT_val = (ADC_Read (0)); // ADC를 사용하여 POT 값 읽기 Duty_cycle = (POT_val * 0.0976); // 0 ~ 1024 ~ 0 ~ 100 매핑 T_ON = ((Duty_cycle * T_TOTAL) * 10 / 100); // 수식 단위를 사용하여 On Time을 밀리 초 단위로 계산합니다. __delay_ms (100); }
타이머는 0.1ms마다 오버 플로우로 설정되어 있으므로 0.1ms마다 타이머 인터럽트 서비스 루틴 ISR이 호출됩니다. 서비스 루틴 내에서 count라는 변수를 사용하고 0.1ms마다 증가시킵니다. 이렇게하면 f 시간을 추적 할 수 있습니다. PIC 마이크로 컨트롤러의 인터럽트에 대해 자세히 알아 보려면 링크를 따르십시오.
if (TMR0IF == 1) // 타이머 오버플로로 인해 타이머 플래그가 트리거되었습니다.-> 0.1ms마다 오버플로 설정 { TMR0 = 248; // 타이머 값로드 TMR0IF = 0; // 타이머 인터럽트 플래그를 지 웁니다. ++; //0.1ms마다 카운트 증가-> count / 10은 ms 단위의 카운트 값을 제공합니다. }
마지막으로 T_ON 및 T_OFF 값에 따라 GPIO 핀을 토글 할 때 입니다. 시간을 밀리 초 단위로 추적 하는 count 변수가 있습니다. 따라서 해당 변수를 사용 하여 시간 이 on time 보다 작은 지 확인하고, 그렇다면 GPIO 핀을 켜진 상태로 유지하고 그렇지 않으면 새주기가 시작될 때까지 끄고 꺼진 상태로 유지합니다. 이것은 하나의 PWM 사이클의 총 시간과 비교하여 수행 할 수 있습니다. 동일한 작업을 수행하는 코드는 다음과 같습니다.
if (count <= (T_ON)) // 시간이 정시보다 적 으면 RD1 = 1; // GPIO 켜기 else RD1 = 0; // 그렇지 않으면 GPIO 끄기 if (count> = (T_TOTAL * 10)) // 새로운 사이클이 시작될 때까지 꺼진 상태 유지 count = 0;
회로도
PIC 마이크로 컨트롤러의 GPIO 핀으로 PWM 을 생성하는 회로도 는 정말 간단합니다. 발진기로 PIC에 전원을 공급하고 전위차계를 핀 AN0에 연결하고 서보 모터를 핀 RD1에 연결하면 GPIO 핀을 사용하여 PWM 신호를 얻을 수 있습니다. RD1이 무작위로 나옵니다. 전위차계와 서보 모터는 모두 아래 회로도에 표시된 것처럼 7805에서 조절되는 5V로 전원이 공급됩니다.
시뮬레이션
프로젝트를 시뮬레이션하기 위해 저는 프로테우스 소프트웨어를 사용했습니다. 아래에 표시된 회로를 빌드하고 코드를 시뮬레이션에 연결하고 실행하십시오. 프로그램에 따라 RD1 GPIO 핀에서 PWM 신호를 받아야하며 PWM의 듀티 사이클은 전위차계의 위치에 따라 제어되어야합니다. 아래 GIF는 전위차계를 통해 ADC 값이 변경 될 때 PWM 신호와 서보 모터가 어떻게 반응하는지 보여줍니다.
PIC 마이크로 컨트롤러를 사용하여 서보 모터를 제어하기위한 하드웨어 설정
내 전체 하드웨어 설정은 아래에 나와 있습니다. 내 튜토리얼을 따르는 사람들에게는이 보드가 익숙해 보일 것입니다. 지금까지 모든 튜토리얼에서 사용한 것과 동일한 보드입니다. 어떻게 빌드하는지 알고 싶다면 LED 깜박임 튜토리얼을 참조하십시오. 그렇지 않으면 위의 회로도를 따르고 모든 것이 잘 작동합니다.
프로그램을 업로드하고 전위차계를 변경하면 전위차계의 위치에 따라 서보가 위치를 변경하는 것을 볼 수 있습니다. 프로젝트 의 전체 작업 은이 페이지 끝에 제공되는 비디오에 표시됩니다. 프로젝트를 이해하고 즐겁게 건축 하셨기를 바랍니다. 질문이 있으시면 언제든지 포럼에 게시 해 주시면 최선을 다해 답변 해 드리겠습니다.
여러 서보 모터를 제어하는 옵션을 추가하여 이미 구축 한 Arduino Robotic Arm과 유사한 로봇 팔을 구축하여이 프로젝트를 진행할 계획입니다. 그럼 그때까지 만나요 !!