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

PIC18F4431 & QuadratureEncoderInterface Module on PCWH 4
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
[email protected]



Joined: 18 May 2007
Posts: 1
Location: San Jose, Costa Rica

View user's profile Send private message Send e-mail MSN Messenger

PIC18F4431 & QuadratureEncoderInterface Module on PCWH 4
PostPosted: Mon Aug 13, 2007 11:20 pm     Reply with quote

Hi,

I'm using ur PCWH Compiler 4.023 and a PIC18F4431...

I need to use the internal PIC hardware for read a quadrature encoder,

but the file 18F4431.h doesn't have anything about this hardware modules,

I can't program the PIC hardware for that...



Can u help me, or send me a new upgraded 18F4431.h?


Thanks for ur time and help...
_________________
Fabian Vargas Delgado
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Aug 14, 2007 1:32 am     Reply with quote

Strange, I've never before seen a question about the quadrature encoder before and now in two days two people are asking the same question. Or are you the same person as Fabeo123 from http://www.ccsinfo.com/forum/viewtopic.php?t=31696?

Quote:
Can u help me, or send me a new upgraded 18F4431.h?
Read the note on the right top of this page. This is a user's forum. The forum is hosted by CCS but the CCS people don't visit here very often.
What you are asking for is a new feature, not a bug. Receiving a new header file will not help you, only a new compiler version could implement a new feature like this. Then the good news: you can write your own driver! Or search the internet, maybe you are lucky and someone else already published a driver.

Quote:
I'm using ur PCWH Compiler 4.023
This is an old and very unstable version of the compiler. Save everybody a lot of time and don't use this version. The v4.0xx compilers became more or less stable with release 4.030, or use the v3.249 which was available for download when you bought your compiler.
Guest








PostPosted: Tue Aug 14, 2007 7:34 pm     Reply with quote

Hi, u say that 4.023 is a unstable version of PICC???

Why unstable???



I just need a guide to try that hardware of my PIC18F4431...
Ttelmah
Guest







PostPosted: Wed Aug 15, 2007 7:03 am     Reply with quote

The low 4.030 versions, were the first ones that started to generate code without too many problems. Up to this point, individual versions had problems with things like memory leaks, functions not working at all, etc. etc..
You could probably write a fully working program with 4.023, provided you kept it very simple. However touch things like structures, or try to use just about any of the 'new' V4 features, and you are likely to have problem. :-(

Best Wishes
FUEVARDE
Guest







PostPosted: Wed Aug 15, 2007 12:54 pm     Reply with quote

I need buy again the compiler PCWH....



Or i can upgrade my compiler 4.023 on internet

or something like that???
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Wed Aug 15, 2007 1:04 pm     Reply with quote

Quote:

I need buy again the compiler PCWH....

Well this up to you, latest V4 versions seems to be very reliable to work. I wouldn´t made
a new complex project with your version (4.023).

PCH V4.050 version doesn´t have any built in function regarding the use of the
quadrature encoder PIC hardware module.

Quote:

but the file 18F4431.h doesn't have anything about this hardware modules,

I dont have V4.023 to check it, but if you will see the following 2 interrupts -in the interrupt
listing for the device- at the end of the 18F4431.H file, you already have this feature.

INT_IC3DR Direction Change Interrupt
INT_IC2QEI Position Counter Interrupt

I never worked with this device, but it is not necesary to write any driver, the compiler
should trigger these interrupts.

In order to obtain this, in the initialization procedure you should add:
Code:

  enable_interrupts(INT_IC3DR);
  enable_interrupts(INT_IC2QEI);


Then, write the interrupt handler inside INT_IC3DR , it should test QEICON.5 bit
to know the direction (1=forward 0=reverse)

The interrupt handler inside INT_IC2QEI should update the position counter (x2 or x4)
according to criteria selected in QEICON 4:2

and you will be very close to get what you need.


Humberto
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

PostPosted: Wed Aug 15, 2007 8:06 pm     Reply with quote

The basic test code below is for the 18F2331 in QEI mode with the encoder index
to clear the counter. It should work for the 18F4431.

Your application could be built on this and possibly include the interrupts for
detecting the index and change of direction.
The CCS version was 3.249. This version also has support for the interrupts.

Note that for the counter to be reset, the encoder must move to give a
transition on one of the encoder phases while the INDEX is high.

The position counter is not buffered and this can cause a problem:
http://forum.microchip.com/tm.aspx?m=199253&mpage=2

Code:

#include <18F2331.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP,PWMPIN
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS)

