CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Quadrature Encoder Using the PIC18F2331/PIC18F2431
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

Quadrature Encoder Using the PIC18F2331/PIC18F2431
PostPosted: Wed Feb 16, 2011 9:31 pm     Reply with quote

Hi, I’m trying to use the inbuilt hardware QEI decoder in the PIC18F2.xxx
series of chips. Currently I am using 4.116 of the compiler. The encoder
I am using is a Bourns 24det mechanical type with 3 pins, it also has a built in push switch. The pins of the encoder are pulled up via 47k resistors
to vcc and connected to pins 5 & 6 on the chip.

Anyway what I want to accomplish is to simply increment a variable as the encoder is turned clockwise and decrement it as its turned anti-clockwise. Similar to how a tuning knob works on your car radio.

Looking through the ccs help file there is some info on how to setup_qei
with various options. The .h file for the part also includes the defines, but
there is no worked example so it’s difficult to figure out how to really use
the qei features of the part.

Looking at the PIC app note I think what I am after is a way to read the
position counter and use that to increment/decrement my variable.

Here is what I have tried so far. I would prefer to get the code working
not using a ISR to start with and then go from there.
Code:

#include <MAIN.h>
#USE delay(clock=10Mhz, crystal)

#USE FAST_IO(A)
#USE FAST_IO(B)               
#USE FAST_IO(C)               

#BYTE port_a = 0xF80         
#BYTE port_b = 0xF81
#BYTE port_c = 0xF82

int Count;                     
#include <LCD4bit.c>         

void Write_Display (void)
{
 Lcd_Config( LCD_LINE1 );
 printf(Write_LCD, "%d",Count);
}
 

#int_IC3DR
void  IC3DR_isr(void)
{
Count--;
}

#int_IC2QEI
void  IC2QEI_isr(void)
{
Count++;
}


void main(void)
{                         
                     
   set_tris_b(0b00001101);       //Port B I/O Config
   set_tris_c(0b11000000);       //Port C I/O Config
   LCD_Start();                  //Enable LCD to Start up
   Count=100;
     
  setup_qei(QEI_MODE_X2);
       
   enable_interrupts(INT_IC3DR);
   enable_interrupts(INT_IC2QEI);
   enable_interrupts(GLOBAL);

  while(true)
  {
    Write_Display();
  } 
}

The code is really bare bones at this point as I don’t have much to go on.
I noticed that the #int_IC3DR appears to be working but the count goes
down by a large number on each click of the encoder. I can turn the
encoder either left or right but the count still goes down Smile LOL got to love
that eh.

The #int_IC2QEI ISR, does not appear to do anything at this point.

As I mentioned above I would prefer to get the thing working not using
a ISR to begin with so as to fine tune things and then take it from there.

Any guidance would be welcome.

Thanks Scott.
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Wed Feb 16, 2011 9:53 pm     Reply with quote

If I remember correctly, the encoder count registers maintain the count without you having to do anything but set them up. The QEI interrupts are for overflows and underflows of the count registers so you can do some extra bookkeeping with a larger integer.

You don't want to service an interrupt every time the encoder clicked. You wouldn't use a chip in this 18fxx31 series if that's how you wanted to handle things.
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 9:11 am     Reply with quote

ok, I'm back... I looked last night as I was going to bed and decided rather than clicking a response and my keyboard waking up my girlfriend, I would reply today.

You are absolutely using this module incorrectly.

For your value, you just read the QEI position counter... It automatically goes up and down. You don't have to do it.

You're using the interrupts incorrectly. DR is only for a change in direction... not every pulse that's backwards. (backwards relative to what?)

IC2QEIF only interrupts on a period match, a rollover or and index pulse.

Your display should be showing the value of POSCNTH:POSCNTL.

Also, keep in mind, this is a 16bit counter... after it reaches 0 or 0xFFFF it will roll over unless there's an index pulse. Are you using an encoder with an index pulse? if not, you'll want to find another way to zero the position, no? You haven't told us what encoder you're displaying and why.

Cheers,

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 10:22 am     Reply with quote

Another question I meant to ask is:

Is your encoder an absolute position encoder or just a counter (like a knob on a stereo)??

You describe your task as being one to get absolute position.. and if that's the case, you need to know the number of pulses for a full turn.

That, and you should have an index pulse.. otherwise you'll see the position counter zero out as it should on index.

This still will be important for modes like powerup when the PIC doesn't have a count or index on the position yet and doesn't know about the position of what the encoder is linked to... (and from there, all sorts of other problems can come up).

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 11:33 am     Reply with quote

Ben the Encoder is a mechanical type like a Stereo Knob. Its got
24 clicks in total for one revolution. It does not have a index.

Bourns PEC 11 Incremental Encoder
http://www.bourns.com/data/global/pdfs/PEC11.pdf

I figured I was not using the module correctly as the code is based on
info from the ccs help file and the .h file, really bare bones at this point.

