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

QEI Velocity Mode - 18f4431

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
123bally



Joined: 20 Jan 2013
Posts: 21

View user's profile Send private message

QEI Velocity Mode - 18f4431
PostPosted: Sun Jan 20, 2013 4:16 pm     Reply with quote

Hi Really appreciate some help on this:

Trying to use QEI to capture position and speed on a 18f4431. The position presented no problem and works well. Velocity is causing a headache and as MPLAB cannot simulate QEI I feel somewhat in the dark!

My understanding is that if I use the function
count=qei_get_count(QEI_GET_VELOCITY_COUNT);
Then count will have the value of timer 5 loaded and timer 5 will be reset.

I modified my position code but I seem to get no response when I run the encoder.

My rough cut test code below:

Code:

#include <18F4431.H>
#fuses hs, NOWDT, NOBROWNOUT, PUT, NOLVP,NOMCLR
#use delay(clock = 20000000)

#USE rs232(bAUD=9600,XMIT=PIN_C6, RCV=pin_c7, BITS=8,errors)

#include "flex_lcd.c"

//*********************DEFINITIONS**************
#define Tare PIN_b0
#define Print PIN_B1
#define Alive PIN_B7

// note do note use PINS D0-D3 and Pins B4-B6 as they are reserved for ETAngleMeter-LCD driver

//*********************Variables************************************
signed long count;
float angle;
INT DIRF,ext;
   
//==========================



void main()
{

   set_tris_b(0x03); // B0 - B1 as inputs
   set_tris_a(0x3C); // RA2,Ra3,RA4 as input
   set_tris_d(0x00);
   setup_QEI(QEI_MODE_X4_RESET_with_indx );
   setup_QEI(QEI_VELOCITY_PULSE_DIV_1);      //add velocity options to original code
   setup_QEI(QEI_VELOCITY_MODE_ENABLED); 
   SETUP_TIMER_5(T5_INTERNAL);
   SETUP_TIMER_5(T5_DIV_BY_1);


while(true)
   {
      //count=qei_get_count(QEI_GET_POSITION_COUNT); //comment out
      count=qei_get_count(QEI_GET_VELOCITY_COUNT);//add velocity capture
      Angle=count/(float)4;
      printf(lcd_putc,"Angle:  %5.2f",angle);


   }//while loop
      
 
} // end main


Thanks in advance for all help...

Andy
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jan 20, 2013 5:13 pm     Reply with quote

Just a couple of quick comments. While I don't use that PIC, I have used external encoders.

1) Try displaying the raw 'count' onto the LCD or PC screen..
this will confirm/deny the encoder and QEI peripheral is working/coded right.


2) "Angle=count/(float)4;" might not be what you want. Try 'hardcoding' a few numbers in for 'count' and see what is displayed in the print function.
I'm thinking that "angle=float(count/4)" might be the proper casting?

I find it best to break down even 'simple' programs like this, 'hard code' expected test data and see the results. Often it'll show that a couple of braces here a wrong semicolon there cause unexpected results.

Also be sure to list your compiler version as there may be a bug in yours and later versions have been corrected.


hth
jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 20, 2013 8:01 pm     Reply with quote

Quote:

setup_QEI(QEI_MODE_X4_RESET_with_indx );
setup_QEI(QEI_VELOCITY_PULSE_DIV_1); //add velocity options to original code
setup_QEI(QEI_VELOCITY_MODE_ENABLED);

CCS functions are not cumulative. You don't add features by calling
setup_qei() multiple times. It should all be done in one call.

Look in the setup_qei() section of the manual. It has a code example
on the next page in the manual, after the function explanation:
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
123bally



Joined: 20 Jan 2013
Posts: 21

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 4:41 am     Reply with quote

Thanks for all the replies:

Temtronic - Appreciate your comments - thanks.

PCM - Thanks for the tip on calling setup functions. Not sure how I have managed for so long without fully appreciating this fact!

I have rewritten the code and got further forward but still struggling with velocity values. Basically I get a value captured but it is very erractic. I am still assuming that:

Enabling velocity mode will capture the value of timer5 and reset the timer to 0 with every velocity trigger event.

Thus COUNT=qei_get_count(QEI_GET_VELOCITY_COUNT); will tell me the time period between events.

So when I run the encoder I am expecting a high value at low speed and a low value at high speed.

What I get is the value is instable, using the whole 16bit range - regardless of speed. (Unless the encoder is stationary then it simply shows a constant but "random" value)

Over a range of 100-1000 rpm on a 360ppr encoder I am expecting velocity values of 37500 - 3750

Note position works fine showing 360 deg with a reset on index

Heres the new code: (CCS PCH version 4.132)


Code:
#include <18F4431.H>
#fuses hs, NOWDT, NOBROWNOUT, PUT, NOLVP,NOMCLR
#use delay(clock = 4000000)

#USE rs232(bAUD=9600,XMIT=PIN_C6, RCV=pin_c7, BITS=8,errors)

#include "flex_lcd.c"

//*********************DEFINITIONS**************
#define Tare PIN_b0
#define Print PIN_B1
#define Alive PIN_B7


// note do note use PINS D0-D3 and Pins B4-B6 as they are reserved for ETAngleMeter-LCD driver

//*********************Variables************************************
unsigned long count,timer;

signed long position;
float angle;
INT DIRF,ext;
   
//=========================