// Definitions
#byte QEICON      = 0xFB6  // Quadrature Encoder Interface control register
#byte DFLTCON     = 0xF60  // Digital filter control register

#byte POSCNTH     = 0xF67  // Position register high byte
#byte POSCNTL     = 0xF66  // Position register low byte


union
{
   int8 bytes[2];
   int16 word;
} position_union;


void main()
{
     
   // QEICON setup:
   // Velocity mode disabled, no overflow or underflow error bit,
   // UP/DOWN 1 = Forward, x4 QEI mode, INDX to clear count.
   
   QEICON = 0xB4;   
   
   // Digital filter setup:
   // Enabled for INDX, PHA, PHB. Tcy/16
   
   DFLTCON = 0x3B;   

   while(1)
   {
 
      position_union.bytes[0] = POSCNTL;
      position_union.bytes[1] = POSCNTH;

      // Workaround for hardware bug caused by lack of buffering
     
      if ((position_union.bytes[0] == 0) || (position_union.bytes[0] == 0xFF))
      {
         position_union.bytes[0] = POSCNTL;
         position_union.bytes[1] = POSCNTH;
      }

      printf("position = %5lu\n\r",position_union.word);
     
      delay_ms(500);
   }
}
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

Encoder count problem
PostPosted: Thu Jan 29, 2009 5:23 am     Reply with quote

Hi Kenny,

I tried your code with an optical encoder (PPR - 1024 with A, B and index).
I tested it at low RPM and the count goes upto approx 1200 then resets at the index pulse. It is supposed to count upto 1024 then reset.




Code:

#include <18F2331.h>
#include <flex_lcd.c>
#use delay(clock=20000000)
#use fast_io(a)     
#use fast_io(b)
#use fast_io(c)     
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP,PWMPIN

//configuracoes QEI
// Definitions
#byte QEICON      = 0xFB6  // Quadrature Encoder Interface control register
#byte DFLTCON     = 0xF60  // Digital filter control register
#byte POSCNTH     = 0xF67  // Position register high byte
#byte POSCNTL     = 0xF66  // Position register low byte
union
{
   int8 bytes[2];
   int16 word;
} position_union;
//
void main()
{
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0|ADC_WHEN_INT0|ADC_INT_EVERY_OTHER);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   lcd_init();
   enable_interrupts(GLOBAL);
   setup_oscillator(false);
   // QEICON setup:
   // Velocity mode disabled, no overflow or underflow error bit,
   // UP/DOWN 1 = Forward, x4 QEI mode, INDX to clear count. 
   QEICON = 0xB4;       
   // Digital filter setup:
   // Enabled for INDX, PHA, PHB. Tcy/16 
   DFLTCON = 0x3B;
  while(1)
   {
      position_union.bytes[0] = POSCNTL;
      position_union.bytes[1] = POSCNTH;
      // Workaround for hardware bug caused by lack of buffering
      if ((position_union.bytes[0] == 0) || (position_union.bytes[0] == 0xFF))
      {
         position_union.bytes[0] = POSCNTL;
         position_union.bytes[1] = POSCNTH;
      }
      lcd_gotoxy(1,1);
      printf(lcd_putc,"\fpos = %5lu\n\r",position_union.word);
      delay_ms(50);
   }
}


Am I doing something wrong?
Can anybody see anything

Best Regards
Carl
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

Re: Encoder count problem
PostPosted: Thu Jan 29, 2009 4:49 pm     Reply with quote

Not active with PICs at the moment (other duties) but here goes.

