Đây là hướng dẫn thứ 11 của chúng tôi về Học vi điều khiển PIC sử dụng MPLAB và XC8. Trong hướng dẫn này, chúng ta sẽ học Cách điều khiển Động cơ Servo bằng Vi điều khiển PIC. Nếu bạn đã làm việc với động cơ Servo, bạn có thể bỏ qua nửa đầu của hướng dẫn này nhưng nếu bạn chưa quen với chính động cơ servo thì hãy tiếp tục đọc.
Cho đến nay, chúng tôi đã đề cập đến nhiều hướng dẫn cơ bản như nhấp nháy LED với PIC, Bộ hẹn giờ trong PIC, giao diện LCD, giao tiếp 7 đoạn, ADC sử dụng PIC, v.v. Nếu bạn là người mới bắt đầu, vui lòng truy cập danh sách đầy đủ các hướng dẫn PIC tại đây và bắt đầu học.
Trong phần hướng dẫn trước, chúng ta đã học cách tạo tín hiệu PWM bằng Vi điều khiển PIC, các tín hiệu được tạo dựa trên giá trị đọc được từ chiết áp. Sau đó, nếu bạn đã hiểu tất cả các chương trình, Xin chúc mừng bạn cũng đã mã hóa cho một động cơ Servo. CÓ, động cơ Servo phản hồi lại các tín hiệu PWM (mà chúng tôi tạo bằng cách sử dụng bộ hẹn giờ ở đây), chúng ta sẽ tìm hiểu lý do và cách làm trong hướng dẫn này. Chúng tôi sẽ mô phỏng và xây dựng thiết lập phần cứng cho dự án này và bạn có thể tìm thấy Video chi tiết ở cuối Hướng dẫn này.
What is a Servo Motor?
Động cơ Servo là một loại cơ cấu truyền động (chủ yếu là hình tròn) cho phép điều khiển góc. Có nhiều loại động cơ Servo nhưng trong hướng dẫn này, chúng ta hãy tập trung vào các động cơ servo sở thích được hiển thị bên dưới.
Servos sở thích là một phương pháp phổ biến vì chúng là phương pháp điều khiển chuyển động rẻ tiền. Họ cung cấp một giải pháp có sẵn cho hầu hết các R / C và nhu cầu của những người yêu thích robot. Họ cũng loại bỏ nhu cầu thiết kế tùy chỉnh hệ thống điều khiển cho từng ứng dụng.
Hầu hết các động cơ servo sở thích có thiên thần quay từ 0- 180 ° nhưng bạn cũng có thể nhận được động cơ servo 360 ° nếu bạn quan tâm. Hướng dẫn này sử dụng động cơ servo 0- 180 °. Có hai loại động cơ Servo dựa trên bánh răng, một loại là Động cơ Servo bánh răng bằng nhựa và loại còn lại là Động cơ Servo bánh răng kim loại. Bánh răng kim loại được sử dụng ở những nơi động cơ bị mài mòn nhiều hơn, nhưng nó chỉ có giá cao.
Động cơ servo được đánh giá theo kg / cm (kilogam trên cm) hầu hết các động cơ servo sở thích được đánh giá ở 3kg / cm hoặc 6kg / cm hoặc 12kg / cm. Kg / cm này cho bạn biết trọng lượng động cơ servo của bạn có thể nâng ở một khoảng cách cụ thể là bao nhiêu. Ví dụ: Một động cơ Servo 6kg / cm sẽ có thể nâng 6kg nếu tải được treo cách trục động cơ 1cm, khoảng cách càng lớn thì khả năng mang trọng lượng càng giảm. Tìm hiểu tại đây Kiến thức cơ bản về động cơ Servo.
Interfacing Servo Motors with Microcontrollers:
Mã màu của động cơ servo của bạn có thể khác nhau, do đó hãy kiểm tra biểu dữ liệu tương ứng của bạn.
Tất cả các động cơ servo đều hoạt động trực tiếp với đường cung cấp + 5V của bạn nhưng chúng tôi phải cẩn thận về lượng dòng điện mà động cơ sẽ tiêu thụ, nếu bạn dự định sử dụng nhiều hơn hai động cơ servo, cần thiết kế một tấm chắn servo thích hợp. Trong hướng dẫn này, chúng tôi sẽ chỉ sử dụng một động cơ servo để trình bày cách lập trình MCU PIC của chúng tôi để điều khiển động cơ. Kiểm tra các liên kết dưới đây để giao tiếp Động cơ Servo với Bộ vi điều khiển khác:
Programming Servo Motor with PICF877A PIC Microcontroller:
OPTION_REG = 0b00000100; // Timer0 with external freq and 32 as prescaler TMR0=251; // Load the time value for 1us delayValue can be between 0-256 only TMR0IE=1; //Enable timer interrupt bit in PIE1 register GIE=1; //Enable Global Interrupt PEIE=1; //Enable the Peripheral Interrupt
oid interrupt timer_isr() { if(TMR0IF==1) // Timer has overflown { TMR0 = 252; /*Load the timer Value, (Note: Timervalue is 101 instaed of 100 as the TImer0 needs two instruction Cycles to start incrementing TMR0 */ TMR0IF=0; // Clear timer interrupt flag count++; } if (count >= on_time) { RB0=1; // complement the value for blinking the LEDs } if (count >= (on_time+(200-on_time))) { RB0=0; count=0; } }
while(1) { pot_value = (ADC_Read(4))*0.039; on_time = (170-pot_value); }
Circuit Diagram:
Simulation and Hardware Setup:
#define _XTAL_FREQ 20000000
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
//TIMER0 8-bit $$RegValue = 256-((Delay * Fosc)/(Prescalar*4))$$
char value = 0;
int on_time ;//= 150; //On-Time for the PWM signal
int count; //count gets incremented for every timer overlap
int pot_value;
/*********ADC Functions*********/
void ADC_Init()
{
ADCON0 = 0x41; //ADC Module Turned ON and Clock is selected
ADCON1 = 0xC0; //All pins as Analog Input
//With reference voltages VDD and VSS
}
unsigned int ADC_Read(unsigned char channel)
{
if(channel > 7) //If Invalid channel selected
return 0; //Return 0
ADCON0 &= 0xC5; //Clearing the Channel Selection Bits
ADCON0 |= channel<<3; //Setting the required Bits
__delay_ms(2); //Acquisition time to charge hold capacitor
GO_nDONE = 1; //Initializes A/D Conversion
while(GO_nDONE); //Wait for A/D Conversion to complete
return ((ADRESH<<8)+ADRESL); //Returns Result
}
//*************************************************//
void interrupt timer_isr()
{
if(TMR0IF==1) // Timer has overflown
{
TMR0 = 252; /*Load the timer Value, (Note: Timervalue is 101 instaed of 100 as the
TImer0 needs two instruction Cycles to start incrementing TMR0 */
TMR0IF=0; // Clear timer interrupt flag
count++;
}
if (count >= on_time)
{
RB0=1; // complement the value for blinking the LEDs
}
if (count >= (on_time+(200-on_time)))
{
RB0=0;
count=0;
}
}
void main()
{
/***************I/O PORT Initialization*************/
TRISB = 0x00; //RB0 used as Servo signal pin
TRISA = 0xFF; //Analog inputs
//*************************************************//
ADC_Init(); //Initializes ADC Module
OPTION_REG = 0b00000100; // Timer0 with external freq and 32 as prescaler
TMR0=251; // Load the time value for 1us delayValue can be between 0-256 only
TMR0IE=1; //Enable timer interrupt bit in PIE1 register
GIE=1; //Enable Global Interrupt
PEIE=1; //Enable the Peripheral Interrupt
while(1)
{
pot_value = (ADC_Read(4))*0.039;
on_time = (170-pot_value);
}
}