The end result of what I am trying to do is. If I have a INT with a value
of 100 and I turn the encoder clockwise the INT value increments by 1.
If I turn the encoder anti-clockwise that INT value decrements by 1

I can do this with regular code and 2 pic pins. I wanted to try use the
dedicated hardware of the pic to try the same thing as the qei module also includes pin filtering for noise etc.

Thanks Scott
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 11:39 am     Reply with quote

Thanks sseidman, Details on using this are really Dire in the CCS help file.
Its kind of amazing really that they never included an example on this.

I will keep digging at it to see if I can get it to function as expected.

Scott
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 12:15 pm     Reply with quote

As Ben says then, you can just read the position registers. Declare a 'WORD' to address these, and just read it. _All_ the donkey work is done for you in the hardware. No need for interrupts, separate counter, or anything. the counter is there just like the timer counters. They just return the 'position' as the knob is turned, nothing more is needed.
Caveat though, most mechanical counters like this, need external pull up resistors.

Best Wishes
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 1:28 pm     Reply with quote

scottc wrote:
Thanks sseidman, Details on using this are really Dire in the CCS help file.
Its kind of amazing really that they never included an example on this.

I will keep digging at it to see if I can get it to function as expected.


It's all about feedback.

most of the veteran PIC users wouldn't really need an example...

So how often are the new users doing this? No feedback - no example.

Why not write up an example and submit it to CCS for inclusion in the next release?

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 4:25 pm     Reply with quote

scottc wrote:
Thanks sseidman, Details on using this are really Dire in the CCS help file.
Its kind of amazing really that they never included an example on this.

I will keep digging at it to see if I can get it to function as expected.

Scott


I posted a real code snippet from long ago in the other thread you were involved in-- just take a peek at that and things should get a bit clearer

http://www.ccsinfo.com/forum/viewtopic.php?t=23455
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

PostPosted: Thu Feb 17, 2011 9:28 pm     Reply with quote

Sseidman, I took a look at your code and kind of get the jist of whats
going on, Something is odd tho. In ver 4.114 I believe CCS added
the defines for the rotary encoder module to the .H file for the parts that
support it but I do not see any of this defined in the .h file.

#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

They got a bunch of defines under
QEI Functions: setup_qei(), qei_set_count(), qei_get_count(),
// qei_status()

I was under the impression I could configure the QEI via setup_qei
and pass what is needed etc, but this does not appear to be the case.
Its like the actual implementation is not complete.

I will bang on the code a bit more and omit the setup_qei part

thanks Scott
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Fri Feb 18, 2011 7:03 am     Reply with quote

Yeah, when I wrote that I don't think CCS had support built in for the QE. Use this code as a lesson plan, though-- Don't be afraid to go to the datasheet for the chip and learn about the special registers you're writing too, then see if the new h-file makes sense.
ALPL



Joined: 29 Mar 2009
Posts: 30

View user's profile Send private message

PostPosted: Fri Feb 18, 2011 9:03 am     Reply with quote

Scottc, this code will not work - you have to declare RA3 and RA4 as digital inputs (TRIS and ADCON0) first. Then set QEICON to the desired values, if applicable assign a value to MAXCNTL and MAXCNTH as well as to POSCNTL and POSCNTH and activate all interrupts. If needed activate the filter (DFLTCON). Then if the ISRs are correctly set up the code will work.
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Fri Feb 18, 2011 9:50 am     Reply with quote

ALPL wrote:
Scottc, this code will not work - you have to declare RA3 and RA4 as digital inputs (TRIS and ADCON0) first. Then set QEICON to the desired values, if applicable assign a value to MAXCNTL and MAXCNTH as well as to POSCNTL and POSCNTH and activate all interrupts. If needed activate the filter (DFLTCON). Then if the ISRs are correctly set up the code will work.


Unless I'm reading the datasheet incorrectly,

One of his ISR's will fire on a change of direction... once that direction is changed, no more interrupts of that type will trigger on each successive rotation click in the same direction. So having the ISR do all the position count subtractions is an error of implementation.

For the other interrupt, it only triggers on an indx pulse. He's not using an index input.

So he needs to watch for under/overflows... otherwise, the rest is up to him how to implement.

Maybe I'm nutz.
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
ALPL



Joined: 29 Mar 2009
Posts: 30

View user's profile Send private message

PostPosted: Fri Feb 18, 2011 10:26 am     Reply with quote

Correct - he has to poll the POSTCNTL/H-register-pair in the main code to find out the position.
scottc



Joined: 16 Aug 2010
Posts: 95

View user's profile Send private message

PostPosted: Fri Feb 18, 2011 9:31 pm     Reply with quote

I was looking through a data sheet last night and the analog pins need
to be set as digital IO, thanx ALPL for pointing that out.

I am wondering is it even necessary to use a ISR for this. I am back hunting the datasheet. THere has got to be a register that is getting either
a 1 or a 0 based on each pulse and direction. I believe if I can access that
then I can get to where I need to be.

Thanks Scott
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
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