The code is setup for x4 mode, which means that the leading and trailing edges of both phases are counted. Is "PPR - 1024" a 1024 slot encoder? If so the count should range from 0 to 4095.

Does the count go down when the shaft is turned in the opposite direction?

Unless you really need fast_io for other purposes delete these lines of code. There is no advantage in terms of speed for the encoder since the up/down counting is done in the QEI hardware. This shouldn't be a problem though, since the pins default to inputs, and you haven't manually set the TRIS.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Jan 30, 2009 2:39 am     Reply with quote

Hi Kenny,

Thanks for your help.

I have tried with and without the fast io - no difference as you said. The encoder is an optical encoder with a film (1024ppr light and dark lines).
I thought that it should count 4 x 1024 = 4096 but it doesn't.

The counting when the shaft rotates clockwise, counts from 0 upto about 1200 and then when the index on the encoder is present the count resets back to zero and starts again.

When the shaft rotates couterclockwise the count decrements past zero to 65535 and then countinues decrementing 65534, 65533 etc.

I have tried changing the Tcy/16 to various options from 1:1 to 128 and each time it makes a big difference to the count - but still not accurate.

Eg
DFLTCON = 0x3C; //(Tcy/32)
and it now counts upto approx 1100.

DFLTCON = 0x38; //(Tcy/1)
and it now counts upto approx 3300.

am I using the timer incorrectly - isn't the QEI ONLY connected with timer5??

I am setting these timers up - is this wrong??

Code:
setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);


Thankyou for your time Kenny

Carl
Ttelmah
Guest







PostPosted: Fri Jan 30, 2009 5:27 am     Reply with quote

A couple of minor comments, but they shouldn't affect what you are doing.
Get rid of the enable_interrupts line. You have no interrupt handlers present, and though in the code as shown, you don't enable any individual interrupts, this raises the risk of something going wrong, if an interrupt does occur. Without a handler, the compiler won't generate code to handle interrupts, which _will_ result in disaster...
Why do you have the line 'setup_oscillator(false)'?...
Consider using 16bit to access the counter. Try:

int16 position;
#byte position=0xF66

The compiler will then allow you to access the 16bit variable containing both halves of the counter.

Are you sure that your quadrature signals do reliably pull high to the levels needed by these inputs?. In QEI mode, these input are Schmitt type, and require the signal to reach 0.8*Vdd. Many encoders will need pullups, or buffers to do this reliably.

The noise filter, may cause problems. Potentially, with 1024 edges per rotation, your working frequency is high enough, that at anything above quite low rotational rates, this could start filtering the actual signal. I'd look at running with 0x3A or lower. However I think this may be showing a massive amount of noise of the signal at present, because the signals are not reliably getting high, and this is why you are seeing large charges from this.....

Best Wishes
Briany



Joined: 06 Jan 2009
Posts: 15

View user's profile Send private message

PostPosted: Fri Jan 30, 2009 6:00 am     Reply with quote

put this to your 18F4431.h file

Code:


//setting QEI

#define     DISABLE_VELOCITY      0x80
#define     QEI_OFF               0x00
#define     QEI_2XINDX            0x04
#define     QEI_2XPER             0x08
#define     QEI_4XINDX            0x14
#define     QEI_4XPER             0x18
#define     VELOCITY_DIV_1        0x00
#define     VELOCITY_DIV_4        0x01
#define     VELOCITY_DIV_16       0x02
#define     VELOCITY_DIV_64       0x03

#byte       QEICON                = 0xFB6
//bits in QEICON
#define     QEI_NOT_VELM          7
#define     QEI_ERROR             6
#define     QEI_DIRECTION         5

int16       POSCNT;
#byte       POSCNT                = 0xF66
#byte       POSCNTH               = 0xF67
#define     POSCNTL               = 0xF66
int16       VREG;
#byte       VREG                  = 0xF68
#byte       VREGH                 = 0xF69
#byte       VREGL                 = 0xF68
#byte       DFLTCON               = 0xF60   //Digital Filter Control Register
#byte       CAP1CON               = 0xF63

