Articles by "điều khiển động cơ"

10 4.104 8051 9 Acquy adc pic All datasheet ALTIUM Altium Designer AM-FM Arduino ARM ARM là gì Ấn Tượng Bản tin công nghệ Bản tin Thiết Bị Số Barobo bất động sản biến Binary Bit board lpc2378 Bộ chuyển đổi ADC Bộ Đếm Bộ điều khiển cửa cuốn Bộ Định Thời Buy Khóa Số Điện Tử Buy Mạch đếm sản phẩm Buy Mạch giao thông Buy Mạch nạp Buy Matrix Byte C cho AVR các hàm vào ra các loại lõi arm các mạch DAC cơ bản các ngắt trong pic Cách đọc điện trở Cách Đọc Giá Trị Điện Trở Cách đọc giá trị tụ điện Cách hàn linh kiện dán cách làm mạch khóa số cách tạo linh kiện dán cad/cam Cài Đặt cài đặt proteus 8 cảm biến Cấu Kiện Logic Khả Trình cấu tạo cấu trúc arm cấu trúc lệnh CCS Chân chân Transistor Chip Khả Trình chuyển đổi Chuyển đổi số tương tự Chuyển Đổi Tương Tự/Số - ADC Chuyển động số chương trình City Clip Điện Tử Code 8051 - ASM Code 8051 - C Code 8051-C code ASM code ASM mẫu 8086 Code AVR - C code C Code Lập Trình Code led sao băng code maupic code mẫu 8051 Code Mẫu 8086 Code Mẫu cho ARM - LPC1343 code mẫu pic Code PIC - C codemaupic Counter Cổng Vào Ra Cơ Bản Cuộn Cảm Cửa cuốn DA DAC Debug Decimal Delay8051 Dev-C++ Diode DIY Dò đường Do It Yourself doanh nghiệp Download DTMF Mobile đảo chiều động cơ Điện Trở Điện Tử Điện Tử Cơ Bản điều chế độ rộng xung điều chế xung PWM điều khiển bằng điện thoại Điều khiển cửa cuốn Điều khiển cửa cuốn bằng điện thoại điều khiển động cơ đo điện áp đo nhiệt độ đo nhiệt độ hiển thị lên lcd trên 8051 Đo Nhiệt Độ LM35 + LCD Đo Nhiệt Độ LM35 + Led 7 thanh đọc màu điện trở đồ chơi động cơ chân không Động cơ nhiên liệu Động cơ robo đồng hồ thời gian thực Ebook Đại Học ebook điện tử Ebook đồ án Ebook Tin Học Encoder Encoder là gì Full Giải Thuật Giải thuật PID Giáo Dục giao tiếp i2c pic 16f877a giao tiếp i2c pic16f877a với ic ds1307 giao tiếp máy tính qua rs232 Giao Tiếp Máy Tính VB6 giao tiếp rs232 giao tiếp spi giữa 2 pic giao tiếp spi trong pic Giáo Trình Điện Tử Giới thiệu 8051 Giới thiệu cơ bản GPIO Graphic Design hàm Hàn linh kiện dán Hexadecimal Hệ Hexa Hệ Nhị Phân Hệ Thập Lục Phân Hệ Thập Phân hiển thị lên lcd 16x2 Hoạt Động Học Học 8051 qua các ví dụ đơn giản Học ALtium Designer học AVR Học Corel Draw X3 Học Eagle HỌC LẬP TRÌNH 16F877A Học Lập Trình 8051 Học Lập Trình C Học Orcad Học Protues hoc-lam-robot-do-duong-qua-video Hồng ngoại hướng dẫn hướng dẫn Altium Designer hướng dẫn đo đồng hồ VOM hướng dẫn keil - C lập trình 8051 hướng dẫn làm led sao băng hướng dẫn làm led trái tim hướng dẫn lập trình ARM Hướng Dẫn Lập Trình ARM - LPC1343 hướng dẫn lập trình ARM-LPC2378 hướng dẫn lập trình CCS hướng dẫn lập trình PIC Hướng Dẫn Led Trái Tim hướng dẫn module sim548c hướng dẫn sử dụng keil hướng dẫn sử dụng proteus 8 Hyper Terminal hercules 3.2.4 I/O IC 555 IC 7447 IC 74HC151 IC 74HC154 IC 74HC245 IC 74HC595 IC 74LS138 IC DS1307 IC đồng hồ thời gian thực IC LM324 IC LM342 IC LM7805 IC số IC số opamp LM324 IC Thông Dụng IC555 Interrupt Keil 4 Full keil arm Keil C Keil uVision3 kế toán kiểm toán khái niệm Khái Niệm Cơ Bản Kho Vật Liệu khóa điện tử khóa số dùng 8051 khóa số dùng 89s52 Khóa Số Điện Tử khuếch đại kiểm tra Kinh doanh maketing kinh tế quản lí Kỹ Thuật Kỹ Thuật Vi Xử Lý làm mạch điện lý thú Làm quen AVR Lap Trinh Dieu Khien Robot Lập Trình lập trình 8051 Lập Trình AVR Lập Trình C lập trình c++ Lập Trình Led Quảng Cáo Lập Trình Nhúng Lập trình pic Lập trình Robot Lập Trình Vi Điều Khiển Lập Trình Với AVR Studio LCD 16x2 Lcd16x2 Led Clock Led Quay led sao băng led trai tim Led Trái Tim Lịch sử ra đời Linh Kiện Cơ Bản linh kiện điện tử Loa LPC 2378 LSB lý thú Mã AVR - C Mạch 7seg Mạch Amply.Mạch Loa Mạch Autorobo Mạch bảo vệ Mạch Cảm Biến mạch cảm ứng sờ tay Mạch Cầu H Mạch cube Mạch Đếm Sản Phẩm Mạch điện cơ bản Mạch điện hay Mạch Điện Ứng Dụng Mạch Điều khiển động cơ Mạch Động Cơ Mạch đồng hồ Mạch đồng hồ 4 led Mạch giao thông Mạch IC số Mạch in mạch khóa số mạch khuếch đại thuật toán mạch led chúc mừng năm mới mạch led đẹp Mạch Led đơn Mạch Led Quảng Cáo mach led trai tim mạch led trái tim Mạch Led Vumeter mạch lý thú Mạch Ma trận Phím Mạch Matrix Mạch nạp Mạch nguồn Mạch Nút Bấm mạch sóng rf mạch tăng áp Mạch thu phát Mạch tổ hợp MSI Mạch trái tim Mạch Vi điều khiển Microbicho module module GSM/GPS Module Sim548 Module Sim548 giao tiếp với vi điều khiển PIC Module Sim548C Mosfet Motor Mô Phỏng Phần Cứng Mô Tả Phần Cứng MSB mua led sao băng News Ngắt Ngắt Trong LPC23xx ngân hàng Ngôn Ngữ Ngôn Ngữ C Ngôn Ngữ Tự Học Lập Trình C Ngôn Ngữ VHDL Nguyên Lý nguyên lý ic 555 Nguyên Tắc nháy led Nhập môn C Nhỏ Gọn Nibble opamp People Phần Mềm phần mềm altium Designer Phần mềm điện tử Phần Mềm Điện Tử Phần Mềm Điện Tử Hay Phần Mềm Hay Phần Mềm Led Quảng Cáo phần mềm proteus 8 Phần mềm vi tính Phần Mền Phương pháp hàn linh kiện dán PIC pic16f877a Print Design Proteus Proteus 7.8 SP2 FULL PWM quà tặng bạn gái quà tặng độc đáo quản trị doanh nghiệp quản trị kinh doanh quét led 7 đoạn Relay robocon Robot ROBOT DÒ ĐƯỜNG rút gọn mạch logic tổ hợp Sach Dien Tu Sản Phẩm Thú Vị Sản Phẩm Thương Mại Sáng tạo Short Smart Home SMD sơ đồ nguyên lý spi Sports Sử Dụng Sử Dụng Đồng Hồ sử dụng đồng hồ VOM sử dụng ngắt trong pic sự khác nhau Sức mạnh số Tải tài chính tài chính doanh nghiệp tài chính ngân hàng Tài Khoản Chia Sẻ Tài Liệu Tài Liệu 8051 tài liệu avr Tài liệu Điện Tử Tài Liệu Pic Tài liệu robocon tài liệu về ngân hàng Tài Liệu Vi Điều Khiển tailieuvn Tạo cổng Com ảo Tạo cổng nối tiếp ảo tạo dự án trong keil arm Tạo Project trong Vi Xử Lý ARM tạo thư viện altium designer tạo xung vuông Tạp chí Tạp Chí Hay tăng áp Tập lệnh AT Team Support TEAMPLATE PROTEUS Test thị trường tài chính Thiết Bị Thú Vị Thiết kế robot Thiết lập Fuse Bits Thiết Lập Pin Thuật Toán Thuật Toán Điều Khiển PID Thuật Toán Quine MCCluskey Thư viện Protues Thực Hành Thyristor Timer Timer/Counter Tin Học Chia Sẻ Tổ Chức Bộ Nhớ tổng quan về proteus 8 Transistor Tranzito Tranzitor Trao đổi học tập Travel Trình Biên Dịch Trình Dịch Trong Suốt Truyền Thông Nối Tiếp Không Đồng Bộ- UART truyền thông nối tiếp RS232 Tụ điện TUT - 8051 - ASM TUT - 8051 - KeilC tự hành Tự Học C Tự Học Lập Trình C Tý hon UART Update USB Ứng Dụng Led Quảng Cáo ứng dụng mạch khuếch đại thuật toán vẽ mạch in vẽ mạch nguyên lý VHDL Vi Điều Khiển Vi điều khiển - Ứng dụng vi điều khiển PIC Vi mạch số Vi Xử Lý Vi Xử Lý 8051 Vi Xử Lý 8086 Vi Xử Lý ARM Vi Xử Lý PIC Video Video Mach Điện Virtual Serial Port Driver VOM vxl Web Design xác định góc quay động cơ xử lý chuỗi
Hiển thị các bài đăng có nhãn điều khiển động cơ. Hiển thị tất cả bài đăng


Tóm tắt
Tài liệu hướng dẫn lập trình cho robot tự động dò đường theo vạch trắng và điều khiển các cơ cấu một cách cơ bản nhất.Vi điều khiển được sử dụng trong tài liệu là PIC16F877A của Microchip.Lập trình bằng ngôn ngữ C với trình biên dịch CCS.

1 TÓM TẮT VỀ THIẾT KẾ ROBOT TỰ ĐỘNG
Robot tự động trong các cuộc thi Robocon gồm 3 thành phần chính: Cơ khí, Mạch điện tử, Lập trình.

1.1 Cơ khí
Một robot đơn giản gồm 2 động cơ truyền động cho 2 bánh xe bên trái và bên phải giúp robot di chuyển. Phía trước có thể là 1 hoặc 2 bánh tự do (bánh tự lựa, omni, mắt trâu,…). Để thực hiện được các công việc như nâng hạ trục, gắp nhả đẩy quá, robot được trang bị thêm các động cơ khác để truyền động cho các cơ cấu này. 
Tất cả các bộ phận trên được bố trí trên một khung bằng nhôm, sắt,… 
Phần hướng dẫn chi tiết về thiết kế cơ khí sẽ được trình bày trong một tài liệu khác. Tài liệu này chỉ tập trung vào phần lập trình.
Mô hình robot dò dường đơn giản


1.2 Mạch điện tử

Sơ đồ hoạt động của robot tự động

1.2.1 Mạch ngõ vào (cảm biến, nút ấn, công tắc hành trình)
Với robot đơn giản, ngõ vào thường là mức logic lấy từ cảm biến quang (quang trở, quang diode), nút ấn hoặc công tắc hành trình. Từ đó mạch vi điều khiển xử lý các tín hiệu này để xuất ngõ ra (thường là động cơ DC) chophù hợp.
Cảm biến quang phải được che chắn cẩn thận để hạn chế ảnh hưởng từ cácnguồn ánh sáng bên ngoài.

