|
|
View previous topic :: View next topic |
Author |
Message |
[email protected]
Joined: 18 May 2007 Posts: 1 Location: San Jose, Costa Rica
|
PIC18F4431 & QuadratureEncoderInterface Module on PCWH 4 |
Posted: Mon Aug 13, 2007 11:20 pm |
|
|
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
|
|
Posted: Tue Aug 14, 2007 1:32 am |
|
|
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
|
|
Posted: Tue Aug 14, 2007 7:34 pm |
|
|
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
|
|
Posted: Wed Aug 15, 2007 7:03 am |
|
|
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
|
|
Posted: Wed Aug 15, 2007 12:54 pm |
|
|
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
|
|
Posted: Wed Aug 15, 2007 1:04 pm |
|
|
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
|
|
Posted: Wed Aug 15, 2007 8:06 pm |
|
|
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
|
Encoder count problem |
Posted: Thu Jan 29, 2009 5:23 am |
|
|
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
|
Re: Encoder count problem |
Posted: Thu Jan 29, 2009 4:49 pm |
|
|
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
|
|
Posted: Fri Jan 30, 2009 2:39 am |
|
|
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
|
|
Posted: Fri Jan 30, 2009 5:27 am |
|
|
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
|
|
Posted: Fri Jan 30, 2009 6:00 am |
|
|
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
|
|
Posted: Fri Jan 30, 2009 6:32 am |
|
|
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
|
|
Posted: Fri Jan 30, 2009 8:12 am |
|
|
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
|
|
Posted: Fri Jan 30, 2009 8:45 am |
|
|
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 |
|
|
|
|
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
|