PDA

View Full Version : Giúp đỡ - bị nhiễu xung encoder


vietlong04
15-03-2010, 06:36 PM
Chào các bạn, mình đã biết đến diễn đàn picvn này từ lâu nhưng giờ mới có việc thực sự rất cần ý kiến trao đổi của các bạn. Mình dùng Pic 18f4331(sơ đồ mạch http://www.mediafire.com/?mjmjm5w3myv ) lập trình điều khiển động cơ và dùng encoder để đo nhưng không hiểu sao nếu không có động cơ mắc vào chân PWM thì chương trình đếm xung rất tốt con nếu có động cơ thì tự động thực hiện chương trình. Ví dụ chương trình đơn giản của mình. Viết bằng CCS

mình dùng encoder 100 xung 2 sign 2 nguồn, động cơ kéo kính hoặc 3000vong (nói chung động cơ nào dùng cũng bị nhiễu)

#include <18f4550.h>

#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWDT

#use delay(clock=20000000)

#use fast_io(b)
#use fast_io(c)
#use fast_io(a)
#use fast_io(d)
#use fast_io(e)

int1 flag_ngat1=0,flag_ngat2=0,ngat1=0,ngat2=0;
int16 signA,signB,en_t,en_p;
int8 en;
/**************************************/

#int_ext1 //dem xung encoder banh trai
void ngat_int1()
{
disable_interrupts(int_ext1);
signA++;
if ((signA >= en_t)&&(flag_ngat1 == 0))
{
ngat1 = 1;
flag_ngat1 = 1;
signA = 0;
}
enable_interrupts(int_ext1) ;
}

#int_ext2 //dem xung encoder banh phai
void ngat_int2()
{
disable_interrupts(int_ext2);
signB ++;
if ((signB >= en_p)&&(flag_ngat2 == 0))
{

ngat2 = 1;
flag_ngat2 = 1;
signB = 0;
}
enable_interrupts(int_ext2) ;
}

/**************************************/
void main(){

set_tris_A(0xB1); // pin A7 -> pin A0 1011 0001
set_tris_B(0xC0); // pin B7 -> pin B0 1100 0000
set_tris_C(0x39); // pin C7 -> pin C0 0011 1001
set_tris_D(0x03); // pin D7 -> pin D0 0000 0011
set_tris_E(111);

setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);


setup_timer_0( RTCC_INTERNAL| RTCC_DIV_256 | RTCC_8_BIT);
setup_timer_2(T2_DIV_BY_16, 255, 1);

/* setup_power_pwm_pins(PWM_BOTH_ON,PWM_BOTH_ON,PWM_O FF,PWM_OFF);
setup_power_pwm(PWM_CLOCK_DIV_128|PWM_FREE_RUN,
1, //postscale, not used
0, //initial PTMR
63, //**************PTPER9 //
0, //compare special event, not used
1, //postscale compare special event, not used
0); //dead_time
set_power_pwm_override(1, false, 0);
set_power_pwm_override(3, false, 0);
set_power_pwm_override(5, false, 0);
set_power_pwm_override(7, false, 0);*/ // su dung mode PWM cua 18f4331

enable_interrupts(int_ext1);
enable_interrupts(int_ext2);
ext_int_edge(1, L_TO_H );
ext_int_edge(2, L_TO_H );
enable_interrupts(GLOBAL);

output_high(PIN_B0);
output_high(PIN_B1);
output_high(PIN_B2);
output_high(PIN_B3);
output_high(PIN_B4);
output_high(PIN_B5);

output_high(PIN_D2);
output_high(PIN_D3);
output_high(PIN_D4);
output_high(PIN_D5);
output_high(PIN_D6);
output_high(PIN_D7);

output_high(PIN_C6);
output_high(PIN_C7);

set_pwm1_duty(255); //đưa full áp trên chân CCP1
set_pwm2_duty(255); //đưa full áp trên chân CCP2

signA=0
while(true){
if(signA>100) output_low(PIN_B0); //nếu quay 1 vòng en thì đèn nói chân B0 ra sẽ sáng
if(signA>200) output_low(PIN_B1); //nếu quay 1 vòng en thì đèn nói chân B1 ra sẽ sáng
if(signA>300) output_low(PIN_B2); //nếu quay 1 vòng en thì đèn nói chân B2 ra sẽ sáng
if(signA>400) output_low(PIN_B3); //nếu quay 1 vòng en thì đèn nói chân B3 ra sẽ sáng
if(signA>500) output_low(PIN_B4); //nếu quay 1 vòng en thì đèn nói chân B4 ra sẽ sáng
}

}

nếu không bắt động cơ vào thì mình quay encoder thấy nó thực hiện chương trình rất đúng,còn nếu có động cơ vào chạy thì chẳng cần quay encoder chương trình vẫn tự động thực hiện @@ ( Đã nối tụ giữa 2 đầu động cơ, diot từ chân pwm đến dương nguồn, nguồn nuôi pic khác với nguồn nuôi động lực)