Mạch cảm biến, nút ấn và công tắc hành trình


1.2.2 Mạch vi điều khiển
Mạch sử dụng vi điều khiển PIC16F877A của Microchip. Mạch nhận tín hiệu từ ngõ vào, xử lý và xuất ngõ ra qua một mạch cách ly bằng opto ra mạch công suất.



Mạch vi điều khiển


1.2.3 Mạch công suất điều khiển động cơ DC
Một số mạch thông dụng:





Mạch công suất sử dụng 1 FET và 1 relay



Mạch cầu H điều khiển động cơ với Half Bridge Driver IR2184


1.3 Lập trình
Đây là phần chính của tài liệu này. Ngôn ngữ lập trình được sử dụng là C, với trình biên dịch CCS cho vi điều khiển PIC của Microchip.
Kiến thức ban đầu: 
         Lập trình C căn bản
Các tài liệu tham khảo:
         Tài liệu CCS tiếng Việt.

Đây là các tài liệu cần đọc qua trước khi vào lập trình cho PIC để có thể biết các hàm nhận tín hiệu ngõ vào, xuất tín hiệu ngõ ra, ngắt, timer, counter, PWM,…
Các hàm quan trọng sẽ được nhắc lại ở phần 2.

2 LẬP TRÌNH CHO ROBOT TỰ ĐỘNG DÒ ĐƯỜNG ĐƠN GIẢN
Chương trình giúp robot chạy theo vạch trắng trên nền màu sậm.

2.1 Phần cứng
 8 cảm biến quang dò đường
 Mạch công suất điều khiển 2 động cơ
 Mạch vi điều khiển:
          o PORTD: nối với tín hiệu ra của 8 cảm biến
          o Động cơ trái:
                           Chân C0: điều khiển chiều (DIR_LEFT)
                           Chân C1: điều khiển cho phép chạy (EN_LEFT)
          o Động cơ phải:
                           Chân C3: điều khiển chiều (DIR_RIGHT)
                           Chân C2: điều khiển cho phép chạy (EN_RIGHT)
(Các ngõ vào và ngõ ra có thế nối với bất cứ PORT và chân nào của vi điều khiển)

2.2 Nguyên tắc điều khiển
2.2.1 Điều khiển động cơ


Tương tự đối với các động cơ điều khiển các cơ cấu.

2.2.2 Hướng di chuyển của robot




2.2.3 Xử lý tín hiệu cảm biến (xem hình vẽ)
Mục đích của việc dò đường là hướng cho robot đi theo 1 vạch thẳng màu trắng trên một nền màu đậm (đen, xanh,…)
Cảm biến được đặt ở giữa robot.
            o Khi cảm biến số 3,4 nằm trên vạch trắng (mức 1): robot chạy thẳng
            o Khi robot lệch sang trái: quay phải để điều chỉnh robot về đúng vạch
            o Khi robot lệch sang phải: quay trái để điều chỉnh robot về đúng vạch



Các mức độ lệch ra khỏi vạch trắng của robot


2.3 Chương trình điều khiển

#include <16f877A.h>
#include <def_877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
/* ĐỊNH NGHĨA CÁC CHÂN VÀ PORT */
#define DIR_LEFT RC0
#define  EN_LEFT         RC1
#define DIR_RIGHT RC3
#define  EN_RIGHT RC2


#define SENSOR PORTD
/* KHAI BÁO CÁC CHƯƠNG TRÌNH CON */
void motor_left_forward();
void motor_left_reverse();
void motor_left_stop();
void motor_right_forward();
void motor_right_reverse();
void motor_right_stop();
void forward();
void reverse();
void stop();
void turn_left();
void turn_right();
/* CÁC CHƯƠNG TRÌNH CON */
// Động cơ trái chạy thuận
void motor_left_forward()
{
DIR_LEFT=1; // chiều thuận
EN_LEFT=1; // cho phép chạy
}
// Động cơ trái chạy ngược
void motor_left_reverse()
{
DIR_LEFT=0; // chiều ngược
EN_LEFT=1; // cho phép chạy
}
// Động cơ trái dừng
void motor_left_stop()
{
EN_LEFT=0; // không cho phép chạy
}
// Động cơ phải chạy thuận
void motor_right_forward()
{
DIR_RIGHT=1;// chiều thuận
EN_RIGHT=1; // cho phép chạy
}
// Động cơ phải chạy ngược
void motor_right_reverse()
{
DIR_RIGHT=0;// chiều ngược
EN_RIGHT=1; // cho phép chạy
}
// Động cơ phải dừng
void motor_right_stop()
{
EN_RIGHT=0; // không cho phép chạy
}
// Chạy thẳng
void forward()
{
motor_left_forward();
motor_right_forward();
}
// Chạy lùi
void reverse()
{
motor_left_reverse();
motor_right_reverse();
}
// Dừng
void stop()
{
motor_left_stop();
motor_right_stop();
}
// Quay trái
void turn_left()
{
motor_left_forward();
motor_right_reverse(); // hoặc motor_right_stop();
}
// Quay phải
void turn_right()
{
motor_left_reverse(); // hoặc motor_left_stop();
motor_right_forward();
}
/* CHƯƠNG TRÌNH CHÍNH */
void main ()
{
TRISC=0x00; // PORTC là ngõ ra ( động cơ)
TRISD=0x00; // PORTD là ngõ vào (cảm biến quang)
PORTC=0x00; // Khởi tạo giá trị ban đầu 0x00 cho PORTC
while(1)
{
switch (SENSOR)
{
case 0b00011000: forward(); break;
case 0b00001100: turn_left(); break;
case 0b00000110: turn_left(); break;
case 0b00000011: turn_left(); break;
case 0b00000001: turn_left(); break;
case 0b00110000: turn_right(); break;
case 0b01100000: turn_right(); break;
case 0b11000000: turn_right(); break;
case 0b10000000: turn_right(); break;
}
}
}


