You are on page 1of 6

Author 123bally QEI Velocity Mode - 18f4431

Posted: Sun Jan 20, 2013 4:16 pm Joined: 20 Jan 2013 Posts: 12

Message

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
Posted: Sun Jan 20, 2013 5:13 pm

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

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

Posted: Sun Jan 20, 2013 8:01 pm

Quote:
Joined: 06 Sep 2003 Posts: 17230

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

Posted: Mon Jan 21, 2013 4:41 am

Thanks for all the replies:


Joined: 20 Jan 2013 Posts: 12

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_VELOC ITY_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
Posted: Mon Jan 21, 2013 6:02 am

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 Joined: 11 Mar 2010 know your velocity is below the limits of reading. Posts: 4754 I'd don't think reset on index is compatible with velocity mode. Best Wishes

123bally

Posted: Mon Jan 21, 2013 6:18 am

More progress on this....

Joined: 20 Jan 2013 Posts: 12

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

Posted: Mon Jan 21, 2013 8:13 am

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 Joined: 11 Mar 2010 registers. It sounds rather as if GET_VELOCITY_COUNT is actually returning the Posts: 4754 count registers, rather than the velocity registers. Best Wishes

123bally

Posted: Mon Jan 21, 2013 9:32 am

HI Ttelmah
Joined: 20 Jan 2013 Posts: 12

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

Posted: Mon Jan 21, 2013 9:52 am

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 Joined: 11 Mar 2010 mode. Posts: 4754 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
Posted: Mon Jan 21, 2013 11:44 am

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 Joined: 11 Mar 2010 of timer5 are saved, and it is then reset. Posts: 4754 As far as I can see you have no capture event. Best Wishes

123bally

Posted: Mon Jan 21, 2013 12:07 pm

Quote:
Joined: 20 Jan 2013 Posts: 12

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

You might also like