You are on page 1of 14

Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

LẬP TRÌNH ROBOT TỰ ĐỘNG ĐƠN GIẢN


VỚI VI ĐIỀU KHIỂN PIC16F877A
Cao Hoàng Long, EM-BOT Robot Team
chlong.mechatronics@gmail.com ; embot.robocon@gmail.com
Khoa Công nghệ, Đại học Cần Thơ
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 (nâng hạ, gắp nhả quà) 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.

Hình 1: Mô hình robot dò dường đơn giản


1.2 Mạch điện tử

Hình 2: Sơ đồ hoạt động của robot tự động

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 1/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

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) cho
phù 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ác
nguồn ánh sáng bên ngoài.
5V
R4 100K
VCC
VCC

R R2
1
330 33K
3 + U1A R3
1 CAMBIEN 10K
2 - 1 CTHT

LM324
D2 D3
LED QUANG TRO
Vạch trắng: mức 1 C1 SW2
BIT0
104
Nền: mức 0

Hình 3: 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.
RESET 1 33 RB0
MCLR*/VPP RB0/INT 34 RB1
RA0 2 RB1 35 RB2
RA1 3 RA0/AN0 RB2 36 RB3
RA2 4 RA1/AN1 RB3/PGM 37 RB4
RA3 5 RA2/AN2/VREF-/CVREF RB4 38 RB5
RA4 6 RA3/AN3/VREF+ RB5 39 RB6
RA5 7 RA4/T0CKI/C1OUT RB6/PGC 40 RB7
RA5/AN4/SS*/C2OUT RB7/PGD
RC0 15 19 RD0
RC1 16 RC0/T1OSO/T1CKI RD0/PSP0 20 RD1
RC2 17 RC1/T1OSI/CCP2 RD1/PSP1 21 RD2
RC3 18 RC2/CCP1 RD2/PSP2 22 RD3
RC4 23 RC3/SCK/SCL RD3/PSP3 27 RD4
RC5 24 RC4/SDI/SDA RD4/PSP4 28 RD5
RC6 25 RC5/SDO RD5/PSP5 29 RD6
RC7 26 RC6/TX/CK RD6/PSP6 30 RD7
C5 30p RC7/RX/DT RD7/PSP7
13
OSC1/CLKIN 8 RE0
Y1 RE0/RD*/AN5 9 RE1
CRY STAL RE1/WR*/AN6 10 RE2
14 RE2/CS*/AN7
OSC2/CLKOUT 5V
C6 30p 12 11
31 VSS VDD 32
VSS VDD
PIC16F877A

MCU MODULE
Hình 4: 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:

P-DIR2

LS2
12V D13
RELAY
D12 M2 8
1N5819 Q4 IRF540 1 MOTOR2
D468 5
D14 6 1N5819 1
P-PWM2 1N5819 24V 7 2
4 C2
Q5 R12 3 104
B562 330 2W 2 CON2

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 2/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

Hình 5: Mạch công suất sử dụng 1 FET và 1 relay


12V

D1 D2

DIODE DIODE
U3
U4
5 8
VCC VB 5 8
C1 VCC VB
IN1 1 7 + C2
IN HO IN2 1 7 + C3 C4
4.7u 100n IN HO
2 6 4.7u 100n
C5 + SD VS 2 6
4.7u SD VS
C6 3 4
100n COM LO 3 4
COM LO
24V

IR 2184
IR2184

Q1
R4 4.7R R5 Q2
IRF540 IRF540
4.7R
J1

1
C14 2
104

C7 + C8 MOTOR
470n Q3 470u
R6 4.7R Q4
R7
IRF540 IRF540
4.7R

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

Phần hướng dẫn chi tiết về mạch điện tử 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.

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 3/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

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: http://www.mediafire.com/?hd2ugmmzvwf
 Hướng dẫn lập trình PIC-DKS:http://www.mediafire.com/?e0ioxeideyx
 Giáo trình PIC (ĐH Reading): http://www.mediafire.com/?iyewnoldyjk
 Lập trình C cho PIC 8bit: http://www.mediafire.com/?tnjlztmmzdm
 CCS Manual (tra cứu lệnh): http://www.mediafire.com/?htljg1jg2mn
Đâ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ơ

Trạng thái DIRECTION ENABLE


Thuận 1 1
Ngược 0 1
Dừng x 0

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

Trạng thái Động cơ trái Động cơ phải


Thẳng Thuận Thuận
Quay trái Thuận Ngược (Dừng)
Quay phải Ngược (Dừng) Thuận

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 4/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

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

7 6 5 4 3 2 1 0 Trạng thái cảm


biến
Giữa vạch
0 0 0 1 1 0 0 0
Lệch trái mức 1
0 0 0 0 1 1 0 0
Lệch trái mức 2
0 0 0 0 0 1 1 0
Lệch trái mức 3
0 0 0 0 0 0 1 1
Lệch trái mức 4
0 0 0 0 0 0 0 1
Ngoài vạch
0 0 0 0 0 0 0 0
Lệch phải mức 1
0 0 1 1 0 0 0 0
Lệch phải mức 2
0 1 1 0 0 0 0 0
Lệch phải mức 3
1 1 0 0 0 0 0 0
Lệch phải mức 4
1 0 0 0 0 0 0 0
Ngoài vạch
0 0 0 0 0 0 0 0

Hình 7: 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

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 5/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

#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()

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 6/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

{
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;
}
}
}

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 7/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

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 (xem lại hình 7):

Trạng thái Tốc độ động cơ trái Tốc độ động cơ phải


Giữa vạch 100% 100%
Lệch trái mức 1 90% 80%
Lệch trái mức 2 80% 70%
Lệch trái mức 3 70% 60%
Lệch trái mức 4 60% 50%
Lệch phải mức 1 80% 90%
Lệch phải mức 2 70% 80%
Lệch phải mức 3 60% 70%
Lệch phải mức 4 50% 60%
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 biến độ 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
Ton
duty _ cycle 
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à
1 1 1
f     1kHz
Ton  Toff 0.8ms  0.2ms 1ms

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 8/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

Ton 0 .8
duty _ cycle    0.8  80%
Ton  Toff 0.8  0.2
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.

Hình 8: 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) và 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

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 9/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

f osc
 Tần số điều xung PWM: f 
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:
value
duty _ cycle 
period  1
 Nếu value là giá trị long int 16bit:
value & 1023
duty _ cycle 
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 osc 20000000
f   10000   mode(period  1)  500
4.mode.(period  1) 4.mode.(period  1)
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.
30
o value = 30  duty _ cycle   0.32  32%
124  1
63
o value = 63  duty _ cycle   0.504  50,4%
124  1
113
o value = 113  duty _ cycle   0.904  90,4%
124  1
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%

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 10/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

// 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);

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 11/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

}
/* 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++)
{

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 12/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

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 (tham khảo hình 7), 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;

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 13/14


Lập trình Robot tự động đơn giản với PIC16F877A Biên soạn: EM-BOT Robot Team

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
Tham khảo tại diễn đàn PICVietnam:
http://www.picvietnam.com/forum/showthread.php?p=1062#post1062
Trong Robocon, 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.

Hình 10: Encoder thường được sử dụng trong Robocon


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.

© http://em-bot.tk (Feb 2010) DEMO VERSION Trang 14/14

You might also like