3 CẢI TIẾN CHƯƠNG TRÌNH DÒ ĐƯỜNG
3.1 Điều khiển tốc độ động cơ với các trạng thái lệch khỏi vạch trắng
3.1.1 Nguyên lý
Đối với chương trình dò đường đơn giản, khi robot lệch trái hoặc lệch phải, robot sẽ quay phải hoặc quay trái để điều chỉnh cho dù lệch ít hay lệch nhiều. Như vậy, trong quá trình di chuyển, robot sẽ lắc liên tục vì phải quay trái, quay phải liên tục. Do đó, với các mức độ lệch ra khỏi vạch trắng khác nhau, ta điều chỉnh tốc độ 2 bánh trái, phải cho phù hợp để quá trình di chuyển theo vạch của robot được “nhuyễn” và “mượt” hơn.
Bảng giá trị tham khảo tốc độ động cơ trái và động cơ phải tương ứng với các trạng thái lệch khỏi vạch trẳng của robot:



3.1.2 Điều khiển tốc độ động cơ DC bằng phương pháp PWM
Đối với điều khiển tốc độ động cơ DC trong robot, phương pháp được sử dụng phổ biến nhất là điều chế độ rộng xung (Pulse Width Modulation) hay được gọi tắt là điều xung, băm xung hoặc PWM.
Nguyên lý của phương pháp này là bật tắt nhanh nguồn điện cấp vào động cơ tạo ra một tín hiệu xung. Khi việc bật tắt ở tần số đủ lớn (thường sử dụng từ 1kHz đến 20kHz), động cơ sẽ chạy với 1 tốc độ ổn định nhờ moment quay.
Thời gian cấp nguồn cho động cơ là T-on, thời gian tắt nguồn động cơ là T-off. Việc thay đổi thời gian T-on và T-off làm thay đổi điện áp hiệu dụng cấp cho động cơ. Đối với động cơ DC, tốc độ động cơ tương đối tỉ lệ thuận với điện áp cấp cho động cơ. Vì vậy, bằng cách thay đổi độ rộng của xung, ta đã thay đổi được tốc độ của động cơ DC.
Đại lượng biểu diễn mối quan hệ giữa T-on và T-off được gọi là duty cycle:
duty_cycle = Ton / ( Ton + Toff )
Ví dụ: Ta cấp nguồn động cơ trong 0.8ms, sau đó tắt 0.2ms.
Như vậy: T-on = 0.8ms; T-off = 1ms. Tần số PWM là:
f = 1 / ( Ton + Toff ) = 1 / ( 0.8ms + 0.2ms ) = 1/1ms = 1KHz
duty_cycle = Ton / ( Ton + Toff ) = 0.8 / ( 0.8 + 0.2 ) = 0.8 = 80%

Vì tốc độ động cơ DC tỉ lệ với duty cycle nên tốc độ động cơ đạt tương đương 80% tốc độ tối đa.


Tính toán duty cycle để điều khiển tốc độ động cơ DC


3.1.3 Điều xung PWM dùng vi điều khiển
 Điều xung PWM bằng phần mềm:
Điều xung PWM một cách đơn giản là đưa 1 chân nào đó của vi điều khiển lên mức 1, sau đó đưa xuống mức 0. Công việc này được lặp đi lặp lại liên tục sẽ tạo ra xung, và tốc độ của động cơ sẽ tương ứng với duty cycle.
Ví dụ: Điều xung trên chân A0 :
Code:
RA0=1;
Delay_ms(Ton);
RA0=0;
Delay_ms(Toff);

Tuy nhiên, nếu thực hiện bằng cách này thì vi điều khiển sẽ luôn dành thời gian cho việc điều xung PWM. Do đó, các công việc khác như nhận tín hiệu từ cảm biến, điều khiển các cơ cấu sẽ bị ảnh hưởng.

 Điều xung PWM bằng phần cứng
Để giải quyết vấn đề việc điều xung PWM bằng phần mềm chiếm phần lớn thời gian hoạt động của vi điều khiển, PIC16F877A có hỗ trợ 2 kênh điều xung bằng phần cứng ở 2 chân C1 (CCP2)C2(CCP1) sử dụng TIMER2. Nghĩa là, khi ta khai báo điều xung PWM ở một tần số và duty cycle nào đó thì vi điều khiển sẽ thực hiện công việc xuất xung một cách liên tục và tự động cho đến khi ta thay đổi các giá trị đã khai báo. Khi đó, ta có thể làm các công việc khác một cách dễ dàng mà không phải mất thời gian cho việc duy trì xung PWM.

Các hàm hỗ trợ việc điều xung bằng phần cứng của CCS:
Ghi chú: Chỉ đề cập đến các đối số của các hàm được phục vụ cho việc điều xung PWM.
o setup_timer_2 (mode, period, postscale)
       mode: T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
          period: 0-255
          postscale: 1
       Tần số điều xung PWM:
f = fosc / [ 4*mode*(period+1) ]
o setup_ccp1(mode) và setup_ccp2(mode)
      mode:
         CCP_PWM: chọn chế độ PWM.
         CCP_OFF: tắt chế độ PWM.
o set_pwm1_duty(value) và set_pwm2_duty(value)
 Nếu value là giá trị kiểu int 8bit:
duty_cycle = value / ( period+1 )
  Nếu value là giá trị long int 16bit:
                                                 duty_cycle = value&1023 / [4*( period+1 )]
 Nếu không cần điều xung quá “mịn” thì nên điều xung ở giá trị value 8bit cho đơn giản.
Ví dụ: Ta muốn điều xung PWM với tần số 10kHz với tần số thạch anh (fosc) sử dụng là 20MHz (value 8bit).
f=fosc/[4*mode*(period+1)] <=> 10000 =20000000/[ 4*mode*(period+1) ] <=> mode(period+1) = 500
Với mode = [1,4,16] và period = 0-255 ta có thể chọn:
       o mode = 4;   period = 124
       o mode = 16; period = 32