Mình lên mạng dò hỏi thì biết nếu dùng pic 18f4331 thì nên dùng mode QEI mà đọc encoder khổ nổi lại không biết config nó = CCS

betabeta
18-04-2010, 12:33 PM
Mình tìm được cái này trên mạng, thấy dùng tốt.
Trong file .h thêm vào các define
//Defines specific for 18F2431 which are not present in 18F2431.H file
//bits of QEICON Quadrature Encoder Interface control register
#define DISABLE_VELOCITY 0x80
#define QEI_OFF 0x00
#define QEI_2XINDX 0x04
#define QEI_2XPER 0x08
#define QEI_4XINDX 0x14
#define QEI_4XPER 0x18
#define VELOCITY_DIV_1 0x00
#define VELOCITY_DIV_4 0x01
#define VELOCITY_DIV_16 0x02
#define VELOCITY_DIV_64 0x03

int16 MAXCNT;
#byte MAXCNT = 0xF64
#byte MAXCNTL = 0xF64
#byte MAXCNTH = 0xF65

#byte QEICON = 0xFB6
//bits in QEICON
#define QEI_NOT_VELM 7
#define QEI_ERROR 6
#define QEI_DIRECTION 5
#bit QD=0xFB6.5
int16 POSCNT;
#byte POSCNT = 0xF66
#byte POSCNTH = 0xF67
#byte POSCNTL = 0xF66
int16 VREG;
#byte VREG = 0xF68
#byte VREGH = 0xF69
#byte VREGL = 0xF68
#byte DFLTCON = 0xF60 //Digital Filter Control Register
#byte CAP1CON = 0xF63

trong file .c phần main thêm vào các thiết lập

enable_interrupts(INT_IC1);
enable_interrupts(INT_IC2QEI);
enable_interrupts(INT_IC3DR);
enable_interrupts(int_rda);

QEICON = QEI_2XPER | VELOCITY_DIV_4;
MAXCNT=600;
QEICON &=0b01001111; //clear Velocity mode bit to enable
CAP1CON = 0b01001000; //enable Time Base reset (TMR5)
//TMR5 used for velocity measurement
setup_timer_5 (T5_INTERNAL | T5_DIV_BY_1);




/////////////////////////////////////////////////////

enable_interrupts(global);

viết thêm các chương trình ngắt cho nó
#int_IC1
// Velocity capture interrupt
void IC1_isr()
{
f=1;
}
#int_IC2QEI
/*
Position counter interrupt
Increment (decrement) variable MSB_position that provides a 32-bit position
counter along with hardware position counter
*/
void IC2QEI_isr()
{
dao=!dao;
OUTPUT_BIT(PIN_B5,dao);
}

#int_IC3DR
/*
Direction of movement interrupt
*/

void IC3DR_isr()
{
}

betabeta
18-04-2010, 12:39 PM
tớ mắc các dây A và B vào cổng NOT (7404) trước khi mắc vào chân QEA và QEB của PIC thì thấy đọc encoder rất tốt.
Phần code trên cậu nên xem thêm datasheet của QEI để hiểu ý nghĩa từng dòng lệnh và sửa đổi cho phù hợp trường hợp của cậu nhé

LeDuc
19-04-2010, 12:23 AM
mình dùng encoder 100 xung 2 sign 2 nguồn, động cơ kéo kính hoặc 3000vong (nói chung động cơ nào dùng cũng bị nhiễu)

#include <18f4550.h>

#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWDT

#use delay(clock=20000000)


int1 flag_ngat1=0,flag_ngat2=0,ngat1=0,ngat2=0;
int16 signA,signB,en_t,en_p;
int8 en;
/**************************************/




nếu không bắt động cơ vào thì mình quay encoder thấy nó thực hiện chương trình rất đúng,còn nếu có động cơ vào chạy thì chẳng cần quay encoder chương trình vẫn tự động thực hiện @@ ( Đã nối tụ giữa 2 đầu động cơ, diot từ chân pwm đến dương nguồn, nguồn nuôi pic khác với nguồn nuôi động lực)

Mình lên mạng dò hỏi thì biết nếu dùng pic 18f4331 thì nên dùng mode QEI mà đọc encoder khổ nổi lại không biết config nó = CCS
Bạn viết CT cho 18f4331 hay 18f4550 ?
config no bang CCS de mà .
Đọc thanh ghi của nó trong datasheet rồi config nó .
Mình cũng đã làm nhiều cái SERVO rồi , nhưng nhiễu thì vẫn chưa gặp kiểu đó bao giờ .

hello00100
08-03-2012, 10:59 PM
bạn có chắc đã cách li nguồn cho động cơ với nguồn cho vđk, chân ngắt rất nhạy đó.