int16       MAXCNT;
#byte       MAXCNT                = 0xF64
#byte       MAXCNTH               = 0xF65
#byte       MAXCNTL               = 0xF64


#list
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Jan 30, 2009 6:32 am     Reply with quote

Hi Ttelmah and Briany,

I have changed the code and it works correctly. I have not made any changes to your suggestions yet because I read your comments after I had changed the code.

The ouputs from the encoder are standard extended line driver 5-24V and so do not need pull ups (they are not Open collector).

If the program needs optimising i will do your suggestions.

My Problem now is though, i only want to print onto the lcd the final count value - ie 1024. I do not want to see it incrementing for every count. Therefore i have added the interrupt, but if I understand correctly, putting a print into a interrupt is not a good idea. It is included just to show you what I mean.

So how can I update the LCD only once per revolution (ie when the interrupt occurs) and display the final count ie 1024??

THankyou for your help

Carl



Code:
#include <18F2331.h>
#include <flex_lcd.c>
#use delay(clock=20000000)
#use fast_io(a)     
#use fast_io(b)
#use fast_io(c)     
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP,PWMPIN
//configuracoes QEI
// Definitions
#byte QEICON      = 0xFB6  // Quadrature Encoder Interface control register
#byte DFLTCON     = 0xF60  // Digital filter control register
#byte POSCNTH     = 0xF67  // Position register high byte
#byte POSCNTL     = 0xF66  // Position register low byte
union
{
   int8 bytes[2];
   int16 word;
} position_union;
//
void main()
{
   setup_timer_5(T5_INTERNAL|T5_DIV_BY_1);
   lcd_init();   
   QEICON = 0xB4;       
   DFLTCON = 0x7B;
   enable_interrupts (INT_IC2QEI);
   enable_interrupts(GLOBAL);
  while(1)
   {
      position_union.bytes[0] = POSCNTL;
      position_union.bytes[1] = POSCNTH;
      // Workaround for hardware bug caused by lack of buffering
      if ((position_union.bytes[0] == 0) || (position_union.bytes[0] == 0xFF))
      {
         position_union.bytes[0] = POSCNTL;
         position_union.bytes[1] = POSCNTH;
      }   
      position_union.word = ((position_union.word/4)+1);
      lcd_gotoxy(1,1);
      printf(lcd_putc,"\fpos = %5lu\n\r",position_union.word);
      delay_ms(50);                
   }
}
#int_IC2QEI
void ic2qei_interrupt (void) { 
      //position_union.word = ((position_union.word/4)+1);
      //lcd_gotoxy(1,1);
      //printf(lcd_putc,"\fpos = %5lu\n\r",position_union.word);
      //delay_ms(50);
}
Ttelmah
Guest







PostPosted: Fri Jan 30, 2009 8:12 am     Reply with quote

Just have a binary flag. Set it when the interrupt occurs, and record the count into a global value at this point.
In the main, check for the flag, if it is set, clear it, and print the value.

I'm not sure what you mean by 5-24v on the drivers. The 'point' is that a TTL output (normally thought of as '5v'), only guarantees 2.4v as it's 'high' level. The inputs involved need 0.8* the supply voltage (4v, with a 5v supply), and so will need pull ups for reliable operation, unless your drivers _guarantee_ that their output high is greater than this. Check the data sheet for the drivers used - also remember to consider the droop/noise present in the connections...

Best Wishes
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Fri Jan 30, 2009 8:45 am     Reply with quote

Hi Ttlemah,

Thanks for your help. I have been trying this technique, but haven't quite got it right yet - I'll keep trying.

As for the voltage, the encoder's output circuit is 5 to 24Volts Extended Line Driver - it is an adaptation of the normal CMOS Line Driver 7-15Volts. Therefore if you put 12V into the encoder then you would get about 11V out on the A,B and Index channels - because of the volt drop over the encoder circuit.

The encoder I am using has a 5V regulated output - So I am supplying it with 9V and am getting 5V out on the A, B and Index channels.

Best Regards
Carl
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