Để cho việc điều xung được “mịn” (chọn được nhiều giá trị duty cycle) ta chọn mode = 4 và period = 124.
Như vậy, để duty_cycle từ 0% đến 100% ta cho value từ 0 đến 125.
       o value = 30 =>  duty_cycle = 30 / ( 124+1 ) = 0.32 = 32%
       o value = 63 =>  duty_cycle = 63 / ( 124+1 ) = 0.504 = 50.4%
       o value = 113 =>  duty_cycle = 113 / ( 124+1 ) = 0.904 = 90.4%

Code:
   setup_timer_2(T2_DIV_BY_4,124,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(30);

Sử dụng CCP1 và CCP2 cho động cơ trái và động cơ phải, ta có thể điều khiển được tốc độ của 2 động cơ phù hợp trạng thái lệch khỏi vạch trắng của robot.
 Các chương trình con tham khảo:
Để việc lập trình được dễ dàng, ta nên tạo các chương trình con xử lý tốc độ. Sau đây là chương trình tham khảo của hàm speed.
o Speed (tốc độ động cơ trái, tốc độ động cơ phải)
        Tốc độ: -100 đến 100 (chạy ngược 100% đến chạy thuận 100%)
        Ví dụ: speed(80,60) => động cơ trái chạy 80%, phải 60%
// Các hàm hỗ trợ
void left_motor_forward(int value)
{
   MOTOR_LEFT_DIR=0;
   setup_timer_2(T2_DIV_BY_4,124,1);         // Dieu xung 10kHz
   setup_ccp2(CCP_PWM);
   set_pwm2_duty(value);
}
void right_motor_forward(int value)
{
   MOTOR_RIGHT_DIR=0;
   setup_timer_2(T2_DIV_BY_4,124,1);         // Dieu xung 10kHz
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(value);
}
void left_motor_reverse(int value)
{
   MOTOR_LEFT_DIR=1;
   setup_timer_2(T2_DIV_BY_4,124,1);         // Dieu xung 10kHz
   setup_ccp2(CCP_PWM);
   set_pwm2_duty(value);
}
void right_motor_reverse(int value)
{
   MOTOR_RIGHT_DIR=1;
   setup_timer_2(T2_DIV_BY_4,124,1);         // Dieu xung 10kHz
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(value);
}
void left_motor_stop()
{
   setup_ccp1(CCP_OFF);
}
void right_motor_stop()
{
   setup_ccp1(CCP_OFF);
}
// Chương trình xử lý tốc độ 2 động cơ
// 0:Stop,100:FORWARD 100%,-100:Reverse 100%
void speed (signed int left_motor_speed, signed int right_motor_speed)
{
   int left_pwm_value=0,right_pwm_value=0;
   /* Left motor */
   if( left_motor_speed >= 0 )
   {
      left_pwm_value = 1.25*left_motor_speed;   // (125*left_motor_speed/100)
      left_motor_forward(left_pwm_value);
   }
   else
   {
      left_motor_speed = -left_motor_speed;
      left_pwm_value = 1.25*left_motor_speed;  // (125*left_motor_speed/100)
      left_motor_reverse(left_pwm_value);
 }
    /* Right motor */
   if( right_motor_speed >= 0 )
   {
      right_pwm_value = 1.25*right_motor_speed;   // (125*left_motor_speed/100)
      right_motor_forward(right_pwm_value);
   }
   else
   {
      right_motor_speed = -right_motor_speed;
      right_pwm_value = 1.25*right_motor_speed;  // (125*left_motor_speed/100)
      right_motor_reverse(right_pwm_value);
   }
}


3.2 Nhận biết vạch ngang
Trong quá trình di chuyển của robot, sẽ có các vạch ngang màu trắng. Nhờ các vạch ngang này, robot biết được mình đang đi đến đâu và sẽ thực hiện công việc gì tiếp theo (quay trái, quay phải, nâng hạ trục, gắp nhả quà,…)
Một cách đơn giản, khi robot đến vạch trắng, tất cả 8 cảm biến sẽ lên mức 1 ứng với giá trị đọc được của cảm biến là 0b11111111 hay 0xFF. Ta dùng một biến đếm để biết thứ tự của vạch ngang đang gặp và thực hiện công việc mong muốn.
Code:
int n // đặt n là số vạch ngang đã nhận
if (SENSOR==0xFF)
{
n++; // tăng giá trị n lên 1 khi gặp vạch ngang
switch (n)
{
case 1:    (công việc 1) break;
case 2:    (công việc 2) break;
….
case n:    (công việc n) break;
}
}
else (chương trình dò đường)

 Tuy nhiên, vì nhiều lý do khác nhau (nhiễu do ánh sáng bên ngoài, các cảm biến có độ nhạy không đều nhau hoặc robot tiếp cận với vạch ngang không theo phương vuông góc), một vài cảm biến khi tiếp xúc với màu trắng nhưng không nhận biết (vẫn giữ trạng thái mức 0 – màu sậm). Điều này gây khó khăn cho việc nhận biết vạch ngang. Vì vậy, khi 4/8 cảm biến ở mức 1, ta nhận đó là một vạch ngang để khắc phục các ảnh hưởng này.
Code:
//KIEM TRA VACH NGANG: 1: co vach, 0:khong co vach
int check_cross_line()
{
   int temp_sensor=0,led_in_line=0,i=0;
   temp_sensor=SENSOR;
   for (i=0;i<8;i++)
  {
   if ((temp_sensor&0x01)==0x01) led_in_line++;
      if (led_in_line==4) break;
      temp_sensor=temp_sensor>>1;
   }
   if (led_in_line==4)
      return 1;
   else
      return 0;
}

 Do chương trình nhận vạch ngang được gọi liên tục để kiểm tra có vạch ngang xuất hiện hay không nên sẽ dẫn đến tình trạng khi robot đến vạch ngang, biến đếm số vạch tăng thêm 1. Sau đó, khi robot chưa kịp chạy qua vạch ngang mà hàm kiểm tra được gọi dẫn đến việc biến đếm tăng liên tục.
Việc này khiến cho robot thực hiện sai công việc.
Hướng giải quyết tình huống này như sau:
       o Khi robot gặp vạch ngang: chạy thẳng
       o Khi hết vạch ngang: biến đếm số vạch tăng thêm 1
       o Thực hiện công việc tương ứng
Code:
while (check_cross_line() == 1) // gặp vạch ngang
{
speed(100,100); // chạy thẳng
}
number_cross_line++; // tăng biến đếm số vạch ngang thêm 1

3.3 Xử lý khi robot lệch hoàn toàn khỏi vạch
Trường hợp robot lệch ra khỏi vạch (quay quá mạnh hoặc bị va chạm), giá trị cảm biến đọc được là 0x00, như vậy robot sẽ bị mất phương hướng.
Để giải quyết trường hợp này, ta đặt một biến trạng thái là biến toàn cục.
Gọi biến này là line_status:
       o Line_status=0: giữa vạch;
       o Line_status=1: lệch trái;
       o Line_status=2: lệch phải;
Khi đọc giá trị cảm biến để dò đường , ta gán luôn giá trị cho biến này. Như vậy khi robot lệch hẳn ra khỏi vạch, ta vẫn biết được trạng thái trước đó để biết quay trái hoặc quay phải để hướng robot di chuyển về
phía line.
Code:
switch (SENSOR)
{
case 0b00000000: // lệch ra hẳn khỏi vạch
{
if (line_status==1) // trạng thái cũ là lệch trái
turn_right(); break; // quay phải để di chuyển về phía vạch
if (line_status==2) // trạng thái cũ là lệch phải
turn_left(); break; // quay trái để di chuyển về phía vạch
}
// Trạng thái lệch thông thường
case 0b00011000: forward(); line_status=0; break;
case 0b00001100: turn_left(); line_status=1; break;
case 0b00000110: turn_left(); line_status=1; break;
case 0b00000011: turn_left(); line_status=1; break;
case 0b00000001: turn_left(); line_status=1; break;
case 0b00110000: turn_right(); line_status=2 ;break;
case 0b01100000: turn_right(); line_status=2 ;break;
case 0b11000000: turn_right(); line_status=2 ;break;
case 0b10000000: turn_right(); line_status=2 ;break;
}

3.4 Ứng dụng encoder
3.4.1 Kiến thức cơ bản về encoder
Trong Robot, ta thường sử dụng incremental encoder (encoder tương đối) hay còn gọi là rotary encoder. Mục đích của việc sử dụng encoder trong robot là đếm số vòng quay để tính số vòng quay của động cơ (bánh xe), từ đó suy ra quãng đường di chuyển và tốc độ của robot.
Encoder thường được sử dụng trong Robot

3.4.2 Sử dụng PIC để nhận và đếm xung từ encoder
Để nhận xung từ encoder, ta có thể sử dụng ngắt ngoài, ngắt timer hoặc đơn giản là tham dò mức logic của các chân vi điều khiển một cách liên tục. Phần sau đây giới thiệu cách nhận và đếm xung của PIC16F877A dùng ngắt ngoài B0 (nối với kênh A của encoder) và chân B1 (nối với kênh B của encoder). Ta có thể làm tương tự đối với các cách nhận xung khác.
 Khởi tạo ngắt ngoài theo cạnh lên tại chân B0:
Code:
ext_int_edge(0,L_TO_H); // Ngắt cạnh lên tại RB0
enable_interrupts(INT_EXT); // Cho phép ngắt ngoài
enable_interrupts(GLOBAL); // Cho phép ngắt toàn cục
 Chương trình con phục vụ ngắt:
Code:
#int_EXT
void  EXT_isr(void) //Chương trình được gọi khi có tác động cạnh lên tại chân B0
{
   if (RB1==1) pulse++; // Nếu kênh B mức cao thì tăng giá trị xung thêm 1
   else pulse--;       // Nếu kênh B mức cao thì giảm giá trị xung xuống 1
}

 Từ giá trị xung tính được tại các thời điểm ta có thể tính ra các thông số mong muốn.

Phạm Văn Ngọc Anh- 01644326695


(Nguồn: Cao Hoàng Long, EM-BOT Robot Team)


Sơ lược về encoder:

Encoder mục đích dùng để quản lý vị trí góc của một đĩa quay, đĩa quay có thể là bánh xe, trục động cơ, hoặc bất kỳ thiết bị quay nào cần xác định vị trí góc.

Encoder được chia làm 2 loại, absolute encoder và incremental encoder. Tạm dịch là encoder tuyệt đối và encoder tương đối. Chữ encoder tuyệt đối dịch theo nguyên văn, nhưng vì tiếng Việt mình cái gì có 2 loại, thì loại còn lại được dịch ngược lại với loại kia. Cho nen dịch là encoder tương đối cho incremental encoder.

Nếu dịch sát nghĩa, khi ta đọc absolute encoder, có nghĩa là encoder tuyệt đối, tức là tín hiệu ta nhận được, chỉ rõ ràng vị trí của encoder, chúng ta không cần xử lý gì thêm, cũng biết chính xác vị trí của encoder.

Còn incremental encoder, là loại encoder chỉ có 1, 2, hoặc tối đa là 3 vòng lỗ. Các bạn hình dung thế này, nếu bây giờ các bạn đục một lỗ trên một cái đĩa quay, thì cứ mỗi lần đĩa quay 1 vòng, các bạn sẽ nhận được tín hiệu, và các bạn đã biết đĩa quay một vòng. Nếu bây giờ các bạn có nhiều lỗ hơn, các bạn sẽ có được thông tin chi tiết hơn, có nghĩa là đĩa quay 1/4 vong, 1/8 vòng, hoặc 1/n vòng, tùy theo số lỗ nằm trên incremental encoder.

Cứ mỗi lần đi qua một lỗ, chúng ta phải lập trình để thiết bị đo đếm lên 1. Do vậy, encoder loại này có tên incremental encoder (encoder tăng lên 1 đơn vị).




Nguyên lý hoạt động cơ bản của encoder, LED và lỗ:

Nguyên lý cơ bản của encoder, đó là một đĩa tròn xoay, quay quanh trục. Trên đĩa có các lỗ (rãnh). Người ta dùng một đèn led để chiếu lên mặt đĩa. Khi đĩa quay, chỗ không có lỗ (rãnh), đèn led không chiếu xuyên qua được, chỗ có lỗ (rãnh), đèn led sẽ chiếu xuyên qua. Khi đó, phía mặt bên kia của đĩa, người ta đặt một con mắt thu. Với các tín hiệu có, hoặc không có ánh sáng chiếu qua, người ta ghi nhận được đèn led có chiếu qua lỗ hay không.

Khi trục quay, giả sử trên đĩa chỉ có một lỗ duy nhất, cứ mỗi lần con mắt thu nhận được tín hiệu đèn led, thì có nghĩa là đĩa đã quay được một vòng.

Đây là nguyên lý rất cơ bản của encoder.

Tuy nhiên, những vấn đề được đặt ra là, làm sao để xác định chính xác hơn vị trí của đĩa quay (mịn hơn) và làm thế nào để xác định được đĩa đang quay theo chiều nào? Đó chính là vấn đề để chúng ta tìm hiểu về encoder.

Hình sau sẽ minh họa nguyên lý cơ bản của hoạt động encoder.




Các bạn thấy trong hình, có một đĩa mask, không quay, đó là đĩa cố định, thực ra là để che khe hẹp ánh sáng đi qua, giúp cho việc đọc encoder được chính xác hơn mà thôi. Chúng tôi không để cập đến đĩa mặt nạ này ở đây.


Hoạt động của hai loại encoder này như thế nào?

1) Absolute encoder