void main()
{
   
   set_tris_b(0x03); // B0 - B1 as inputs
   set_tris_a(0x3C); // RA2,Ra3,RA4 as input
   set_tris_d(0x00);
   setup_timer_5(T5_INTERNAL|T5_DIV_BY_1); // so timer 5 should roll over every 0.07 sec based on (4MHZ / 4 x 8)
   setup_QEI(QEI_MODE_X4_RESET_WITH_INDX|QEI_VELOCITY_MODE_ENABLED|QEI_VELOCITY_PULSE_DIV_64);
   delay_ms(15);
   count=150;
   lcd_init();  // Always call this first.
   lcd_putc("\fHello World\n");          //putc - puts a set of characters, in ascii format, to the lcd (\f clears the screen and starts from x0,y0)
   printf(lcd_putc,"Count:  %6ld",count);
   output_high(Alive);
   delay_ms(1000);
   output_low(alive);



while(true)
   {
      Position=qei_get_count(QEI_GET_POSITION_COUNT);      //get position
      COUNT=qei_get_count(QEI_GET_VELOCITY_COUNT);      //get time between velocity events

      Angle=Position/(float)4;                     // convert x4 to degrees
      printf(lcd_putc,"\f Angle:  %5.2f\n",angle);      // print angle position
      printf(lcd_putc,"count: %lu",count);            // print value from get_velocity_count
      output_toggle(alive);                        //   
      delay_ms(100);                              //allow LCD some responce time

   }//while loop
      
 
} // end main


Thanks for all your help....

Andy
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 6:02 am     Reply with quote

I think you will have to read qei_status, and work out which bit is the overflow bit. This will be set when the count goes over 65535, and when this is set you then know your velocity is below the limits of reading.
I'd don't think reset on index is compatible with velocity mode.

Best Wishes
123bally



Joined: 20 Jan 2013
Posts: 21

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 6:18 am     Reply with quote

More progress on this....

I had suspected that timer5 was not being reset on a velocity trigger event. That would expalin the inconsistent values. (Please note I have checked bit 6 of cap1ren (1) and it shows that the timer is set to reset on event)

I then found that the IC1IF is triggered by a velocity register update, table 17-7 in data sheet, so I used that interrupt to set the timer to zero. By forcing the reset in this interrupt my code now works!

If anyone can explain why I needed to do this It would be greatly appreciated.

Andy
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 8:13 am     Reply with quote

It is perhaps informative to look at the MicroChip application notes. AN899 in particular to see how they do this. I'd possibly try directly reading the velocity registers. It sounds rather as if GET_VELOCITY_COUNT is actually returning the count registers, rather than the velocity registers.

Best Wishes
123bally



Joined: 20 Jan 2013
Posts: 21

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 9:32 am     Reply with quote

HI Ttelmah

I will check that app note in more detail - Thanks

When you refer to the velocity registers I assume you are refering to CAP1BUF. I can confirm that these are being read ok (0xf68 0xf69) by GET_VELOCITY_COUNT. (checked and confirmed in disassembly listing)

I am just curious as to why timer5 value is not reset. It clearly states that it should be in the data sheet:

PG168 Fig 17-13
3: The TMR5 counter is reset on the next Q1 clock cycle following the “velcap” pulse.

I have implemeted some further refinement to deal with timer 5 rolling over at low speed. Reset on index is working fine with this configuration.

Thanks Andy
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 9:52 am     Reply with quote

I'm referring to the VELR register. This is what has to be read for velocity.
Look at figure 16-13, which shows the operation. However CAP1BUF, is VELR in this mode.
Important thing is that resetting the counter is optional. You can either have it reset, or leave it running. The latter is used when you want to give an absolute measure for 'position' as well. The former is used when you only want velocity. 16.2.6.3 in the data sheet. You say you have checked CAP1REN though, which would give this operation. Note that in the Microchip note, they don't set this bit, and instead subtract the last reading from the current one. I wonder if there is a fault in the hardware here. Other thing to check is the programming bits of the timer, since this only works if it is running synchronous to the internal clock. It certainly _should_ be, but is it.....
I'd double check the CAP1REN bit. This is the only thing that makes sense. Other thing is note3, on fig 16-13, which says that the postscaler needs to be reset after enabling VELM.

Best Wishes
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 11:44 am     Reply with quote

You are reading the value continuously. It is not the act of reading, that resets timer5. It is the capture event trigger. When the capture event fires, the contents of timer5 are saved, and it is then reset.
As far as I can see you have no capture event.

Best Wishes
123bally



Joined: 20 Jan 2013
Posts: 21

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 12:07 pm     Reply with quote

Quote:
You are reading the value continuously
--Yes, well every 100ms

Quote:
It is not the act of reading, that resets timer5. It is the capture event trigger. When the capture event fires, the contents of timer5 are saved, and it is then reset.
--completely agree.

Quote:
As far as I can see you have no capture event.
-- The capture event occurs when I run the encoder for 64 ticks as defined by QEI_VELOCITY_PULSE_DIV_64

So if capture events cease (encoder stationary) then it just reports the last captured value - I would agree this needs refinement but serves to prove operation.

I think we are pretty much on the same page with this one, exactly why i need to force timer to zero is a mystery. I am beginning to suspect that the CAP1REN bit may get changed during execution but I double checked and it is configured correctly during initialization. As QEI is not supported by the sim I am probably unable to prove this suspicion.

Makes for an interesting day though!

Andy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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