1. Trang chủ
  2. » Kỹ Thuật - Công Nghệ

Lập trình robot tự động đơn giản với vđk PIC16F877A

20 1,8K 30

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 20
Dung lượng 0,95 MB

Nội dung

Lập Trình RoBot Tự Động Đơn Giản Với VĐK PIC16F877ATó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

Trang 1

Lập Trình RoBot Tự Động Đơn Giản Với VĐK PIC16F877A

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

Trang 2

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

Trang 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

Trang 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:

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

Trang 5

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,…

Trang 6

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

Trang 7

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

Trang 8

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

{

Trang 9

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

Trang 10

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;

Trang 11

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.

Trang 12

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

Trang 13

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

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

Trang 14

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

}

Trang 15

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

}

Trang 16

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)

{

Trang 17

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;

}

Trang 18

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

Ngày đăng: 27/05/2014, 23:42

HÌNH ẢNH LIÊN QUAN

Sơ đồ hoạt động của robot tự động - Lập trình robot tự động đơn giản với vđk PIC16F877A
Sơ đồ ho ạt động của robot tự động (Trang 2)

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w