Vấn đề chúng ta sẽ quan tâm ở đây, chính là vấn đề về độ mịn của encoder, có nghĩa là làm thế nào biết đĩa đã quay 1/2 vòng, 1/4 vòng, 1/8 vòng hay 1/n vòng, chứ không phải chỉ biết đĩa đã quay được một vòng.

Quay lại bài toán cơ bản về bit và số bit, chúng ta xem xét vấn đề theo một cách hoàn toàn toán học nhé:

Với một số nhị phân có 2 chữ số, chúng ta sẽ có 00, 01, 10, 11, tức là 4 trạng thái. Điều đó có nghĩa là với 2 chữ số, chúng ta có thể chia đĩa encoder thành 4 phần bằng nhau. Và khi quay, chúng ta sẽ xác định được độ chính xác đến 1/4 vòng.

Tương tự như vậy, nếu với một số có n chữ số, chúng ta sẽ xác định được độ chính xác đến 1/(2^n) vòng.

Thế làm sao để xác định 2^n trạng thái này của đĩa encoder?

Các bạn xem hình sau:


Ở đây, tôi đưa ra ví dụ với đĩa encoder có 2 vòng đĩa. Các bạn sẽ thấy rằng, ở vòng trong cùng, có một rãnh rộng bằng 1/2 đĩa. Vòng phía ngoài, sẽ có 2 rãnh nằm đối diện nhau.

