PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Cơ bản về vi điều khiển và PIC (http://www.picvietnam.com/forum/forumdisplay.php?f=8)
-   -   XIn các bạn chỉ giúp mình module QEI trong 18f4431 (http://www.picvietnam.com/forum/showthread.php?t=3802)

vagabondtt1503 30-03-2009 07:24 PM

XIn các bạn chỉ giúp mình module QEI trong 18f4431
 
Mình muốn dùng QEI đọc encoder x 4 để thưc hiện bộ điều khiển PID nhưng mình chưa hiểu cách cấu hình trong CCS như thế nào,bạn nào làm rồi có thể cho mình xin ít kinh nghiệm được không?nếu được có thể share code cho mình không?

Mình có tìm các thread trong diễn đàn nhưng vẫn không tự làm được

cảm ơn sự giúp đỡ của mọi người

cong1810 30-03-2009 07:34 PM

thật may vì cũng có người đang hỏi về QEI.
các anh cho em hỏi luôn!
em định dùng QEI ở chế độ x2 để đo tốc độ động cơ.
cách hoạt động và các chân thì em đọc datasheet, em có nắm được!
vấn đề của em là em chưa biết cách nào để lấy số xung ra?
nếu set timer 5 làm bộ đếm thì lại phải mất thêm 1 timer nữa để lấy mẫu thời gian.
nếu em dùng ngắt ở chế độ period - match ( em ko muốn dùng chân indx) và dùng timer 5 lấy mẫu thời gian thì em nghĩ phải set cho thanh ghi MAXCNT là 0xffff.Nhưng em vẫn chưa thấy ổn lắm.
các anh tư vấn thêm giúp em với!!
chúc mọi ngưởi luôn vui khỏe!!

vagabondtt1503 30-03-2009 10:49 PM

Trích:

Nguyên văn bởi cong1810 (Post 24161)
thật may vì cũng có người đang hỏi về QEI.
các anh cho em hỏi luôn!
em định dùng QEI ở chế độ x2 để đo tốc độ động cơ.
cách hoạt động và các chân thì em đọc datasheet, em có nắm được!
vấn đề của em là em chưa biết cách nào để lấy số xung ra?
nếu set timer 5 làm bộ đếm thì lại phải mất thêm 1 timer nữa để lấy mẫu thời gian.
nếu em dùng ngắt ở chế độ period - match ( em ko muốn dùng chân indx) và dùng timer 5 lấy mẫu thời gian thì em nghĩ phải set cho thanh ghi MAXCNT là 0xffff.Nhưng em vẫn chưa thấy ổn lắm.
các anh tư vấn thêm giúp em với!!
chúc mọi ngưởi luôn vui khỏe!!

bạn biết cách khởi động ban đầu cho bộ QEI không? giúp mình với

cong1810 30-03-2009 11:56 PM

hix! em vẫn đang mày mò và quan trọng là vẫn chưa làm được.anh thử đọc phần 16.2 trong datasheet xem có giúp ích gì ko. em cũng đang đọc nó. cứ đọc đi đọc lại rồi thử từng ứng dụng nhỏ một. mỗi lần đọc lại thấy thấm 1 tí. xin lỗi.em chưa giúp được huynh!!

sandro_bk 31-03-2009 08:37 AM

đây là đoạn chương trình khởi tạo và đọc QEI,các bác xem tham khảo,khi đọc encoder thường sử dụng chế độ đọc xung khi ở tốc độ cao,còn đọc theo kiểu capture thời gian sử dụng Timer5 chỉ nên dùng ở tốc độ thấp.

#byte QEICON=0xFB6
#byte POSCNTH=0xF67
#byte POSCNTL=0xF66
#byte MAXCNTH=0xF65
#byte MAXCNTL=0xF64

int16 Read_QEI() //doc QEI
{
int16 tmp=0;
tmp = make16(POSCNTH, POSCNTL);
POSCNTH = 0x3F;
POSCNTL = 0xFF;
return tmp;
}

void Init_QEI() //khoi tao QEI
{
set_tris_A(0xFF);
MAXCNTL=0xFF;
MAXCNTH=0xFF;
POSCNTH = 0x3F;
POSCNTL = 0xFF;
QEICON = 0b10111000;
}

cong1810 31-03-2009 12:36 PM

Trích:

Nguyên văn bởi sandro_bk (Post 24183)
đây là đoạn chương trình khởi tạo và đọc QEI,các bác xem tham khảo,khi đọc encoder thường sử dụng chế độ đọc xung khi ở tốc độ cao,còn đọc theo kiểu capture thời gian sử dụng Timer5 chỉ nên dùng ở tốc độ thấp.

#byte QEICON=0xFB6
#byte POSCNTH=0xF67
#byte POSCNTL=0xF66
#byte MAXCNTH=0xF65
#byte MAXCNTL=0xF64

int16 Read_QEI() //doc QEI
{
int16 tmp=0;
tmp = make16(POSCNTH, POSCNTL);
POSCNTH = 0x3F;
POSCNTL = 0xFF;
return tmp;
}

void Init_QEI() //khoi tao QEI
{
set_tris_A(0xFF);
MAXCNTL=0xFF;
MAXCNTH=0xFF;
POSCNTH = 0x3F;
POSCNTL = 0xFF;
QEICON = 0b10111000;
}

anh cho em hỏi. với đoạn chương trình trên nếu em muốn tính tốc độ của nó thì vẫn phài cần 1 timer để đến thời gian. khi mà POSCNT= MAXCNT.có phải anh dùng cờ ngắt để nhảy đến đoạn read_qei.nhưng như thế đâu biết thời gian bao nhiêu. trước đến h em cứ nghĩ tính vận tốc thì phải lấy mẫu thời gian rồi mới đọc xung.ko biết có ngược lại được ko.tức là lấy đủ xung rồi tính thời gian.nhưng như vậy ko hợp lý!! em chưa rõ mong anh chỉ giáo.
chúc anh luôn vui khỏe!!

sandro_bk 31-03-2009 12:59 PM

Mình thường làm như sau.Dùng 1 cái timer để tạo pwm,(chẳng hạn xuất xung 5khz)thời gian đó cũng chính là chu kỳ lấy mẩu số xung encoder,cứ ngắt pwm xảy ra là lấy mẩu encoder tính ra tốc độ rồi,đó là cách đọc encoder ở tốc độ cao,tức là khi động cơ quay nhanh,
còn ở tốc độ thấp tức là khi động cơ quay chậm thì có thể dùng cách đo thời gian của 1 xung encoder,cho nên người ta mới cung cấp timer5 chung với module encoder cho mình dùng chức năng capture,

vagabondtt1503 31-03-2009 01:19 PM

Trích:

Nguyên văn bởi sandro_bk (Post 24189)
Mình thường làm như sau.Dùng 1 cái timer để tạo pwm,(chẳng hạn xuất xung 5khz)thời gian đó cũng chính là chu kỳ lấy mẩu số xung encoder,cứ ngắt pwm xảy ra là lấy mẩu encoder tính ra tốc độ rồi,đó là cách đọc encoder ở tốc độ cao,tức là khi động cơ quay nhanh,
còn ở tốc độ thấp tức là khi động cơ quay chậm thì có thể dùng cách đo thời gian của 1 xung encoder,cho nên người ta mới cung cấp timer5 chung với module encoder cho mình dùng chức năng capture,

mình sử dụng hàm Read_QEI() của bạn viết sau đó đưa pha A và B vào 2 chân QEA và QEB của vi đièu khiển,sau đó lấy giá trị trả về của hàm Read_QEI() xuất LCD trong vòng while,nhưng giá trị xuất ra rất khó hiểu,hinh như không phải tính xung đưa vào 2 chân QEA và QEB.

Mong bạn chỉ bảo giúp

sandro_bk 31-03-2009 05:57 PM

hàm read_QEI() trả giá trị 16 bit về nên bạn dùng như sau:
int16 a;
a = read_QEI();

bạn thử xem

cong1810 01-04-2009 04:50 PM

Trích:

Nguyên văn bởi sandro_bk (Post 24189)
Mình thường làm như sau.Dùng 1 cái timer để tạo pwm,(chẳng hạn xuất xung 5khz)thời gian đó cũng chính là chu kỳ lấy mẩu số xung encoder,cứ ngắt pwm xảy ra là lấy mẩu encoder tính ra tốc độ rồi,đó là cách đọc encoder ở tốc độ cao,tức là khi động cơ quay nhanh,
còn ở tốc độ thấp tức là khi động cơ quay chậm thì có thể dùng cách đo thời gian của 1 xung encoder,cho nên người ta mới cung cấp timer5 chung với module encoder cho mình dùng chức năng capture,

em hỏi thêm chỗ này!
tại sao anh lại đặt POSCNT=3fff vậy! bởi em nghĩ nếu đặt là 0 thì lúc tính toán mình ko cần trừ đi 3fff? ko biết em hiểu vậy có đúng ko nhỉ!

sandro_bk 01-04-2009 08:16 PM

bạn đặt câu hỏi rất đúng,vì module QEI có thể đếm lên hay đếm xuống tùy theo chiều của xung A,B(bạn xem thêm trong datasheet),đặt giá trị đó là giá trị chính giữa của bộ đếm 16bit 0xffff,sẽ ko sợ bị tràn khi đo tốc độ,thực tế với tốc độ lấy mẫu 200us mình hay dùng chắc chắn chẳng bao giờ tràn cả,
Thân

cong1810 01-04-2009 11:30 PM

.em có dùng thêm cả bộ filter trong pic mà sao QEI của em vẫn nhiễu kinh khủng.em dùng LCD để hiển thị nó thì chưa lần nào đúng cả.nhưng nếu dùng ngắt ngoài thì lại chính xác.
em đang thử đo xung tốc độ chậm thôi.do em đang thử nghiệm với nút nhấn và xoay tay để đo tốc độ thằng động cơ brushless sau này .nên em dùng chế độ x2 để đọc.
mong anh chỉ giáo!!

sandro_bk 02-04-2009 12:37 PM

mình chưa gặp hiện tượng này bao giờ,bạn có thể post code lên,biết đâu có ai đó có thể giúp bạn,
Cùng nhau học tập,ko dám chỉ giáo,
Thân

cong1810 02-04-2009 05:25 PM

Code:

#include <18f4431.h>
#include <def_4431.h>
#fuses  XT,NOWDT,NOPROTECT,NOLVP//,NOBROWNOUT,NOPUT,NOCPD,NODEBUG,NOFCMEN,NOCPB,NOPWMPIN,STVREN
#use delay(clock=4000000)
#use fast_io(a)
#use fast_io(d)
#use fast_io(c)
#use fast_io(e)
#include <lcd.c>
#define use_portd_lcd true

int16 duty_cycle0=0;
int16 velocity=0;
int16 dem=0;
void display_lcd();
void Read_QEI(); //doc QEI
 
#INT_PWMTB
void interrupt_pwmtb()

  dem++;
  if(dem==3000)
  {dem=0;
  Read_QEI();
  }
  }

void main()
{
set_tris_b(0);    // port B la xuat
portb=0;
set_tris_c(0);
portc=0xff;
set_tris_d(0);
portd=0;
set_tris_a(0xff);
porta=0xff;

//setup LCD
lcd_init();
display_lcd();

//setup power PWM
PTCON1=0b10000000;  // dung che do ngat time base
SETUP_POWER_PWM(PWM_CLOCK_DIV_64|PWM_FREE_RUN,1,0,1249,0,1,0);//5khz hay chu ki là 200ms
SETUP_POWER_PWM_PINS(PWM_COMPLEMENTARY,PWM_COMPLEMENTARY,PWM_OFF,PWM_OFF);
SET_POWER_PWM0_DUTY(0);
duty_cycle0=250;

//setup QEI
MAXCNTL=0xFF;
MAXCNTH=0xFF;
POSCNTH = 0x00;
POSCNTL = 0x00;
QEICON = 0b10101000;
DFLTCON =  0b00010011;//filter tren chan QEA clock devider 1:16

//interrupts
enable_interrupts(INT_PWMTB);
enable_interrupts(global);

while(1)
{
display_lcd();
SET_POWER_PWM0_DUTY(duty_cycle0);
SET_POWER_PWM2_DUTY(duty_cycle0);
if(RC1==0)
  {
      delay_ms(50);
      if(RC1==0)
        {

            if(duty_cycle0==500)duty_cycle0=500;
            else duty_cycle0=duty_cycle0+5;
        }
     
  }
if(RC2==0)
  {
      delay_ms(50);
      if(RC2==0)
        {

            if(duty_cycle0==250)duty_cycle0=250;
            else duty_cycle0=duty_cycle0-5;
        }
     
  }
}

}
void display_lcd()
{
lcd_gotoxy(1,1);
printf(lcd_putc,"duty=%lu",duty_cycle0);
lcd_gotoxy(10,1);
printf(lcd_putc,"%lu",dem);
lcd_gotoxy(1,2);
printf(lcd_putc,"V=%lu",velocity/2);
}
void Read_QEI() //doc QEI
{
velocity = make16(POSCNTH,POSCNTL);
POSCNTH = 0x0;
POSCNTL = 0x0;
}

đây là đoạn code em dùng để test thử.mục đích ban đầu chỉ là muốn tính và hiển thị số xung trên chân QÉA.
khi em để hở chân này.giá trị hiển thị rất lớn cỡ mấy chục ngàn.khi em cho nó xuống mass thì có trở về 0 nhưng chỉ cần rung jump 1 tí là lại nhảy lên.
em nối nó vào 1 nút nhấn có điện trở kéo nguồn .nhấn thì xuống mass còn bình thường thì đo là 5v.nó cũng ko chính xác tí nào.nhưng nếu em đổi dùng ngắt ngoài thì chính xác.
em nghĩ do phần cứng nhiều hơn.anh xem giúp em nhé!!

tien168bn 20-03-2013 09:19 PM

Mọi người cho em hỏi cái này ngoài lề một xíu:
SETUP_POWER_PWM(PWM_CLOCK_DIV_64|PWM_FREE_RUN,1,0, 1249,0,1,0);//5khz hay chu ki là 200ms
Em muốn hỏi là cái này tình toán làm sao ra được 5kHz vậy ạ, e mới tìm hiểu về pic nên còn nhiều thứ muốn biết lắm ạ. cảm ơn mọi người


Múi giờ GMT. Hiện tại là 10:59 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam