- Tín hiệu PWM là gì?
- Lập trình PIC để tạo PWM trên các Ghim GPIO
- Sơ đồ mạch
- Mô phỏng
- Thiết lập phần cứng để điều khiển Động cơ Servo bằng Vi điều khiển PIC
Tạo tín hiệu PWM là một công cụ quan trọng trong kho vũ khí của mọi kỹ sư nhúng, chúng rất tiện dụng cho nhiều ứng dụng như điều khiển vị trí của động cơ servo, chuyển đổi một số IC điện tử công suất trong bộ chuyển đổi / bộ đảo và thậm chí để điều khiển độ sáng đèn LED đơn giản. Trong vi điều khiển PIC, các tín hiệu PWM có thể được tạo ra bằng cách sử dụng các mô-đun So sánh, Chụp và PWM (CCP) bằng cách đặt các Thanh ghi bắt buộc, chúng ta đã học cách thực hiện điều đó trong hướng dẫn PIC PWM. Nhưng có một nhược điểm đáng kể với phương pháp đó.
Các PIC16F877A có thể tạo ra các tín hiệu PWM chỉ trên chân RC1 và RC2, nếu chúng ta sử dụng các module ĐCSTQ. Nhưng chúng ta có thể gặp phải các tình huống, trong đó chúng ta cần nhiều chân hơn để có chức năng PWM. Ví dụ trong trường hợp của tôi, tôi muốn điều khiển 6 động cơ servo RC cho dự án cánh tay robot của mình mà mô-đun CCP là vô vọng. Trong các tình huống này, chúng ta có thể lập trình các chân GPIO để tạo ra tín hiệu PWM bằng cách sử dụng các mô-đun hẹn giờ. Bằng cách này, chúng tôi có thể tạo ra nhiều tín hiệu PWM với bất kỳ chân nào được yêu cầu. Ngoài ra còn có các phương pháp hack phần cứng khác như sử dụng IC ghép kênh, nhưng tại sao lại phải đầu tư vào phần cứng khi điều tương tự có thể đạt được thông qua lập trình. Vì vậy, trong hướng dẫn này, chúng ta sẽ học cách chuyển đổi chân PIC GPIO thành chân PWM và để kiểm tra nó, chúng tôi sẽ mô phỏng nó trên proteus bằng máy hiện sóng kỹ thuật số và cảđiều khiển vị trí của động cơ Servo bằng cách sử dụng tín hiệu PWM và thay đổi chu kỳ làm việc của nó bằng cách thay đổi chiết áp.
Tín hiệu PWM là gì?
Trước khi đi vào chi tiết, chúng ta hãy tìm hiểu một chút về Tín hiệu PWM là gì. Điều chế độ rộng xung (PWM) là một tín hiệu kỹ thuật số được sử dụng phổ biến nhất trong mạch điều khiển. Tín hiệu này được đặt ở mức cao (5v) và thấp (0v) trong thời gian và tốc độ xác định trước. Thời gian tín hiệu duy trì ở mức cao được gọi là “đúng giờ” và thời gian tín hiệu ở mức thấp được gọi là “thời gian tắt”. Có hai tham số quan trọng đối với PWM như được thảo luận dưới đây:
Chu kỳ hoạt động của PWM
Phần trăm thời gian mà tín hiệu PWM vẫn ở mức CAO (đúng giờ) được gọi là chu kỳ nhiệm vụ. Nếu tín hiệu luôn BẬT, nó đang ở trong chu kỳ làm việc 100% và nếu nó luôn tắt thì đó là chu kỳ làm việc 0%.
Chu kỳ làm việc = Thời gian BẬT / (Thời gian BẬT + Thời gian TẮT)
Tên biến |
Đề cập đến |
PWM_Frequency |
Tần số của tín hiệu PWM |
T_TOTAL |
Tổng thời gian thực hiện cho một chu kỳ hoàn chỉnh của PWM |
T_ON |
Thời gian của tín hiệu PWM |
T_OFF |
Thời gian tắt của tín hiệu PWM |
Duty_cycle |
Chu kỳ nhiệm vụ của tín hiệu PWM |
Vì vậy, bây giờ, chúng ta hãy làm toán học.
Đây là công thức tiêu chuẩn trong đó tần số đơn giản là nghịch đảo của thời gian. Giá trị của tần số phải do người dùng quyết định và đặt dựa trên yêu cầu ứng dụng của họ.
T_TOTAL = (1 / PWM_Frequency)
Khi người dùng thay đổi giá trị Chu kỳ nhiệm vụ, chương trình của chúng tôi sẽ tự động điều chỉnh thời gian T_ON và thời gian T_OFF theo đó. Vì vậy các công thức trên có thể được sử dụng để tính T_ON dựa trên giá trị của Duty_Cycle và T_TOTAL.
T_ON = (Duty_Cycle * T_TOTAL) / 100
Vì Tổng thời gian của tín hiệu PWM trong một chu kỳ đầy đủ sẽ là tổng thời gian đúng giờ và thời gian tắt. Ta có thể tính thời gian tắt T_OFF như hình trên.
T_OFF = T_TOTAL - T_ON
Với những công thức này, chúng ta có thể bắt đầu lập trình vi điều khiển PIC. Chương trình liên quan đến Mô-đun hẹn giờ PIC và Mô-đun PIC ADC để tạo tín hiệu PWM dựa trên chu kỳ Nhiệm vụ thay đổi theo giá trị ADC dạng POT. Nếu bạn chưa quen với việc sử dụng các mô-đun này thì bạn nên đọc hướng dẫn thích hợp bằng cách nhấp vào các siêu liên kết.
Lập trình PIC để tạo PWM trên các Ghim GPIO
Các chương trình hoàn chỉnh cho hướng dẫn này có thể được tìm thấy ở dưới cùng của trang web như mọi khi. Trong phần này, chúng ta hãy hiểu chương trình thực sự được viết như thế nào. Giống như tất cả các chương trình, chúng tôi bắt đầu bằng cách thiết lập các bit cấu hình. Tôi đã sử dụng tùy chọn chế độ xem bộ nhớ để đặt nó cho tôi.
// CONFIG #pragma config FOSC = HS // Các bit chọn bộ tạo dao động (bộ tạo dao động HS) #pragma config WDTE = OFF // Bit Enable Watchdog Timer (WDT đã bị vô hiệu hóa) #pragma config PWRTE = OFF // Bit Bật bộ hẹn giờ nguồn (PWRT bị vô hiệu hóa) #pragma config BOREN = ON // Brown-out Reset bit Enable (BOR được kích hoạt) #pragma config LVP = OFF // Low-Voltage (Single-Supply) Bit cho phép lập trình nối tiếp trong mạch (RB3 là I / O kỹ thuật số, HV trên MCLR phải được sử dụng để lập trình) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Tắt bảo vệ mã dữ liệu EEPROM) #pragma config WRT = OFF // Flash Program Memory Write Enable bit (Tắt bảo vệ ghi); tất cả bộ nhớ chương trình có thể được ghi vào bởi điều khiển EECON) #pragma config CP = OFF // Bit bảo vệ mã bộ nhớ chương trình Flash (Tắt bảo vệ mã) // Các câu lệnh cấu hình #pragma nên đặt trước tệp dự án bao gồm. // Sử dụng enums dự án thay vì #define để BẬT và TẮT. #include
Sau đó, chúng tôi đề cập đến tần số xung nhịp được sử dụng trong phần cứng, ở đây phần cứng của tôi sử dụng tinh thể 20MHz, bạn có thể nhập giá trị dựa trên phần cứng của mình. Tiếp theo đó là giá trị tần số của tín hiệu PWM. Vì mục đích của tôi ở đây là điều khiển động cơ servo RC sở thích yêu cầu tần số PWM là 50Hz, tôi đã đặt 0,05KHz làm giá trị Tần số, bạn cũng có thể thay đổi điều này dựa trên yêu cầu ứng dụng của mình.
#define _XTAL_FREQ 20000000 #define PWM_Frequency 0,05 // tính bằng KHz (50Hz)
Bây giờ, chúng ta có giá trị của Tần số, chúng ta có thể tính T_TOTAL bằng cách sử dụng các công thức đã thảo luận ở trên. Kết quả được giảm đi 10 để nhận giá trị thời gian tính bằng mili giây. Trong trường hợp của tôi, giá trị của T_TOTAL sẽ là 2 mili giây.
int T_TOTAL = (1 / PWM_Frequency) / 10; // tính Tổng thời gian từ tần suất (tính bằng mili giây)) // 2msec
Sau đó, chúng tôi khởi tạo mô-đun ADC để đọc vị trí của Potentiometer như đã thảo luận trong hướng dẫn ADC PIC của chúng tôi. Tiếp theo, chúng ta có thói quen dịch vụ ngắt sẽ được gọi mỗi lần, bộ đếm thời gian bị tràn chúng ta sẽ quay lại điều này sau, bây giờ hãy kiểm tra chức năng chính.
Bên trong chức năng chính, chúng tôi cấu hình mô-đun hẹn giờ. Ở đây tôi đã cấu hình mô-đun Bộ hẹn giờ để tràn cho mỗi 0,1ms. Giá trị của thời gian có thể được tính bằng cách sử dụng các công thức dưới đây
RegValue = 256 - ((Delay * Fosc) / (Prescalar * 4)) độ trễ tính bằng giây và Fosc tính bằng hz
Trong trường hợp của tôi cho độ trễ 0,0001 giây (0,1ms) với prescalar là 64 và Fosc là 20MHz, giá trị của thanh ghi của tôi (TMR0) phải là 248. Vì vậy, cấu hình trông như thế này
/ ***** Cấu hình cổng cho bộ hẹn giờ ****** / OPTION_REG = 0b00000101; // Timer0 với freq bên ngoài và 64 là prescalar // Cũng cho phép PULL UPs TMR0 = 248; // Nạp giá trị thời gian cho 0,0001s; delayValue có thể nằm trong khoảng 0-256 chỉ TMR0IE = 1; // Kích hoạt bit ngắt bộ định thời trong thanh ghi PIE1 GIE = 1; // Bật ngắt toàn cục PEIE = 1; // Bật ngắt ngoại vi / *********** ______ *********** /
Sau đó, chúng ta phải thiết lập cấu hình Đầu vào và Đầu ra. Ở đây chúng ta đang sử dụng chân AN0 để đọc giá trị ADC và chân PORTD để xuất tín hiệu PWM. Vì vậy, hãy khởi tạo chúng dưới dạng các chân đầu ra và làm cho chúng ở mức thấp bằng cách sử dụng các dòng mã dưới đây.
/ ***** Cấu hình cổng cho I / O ****** / TRISD = 0x00; // Hướng dẫn MCU rằng tất cả các chân trên PORT D là ngõ ra PORTD = 0x00; // Khởi tạo tất cả các chân thành 0 / *********** ______ *********** /
Bên trong vòng lặp while vô hạn, chúng ta phải tính toán giá trị của on time (T_ON) từ chu kỳ nhiệm vụ. Các đúng thời hạn và nhiệm vụ chu kỳ khác nhau dựa trên vị trí của các POT vì vậy chúng tôi làm điều đó nhiều lần trong khi vòng lặp như hình dưới đây. 0,0976 là giá trị phải nhân với 1024 để được 100 và để tính T_ON, chúng tôi đã nhân nó với 10 để nhận giá trị tính bằng mili giây.
while (1) { POT_val = (ADC_Read (0)); // Đọc giá trị của POT bằng ADC Duty_cycle = (POT_val * 0.0976); // Ánh xạ 0 đến 1024 thành 0 đến 100 T_ON = ((Duty_cycle * T_TOTAL) * 10/100); // Tính thời gian sử dụng đơn vị công thức tính bằng mili giây __delay_ms (100); }
Vì bộ hẹn giờ được đặt vượt quá dòng trong mỗi 0,1ms, ISR của dịch vụ ngắt bộ định thời sẽ được gọi sau mỗi 0,1ms. Bên trong quy trình dịch vụ, chúng tôi sử dụng một biến được gọi là đếm và tăng nó lên sau mỗi 0,1ms. Bằng cách này, chúng tôi có thể theo dõi thời gian f. Để tìm hiểu thêm về Ngắt trong vi điều khiển PIC, hãy làm theo các liên kết
if (TMR0IF == 1) // Cờ hẹn giờ đã được kích hoạt do tràn bộ định thời -> đặt thành tràn cho mỗi 0,1ms { TMR0 = 248; // Nạp bộ định thời Giá trị TMR0IF = 0; // Xóa cờ ngắt đếm thời gian ++; // Đếm số gia cho mỗi 0,1ms -> count / 10 sẽ cho giá trị đếm bằng ms }
Cuối cùng, đã đến lúc chuyển đổi chân GPIO dựa trên giá trị của T_ON và T_OFF. Chúng tôi có biến đếm theo dõi thời gian tính bằng mili giây. Vì vậy, chúng tôi sử dụng biến đó để kiểm tra xem thời gian có ít hơn thời gian không , nếu có thì chúng tôi tiếp tục bật chân GPIO, nếu không chúng tôi tắt nó và giữ nó tắt cho đến khi chu kỳ mới bắt đầu. Điều này có thể được thực hiện bằng cách so sánh nó với tổng thời gian của một chu kỳ PWM. Mã để làm điều tương tự được hiển thị bên dưới
if (count <= (T_ON)) // If time less than on time RD1 = 1; // Bật GPIO else RD1 = 0; // Khác thì tắt GPIO if (count> = (T_TOTAL * 10)) // Tiếp tục tắt cho đến khi bắt đầu chu kỳ mới count = 0;
Sơ đồ mạch
Sơ đồ mạch tạo PWM bằng chân GPIO của vi điều khiển PIC thực sự rất đơn giản, chỉ cần cấp nguồn cho PIC với dao động và nối chiết áp vào chân AN0 và Servo Motor vào chân RD1, chúng ta có thể sử dụng chân GPIO để lấy tín hiệu PWM, tôi đã chọn RD1 chỉ là ngẫu nhiên. Cả chiết áp và động cơ Servo đều được cấp nguồn bởi 5V được điều chỉnh từ 7805 như hình bên dưới trong sơ đồ mạch.
Mô phỏng
Để mô phỏng dự án, tôi đã sử dụng phần mềm proteus của mình. Xây dựng mạch hiển thị bên dưới và liên kết mã với mô phỏng của bạn và chạy nó. Bạn sẽ nhận được tín hiệu PWM trên chân GPIO RD1 theo chương trình của chúng tôi và chu kỳ làm việc của PWM sẽ được điều khiển dựa trên vị trí của chiết áp. Ảnh GIF bên dưới cho thấy cách tín hiệu PWM và động cơ servo phản hồi khi giá trị ADC được thay đổi thông qua chiết áp.
Thiết lập phần cứng để điều khiển Động cơ Servo bằng Vi điều khiển PIC
Thiết lập phần cứng hoàn chỉnh của tôi được hiển thị bên dưới, đối với những người đang theo dõi các bài hướng dẫn của tôi, bảng này sẽ trông rất quen thuộc, nó giống với bảng mà tôi đã sử dụng trong tất cả các hướng dẫn của mình cho đến nay. Bạn có thể tham khảo hướng dẫn Đèn LED nhấp nháy nếu bạn muốn biết cách tôi xây dựng nó. Nếu không, chỉ cần làm theo sơ đồ mạch ở trên và tất cả sẽ hoạt động tốt.
Tải lên chương trình và thay đổi chiết áp và bạn sẽ thấy servo thay đổi vị trí dựa trên vị trí của chiết áp. Hoạt động hoàn chỉnh của dự án được hiển thị trong video ở cuối trang này. Hy vọng bạn đã hiểu dự án và thích xây dựng, nếu bạn có thắc mắc, hãy đăng chúng trên diễn đàn và tôi sẽ cố gắng hết sức để trả lời.
Tôi đang có kế hoạch tiếp tục dự án này bằng cách thêm các tùy chọn để điều khiển nhiều động cơ servo và do đó xây dựng cánh tay robot từ nó, tương tự như Cánh tay robot Arduino mà chúng tôi đã chế tạo. Vì vậy, cho đến khi đó gặp bạn !!