Như vậy, chúng ta cần 2 đèn led để phát xuyên qua 2 vòng lỗ, và 2 đèn thu.

Giả sử ở vòng lỗ thứ nhất (trong cùng), đèn đọc đang nằm ở vị trí có lỗ hở, thì tín hiệu nhận được từ con mắt thu sẽ là 1. Và ở vòng lỗ thứ hai, thì chúng ta đang ở vị trí không có lỗ, như vậy con mắt thu vòng 2 sẽ đọc được giá trị 0.

Và như vậy, với số 10, chúng ta xác định được encoder đang nằm ở góc phần tư nào, cũng có nghĩa là chúng ta quản lý được độ chính xác của đĩa quay đến 1/4 vòng. Trong ví dụ trên, nếu đèn LED đọc được 10, thì vị trí của LED phải nằm trong góc phần tư thứ hai, phía trên, bên trái.

Kết quả, nếu đĩa encoder có đến 10 vòng lỗ, thì chúng ta sẽ quản lý được đến 1/(2^10) tức là đến 1/1024 vòng. Hay người ta nói là độ phân giải của encoder là 1024 xung trên vòng (pulse per revolution - ppr).

Sau đây là ví dụ abosulte encoder 8 vòng lỗ:


Vậy cách thiết kế absolute encoder như thế nào?

Các bạn luôn chú ý rằng, để thiết kế encoder tuyệt đối, người ta luôn vẽ sao cho bit thứ N (đối với encoder có N vòng lỗ) nằm ở trong cùng, có nghĩa là lỗ lớn nhất có góc rộng 180 độ, nằm trong cùng. Bởi vì chúng ta thấy rằng, bit0 (nếu xem là số nhị phân) sẽ thay đổi liên tục mỗi 1/2^N vòng quay, vì thế, chúng ta cần rất nhiều lỗ. Nếu đặt ở trong thì không thể nào vẽ được, vì ở trong bán kính nhỏ hơn. Ngoài ra, nếu đặt ở trong, thì về kết cấu cơ khí, nó quá gần trục, và quá nhiều lỗ, sẽ rất yếu. Vì hai điểm này, nên bit0 luôn đặt ở ngoài cùng, và bitN-1 luôn đặt trong cùng như hình trên.

Rất nhiều người thắc mắc về cách thực tế để vẽ encoder như thế nào. Tuy nhiên, kể từ khi có Chương trình thiết kế Encoder 
này, tôi cho rằng chúng ta không nên quan tâm đến vấn đề đó nữa. Chỉ cần hiểu nó hoạt động ra sao, rồi sau đó chúng ta dùng chương trình này để vẽ.

Khi nhấn nút "Tải Về Máy", bạn sẽ vào trang quảng cáo, vui lòng chờ 5 giây. Nút hiện ra ở góc phải phía trên, nhấn vào để đến trang download


2) Incremental encoder

