|
|
View previous topic :: View next topic |
Author |
Message |
williamho Guest
|
QEI code for 18f4431 |
Posted: Thu Jun 30, 2005 11:10 pm |
|
|
hi,
I try to use someone's code for optical encoder with f4431.
phase A connected to RA3(QEA)pin 5 and phase B to RA4(QEB)pin 6.
but lcd only show "count = 3345" or any number after i reset the MCU.
Can anyone help?
Code: | #include <18F4431.h>
#DEVICE ICD=TRUE
#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
#include <lcd.c>
unsigned int16 quadhigh=0;
#int_IC2QEI
QuadRollover()
{
// increment high bytes if + direction on interrupt, decrement if -
QEICONDIR?quadhigh++:quadhigh--;
// to see when this happens,
// I find it helpful to toggle a digital out here
}
void main()
{
signed int32 position=0;
signed int32 old_pos=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;
lcd_init();
lcd_putc("\n\rready\n\r");
enable_interrupts(INT_IC2QEI); // interrupt on maxcount or underflow
enable_interrupts(GLOBAL);
while (1)
{ //of course, in real life, this is RTCC driven!!
position=(((int32)(quadhigh))<<16)+(CAP2BUFL+((int16)CAP2BUFH<<8));
if(old_pos!=position)
{
old_pos=position;
printf(lcd_putc,"\fcount = %6ld",old_pos);
}
}
}
|
|
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
Re: QEI code for 18f4431 |
Posted: Fri Jul 01, 2005 6:45 am |
|
|
williamho wrote: | hi,
I try to use someone's code for optical encoder with f4431.
phase A connected to RA3(QEA)pin 5 and phase B to RA4(QEB)pin 6.
but lcd only show "count = 3345" or any number after i reset the MCU.
Can anyone help?
|
It's my code.
First, add
Code: | CAP2BUFL=0;
CAP2BUFH=0; |
somewhere after you define these registers. This will help you determine whether you're counting at all!
Slow down that last loop a lot. You really don't want to do this print of every iteration through the loop-- maybe every 100 iterations or so. I don't think this is your problem, but all that serial output is going to wreak havoc. The original snippet for the loop in main is just a placeholder-- I used a timer to drive the loop at a kHz for control purposes, and I used a counter to update the display at something like every 100 iterations.
Then, try running the code simply tying both QE inputs low, or one low and one high, and make sure that your count stays at 0 (or maybe one or two LSB's to either side of zero, allowing for startup glitches.
Next, with the type of behavior you're seeing, I'd consider a watchdog timer. How do you know that the lcd is actually updating?? I'd recommend using an RS232 out-- at least in a terminal, you can see whether the output is scrolling or not. At the very least, toggle a bit every once in a while to help you try and figure things out. Depending on your output rate, maybe you could send the 4th or 5th LSB of your count out to a digital out and an LED. If you can look at this output on an oscilloscope, just look at the LSB. With an LED, you need to pick a bit that will change slow enough to see the blinking.
You may or may not need QuadRollover. I needed this because I had a high resolution encoder, running on the motor side of a big gear reducer at high speed. If you're not expecting your count to exceed 16 bits, don't enable the interrupt, change all the position types to signed16, and get rid of the math that marries the count high 16 to the count low 16. Even if you need 32 bits, this would be a good debugging step to help you figure out if the interrupt is killing you.
Get rid of the "6" in your %6ld format. Maybe things die if you need more than 6 digits right now. I don't know much about lcd_putc, so I don't know if it would screw up here, and how the screwup would manifest on the screen.
Bottom line, slow down your output rate to something reasonable, and try to figure out if the count is working through a means more verifiable than an lcd write.
Scott Seidman |
|
|
pswanson Guest
|
Small detail |
Posted: Thu Jul 07, 2005 12:37 pm |
|
|
Note that you declared quadhigh as an unsigned int16. You can potentially and perhaps very easily underflow this term. |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
Re: Small detail |
Posted: Thu Jul 07, 2005 12:54 pm |
|
|
pswanson wrote: | Note that you declared quadhigh as an unsigned int16. You can potentially and perhaps very easily underflow this term. |
Thanks for pointing it out. I'm pretty sure I tested it, and found that when you decrement an unsigned 0x00, it rolls over to 0xFF. Math done with the result will of course be wrong, but I'm just shifting it up to the high byte of an i32, so it doesn't make a difference. I'll check again, just to make sure.
In my actual app, I don't check the encoder until a hit a switch going in the negative direction. when I hit it, I zero the count, and move in the positive direction toward center.
Scott |
|
|
|
|
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
|