|
|
View previous topic :: View next topic |
Author |
Message |
Ra Guest
|
how to read velocity from optical encoder using pic |
Posted: Sun Nov 13, 2005 10:42 pm |
|
|
Hi,
My project is relate with motor control and i use two motors, i try using pic18f2431 to capture the position and velocity but i can get only position.
Any one have a sample code to get velocity from pic18f2431 using interrupt qei and interupt port b?
code to capture the position is
#include <18F2431.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, parity=N, Bits=8, xmit=PIN_C6, rcv=PIN_C7,stream=COM_1)
#BYTE QEICON=0xFB6 // quadrature configure
#bit QEICONDIR=0xFB6.5
#BYTE DFLTCON=0xF60 // quadrature noise filter configure
#BYTE CAP2BUFL=0xF66 // position counter
#BYTE CAP2BUFH=0xF67
#BYTE CAP3BUFL=0xF64 //max count
#BYTE CAP3BUFH=0xF65
#byte portb=0xF81
#bit bchanged=0xFF2.0
#use fast_io(B)
unsigned int16 quadhigh=0;
signed int32 position=0;
#int_rb
void myint(void) {
static int old;
static int new;
static int value;
new=portb;
value=new^old;
//'value', now has the bit set, which has changed
if (value & 0x10) {
//Here the low bit has changed
if (new & 0x10) {
//Here a rising edge on A
if (new & 0x20) --position;
else ++position;
}
else {
//Here a falling edge on A
if (new & 0x20) ++position;
else --position;
}
}
else {
//Here the high bit (B) must have changed
if (new & 0x20) {
//Here a rising edge on B
if (new & 0x10) ++position;
else --position;
}
else {
//Here a falling edge on B
if (new & 0x10) --position;
else ++position;
}
}
old=new;
bchanged=0;
#asm
RETFIE 1
#ENDASM
}
#int_IC2QEI
QuadRollover()
{
QEICONDIR?quadhigh++:quadhigh--;
}
void main(void) {
signed int32 position1=0;
signed int32 old_pos=0;
signed int32 lastpos=0;
position=0;
QEICON=24; // quad in x4 mode, resettable by maxcount
DFLTCON=49; // noise filter on QEA, QEB,, 1:2 clock
CAP3BUFL=0xFF; // set max count
CAP3BUFH=0xFF;
CAP2BUFL=0;
CAP2BUFH=0;
port_b_pullups(true);
setup_adc_ports(NO_ANALOGS);
setup_spi(FALSE);
set_tris_B(0x30);
enable_interrupts(INT_RB);
enable_interrupts(INT_IC2QEI);
enable_interrupts(global);
lastpos=position;
while (true) {
position1=(((int32)(quadhigh))<<16)+(CAP2BUFL+((int16) CAP2BUFH<<8));
if(lastpos!=position || old_pos!=position1){
lastpos=position;
old_pos=position1;
delay_ms(20);
printf("%ld %ld\n\r",lastpos*360/500/23,old_pos*360/500/23);
}
}
}
Thank you for your help. |
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
|
Posted: Sun Nov 13, 2005 10:58 pm |
|
|
When your encoder provides an interrupt on each increment, so the velocity is 1/delta_t [clicks/sec], where delta_t is the time between the current interupt and the previous one. You need to set up one of the PIC's timers, which will generate delta_t. If your revolution rate is high enough, you can read the timer via get_timerX() and reset the timer at the end of your RB interrupt via set_timerX(0). If your revolution rate is not high enough, you'll need to count the interrupts in a global variable.
P.S. Please edit your original posting to add the code tags around your code. |
|
|
Guest
|
|
Posted: Mon Nov 14, 2005 12:14 am |
|
|
Hi Kender,
Thank you very much for your reply. but I don't understant your explanation, Give me more detail about this if you have example code please give me.
Thank you.[/code] |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|