Nhận thấy một điều rằng, encoder tuyệt đối rất có lợi cho những trường hợp khi góc quay là nhỏ, và động cơ không quay nhiều vòng. Khi đó, việc xử lý encoder tuyệt đối trở nên dễ dàng cho người dùng hơn, vì chỉ cần đọc giá trị là chúng ta biết ngay được vị trí góc của trục quay.

Tuy nhiên, nếu động cơ quay nhiều vòng, điều này không có lợi, bởi vì khi đó, chúng ta phải xử lý để đếm số vòng quay của trục.

Ngoài ra, như các bạn thấy đó, nếu thiết kế encoder tuyệt đối, chúng ta cần quá nhiều vòng lỗ, và dẫn tới giới hạn về kích thước của encoder, bởi vì việc gia công chính xác các lỗ quá nhỏ là không thể thực hiện được. Chưa kể rằng việc thiết kế một dãy đèn led và con mắt thu cũng ảnh hưởng rất lớn đến kích thước giới hạn này.

Theo kinh nghiệm của cá nhân tôi, tôi thấy encoder 8 bit là đã rất chi tiết rồi, và ở trường DHBKHCM có loại encoder 12bit đã là loại tốt nhất mà tôi biết. Tôi chưa thấy loại encoder tuyệt đối nào 16 bit cả, và cũng không có ý định tìm nó trên internet.

Độ chính xác của encoder 12 bit đã là 1/4096 rồi.

Tuy nhiên, điều này được khắc phục bằng incremental encoder một cách khá đơn giản. Chính vì vậy, ngày nay, đa số người ta sử dụng incremental encoder trong những ứng dụng hiện đại.

Thật đơn giản, incremental encoder, sẽ tăng 1 đơn vị khi một lần lên xuống của cạnh xung.
Các bạn xem hình encoder sau:




Các bạn thấy rằng, cứ mỗi lần quay qua một lỗ, thì encoder sẽ tăng một đơn vị trong biến đếm.

Tuy nhiên, một vấn đề là làm sao để biết được encoder quay hết một vòng? Nếu cứ đếm vô hạn như thế này, thì chúng ta không thể biết được khi nào nó quay hết một vòng. Nếu bây giờ các bạn đếm số lỗ encoder để biết nó đã quay một vòng, thì nếu với encoder 1000 lỗ chắc các bạn sẽ đếm đến sáng luôn.

Chưa kể, mỗi lần có những rung động nào đó mà ta không quản lý được, encoder sẽ bị sai một xung. Khi đó, nếu hoạt động lâu dài, sai số này sẽ tích lũy, ngày hôm nay sai một xung, ngày hôm sau sai một xung. Đến cuối cùng, có thể động cơ quay 2 vòng rồi các bạn mới đếm được 1 vòng.

Để tránh điều tai hại này xảy ra, người ta đưa vào thêm một lỗ định vị để đếm số vòng đã quay của encoder.

Như vậy, cho dù có lệch xung, mà chúng ta thấy rằng encoder đi ngang qua lỗ định vị này, thì chúng ta sẽ biết là encoder đã bị đếm sai ở đâu đó. Nếu vì một rung động nào đó, mà chúng ta không thấy encoder đi qua lỗ định vị, vậy thì từ số xung, và việc đi qua lỗ định vị, chúng ta sẽ biết rõ hiện tượng sai của encoder.

Đây là hình encoder có lỗ định vị:


Tuy nhiên, một vấn đề lớn nữa là, làm sao chúng ta biết encoder đang xoay theo chiều nào? Bởi vì cho dù xoay theo chiều nào, thì tín hiệu encoder cũng chỉ là các xung đơn lẻ và xoay theo hai chiều đều giống nhau.

Chính vì vậy, người ta đặt thêm một vòng lỗ ở giữa vòng lỗ thứ 1 và lỗ định vị như hình sau: 


Chú ý rằng, vị trí góc của các lỗ vòng 1 và các lỗ vòng 2 lệch nhau. Các cạnh của lỗ vòng 2 nằm ngay giữa các lỗ vòng 1 và ngược lại.

Chúng ta sẽ khảo sát tiếp vấn đề encoder trong phần tín hiệu xung để hiểu rõ hơn về encoder. Tuy nhiên, các bạn sẽ thấy một điều rằng, thay vì làm 2 vòng encoder, và dùng 2 đèn LED đặt thẳng hàng, thì người ta chỉ cần làm 1 vòng lỗ, và đặt hai đèn LED lệch nhau.

Kết quả, các bạn sẽ thường thấy các encoder có dạng:

                                                       
Đây là dạng encoder phổ biến nhất hiện nay.


Tín hiệu xung:


Hình trên là hình xung incremental encoder.

Các bạn thấy rằng nếu như khi xung A đang từ mức cao xuống mức thấp, mà lúc đó B đang ở mức thấp, thì chúng ta sẽ xác định được chiều chuyển động của encoder theo chiều mũi tên màu cam.

Nếu A đang từ mức cao xuống mức thấp, mà B đang ở mức cao, thì chúng ta sẽ biết encoder đang quay theo chiều màu nâu.

Phạm Văn Ngọc Anh- 01644326695



(Nguồn: falleaf)

Author Name

{picture https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN0PUWA2genMqX3Sm26mBTX_30OJgDenoIi4K6BR-E1vl3nI7LALp0X759QZgzqrMcGBB7jEbdZnubJbp4n2ZZ22KT196CWCg9DLs3MfEivocdmkjZEPEn-A42hyphenhyphen9dmsca0VIDQr_LjqM/s512-Ic42/pham-van-ngoc-anh.jpg}

Tôi là Ngọc Anh. Tôi đến từ Nghệ An. Tôi tốt nghiệp một trường đại học tại Sài Gòn. Hiện tôi đang phát triển công ty riêng. Liên lạc với tôi qua:

{facebook https://www.facebook.com/phamvanngocanh}
{twitter https://twitter.com/nghiphong1993}
{google https://plus.google.com/+dientuchiase/posts}
{youtube https://www.youtube.com/channel/UCeJKhA_goBNFmDw6RKNtmYQ}

Biểu mẫu liên hệ

Tên

Email *

Thông báo *

Được tạo bởi Blogger.