View previous topic :: View next topic |
Author |
Message |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
pic18f4431 QEI mismatch Direction of Rotation Status Bit |
Posted: Thu Feb 14, 2008 6:30 pm |
|
|
Hi!
Does anybody know if the delay_ms function call
in lcd.c may disable an interrupt to be called?
I've read this in another topic but I couldn't find the topic anymore..
It explains about ext_int and problems related with delay calls in
code
I want to develop a simple task, just increase or decrease a value
with a QEI interrupt. If a delay is called it means that the interrupt
code will not run (and I'll have a wrong pulse count)? or not?
(I really don't know what will happen, sorry for english,
I hope that you understand my doubt)
thanks
Last edited by andredurao on Thu Feb 21, 2008 8:34 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Fri Feb 15, 2008 5:07 am |
|
|
thanks for your reply PCM Programmer
altough I think my doubt it's a little bit different
In that post , the delay_xx it's been called in the code of the interruption, wich may cause compiler gives the warning:
"Interrupts disabled to prevent re-entrancy: @delay_ms"
I want to know if a delay_ms call out of the interruption code may stop a interruption...
I'll post a code soon |
|
![](templates/subSilver/images/spacer.gif) |
Ken Johnson
Joined: 23 Mar 2006 Posts: 197 Location: Lewisburg, WV
|
|
Posted: Fri Feb 15, 2008 9:35 am |
|
|
Guest, delay_xx() will not disable interrupts.
You may want to use the restart_wdt option in your #use delay line.
Ken |
|
![](templates/subSilver/images/spacer.gif) |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
|
Posted: Mon Feb 18, 2008 6:55 pm |
|
|
once again now I'm sending the code that worked I had no troubles with interrupts thanks for the help....
But now something different is happening..
I've got the interrupts working, but the internal counter it's always
with a ZERO value in both high and low bytes.
Doesn't CAP2BUFL and CAP2BUFH should inc or dec automatically
with the internal counter?
Code: | #include "D:\pic\encoder\enc.h"
#include <LCD.C>
//configuracoes QEI
#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
//
int drcnt;
int16 qeicnt;
#int_IC3DR
void IC3DR_isr(void)
{
drcnt++;
}
#int_IC2QEI
void IC2QEI_isr(void)
{
qeicnt++;
}
boolean direcao=0;
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(INT_IC3DR);
enable_interrupts(INT_IC2QEI);
enable_interrupts(GLOBAL);
setup_oscillator(false);
QEICON=0b00011000; // quad in x4 mode, resettable by maxcount
DFLTCON=49; // noise filter on QEA, QEB,, 1:2 clock
CAP3BUFL=0x0F; // set max count
CAP3BUFH=0x00;
CAP2BUFL=0x00; // reset count
CAP2BUFH=0x00;
while(1){
printf(lcd_putc,"C2:%X-%X;QN:%X\n%Lu;d: %03u",
CAP2BUFH, CAP2BUFL, QEICON, qeicnt, drcnt);
//printf(lcd_putc,"\fENC = ");
//printf(lcd_putc, "%Lu",POSCNT);
delay_ms(50);
}
}
|
in header file I've got this
Code: | #include <18F4431.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV27 //Brownout reset at 2.7V
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES LVP //low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOWINEN //WDT Timer Window Disabled
#FUSES T1LOWPOWER //Timer1 low power operation when in sleep
#FUSES HPOL_HIGH //High-Side Transistors Polarity is Active-High (PWM 1,3,5 and 7)
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES LPOL_HIGH //Low-Side Transistors Polarity is Active-High (PWM 0,2,4 and 6)
#FUSES PWMPIN //PWM outputs disabled upon Reset
#FUSES MCLR //Master Clear pin enabled
#FUSES FLTAC1 //FLTA input is multiplexed with RC1
#FUSES SSP_RC //SCK/SCL=RC5, SDA/SDI=RC4, SDO=RC7
#FUSES PWM4B5 //PWM4 output is multiplexed on RB5
#FUSES EXCLKC3 //TMR0/T5CKI external clock input is muliplexed with RC3
#use delay(clock=20000000)
|
|
|
![](templates/subSilver/images/spacer.gif) |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
|
Posted: Tue Feb 19, 2008 6:35 pm |
|
|
Any rags, any bones, any bottles today? ![Laughing](images/smiles/icon_lol.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
|
Posted: Tue Feb 19, 2008 9:50 pm |
|
|
Worked for me. You do realise that it is setup so that the count will be cleared after 15 counts?
The registers get remapped in QEI mode, as do the names.
To make it more readable use the correct names:
CAP2BUFL is POSCNTL
CAP2BUFH is POSCNTH
CAP3BUFL is MAXCNTL
CAP3BUFH is MAXCNTH |
|
![](templates/subSilver/images/spacer.gif) |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
|
Posted: Wed Feb 20, 2008 5:30 am |
|
|
Thanks Kenny for the reply, but doesn't CAP2BUF and POSCNT are both in the same addresses?
what differs is that
"CAP2BUF is enabled as POSCNT when QEI mode is active."
is that right?
So I have a 200 pulse per revolution optical encoder with
A, B , INDEX signals, (but I will not need INDEX I just need to add
if its CW or sub if its CCW) to have a better precision and less
code I should use the internal counter(POSCNT).
QEICON=0b00011000; // quad in x4 mode, resettable by maxcount
[value=0]
bit 7 VELM: Velocity Mode bit
1 = Velocity mode disabled
0 = Velocity mode enabled
[value=0]
bit 6 ERROR: QEI error bit(1)
1 = Position counter(4) overflow or underflow
0 = No overflow or underflow
[value=0] not using INDEX
bit 5 UP/DOWN: Direction of Rotation Status bit(1)
(*QEI must be enabled and in Index mode.)
1 = Forward
0 = Reverse
[value=110]
bit 4-2 QEIM2:QEIM0: QEI Mode bits(2,3)
111 =Unused
110 =QEI enabled in 4x Update mode; position counter reset on period match
(POSCNT = MAXCNT)
101 =QEI enabled in 4x Update mode; INDX resets the position counter
100 =Unused
010 =QEI enabled in 2x Update mode; position counter reset on period match
(POSCNT = MAXCNT)
001 =QEI enabled in 2x Update mode; INDX resets the position counter
000 =QEI off
[value=00]
bit 1-0 PDEC1:PDEC0: Velocity Pulse Reduction Ratio bit
11 =1:64
10 =1:16
01 =1:4
00 =1:1
I've changed to
QEICON=0b00000100;
//001 =QEI enabled in 2x Update mode; INDX resets the position counter
now poscnt counts only 0 and 1 nothing more than this lol |
|
![](templates/subSilver/images/spacer.gif) |
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
|
Posted: Wed Feb 20, 2008 4:38 pm |
|
|
I have an old bag of bones. Genuine one owner, had them for 62 years
Yes, same register addresses, just makes it easier to read.
I think what is happening is that the first line of the lcd is not being updated.
Add this line before the printf statement:
lcd_gotoxy(1,1);
I posted some test code at the end of this thread if you get stuck:
http://www.ccsinfo.com/forum/viewtopic.php?t=31720 |
|
![](templates/subSilver/images/spacer.gif) |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
|
Posted: Thu Feb 21, 2008 5:43 am |
|
|
Hi Kenny, thanks for the reply
I tought that the problem could be the printf too
so I've added a "\f" at the begin of the string
but not changed
I've tried your code(below) but it keep working the same way that
before, I thought that it could be caused by CAP2CON, theres a
reset by timer but thats not happening.
when I turn the encoder CW or CCW it only counts one pulse
like this
poscnt starts at 16384 I turn CW or CCW it goes 16383..16384..16383..16384.....
Code: |
#include "D:\pic\encoder\enc.h"
#include <LCD.C>
//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);
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
|
Posted: Thu Feb 21, 2008 8:40 am |
|
|
I guess I starting to understand what is happening
have one optical encoder 200 pulses per revolution [phase A , B, index]
which its connected to pins 5, 6 4 respectively
I have configured QEICON at 0xFB6 with the following configuration
QEICON=0b10001000;
bit7 Velocity mode disabled
bit6 No overflow or underflow
bit5 Reverse
bit4-2 QEI enabled in 2x Update mode; position counter reset on period match (POSCNT = MAXCNT)
bit1-0 [1:1]
POSCNT and MAXCNT bytes
POSCNTL=0x00; // reset count
POSCNTH=0x00;
MAXCNTL=0xFF; //maxvalues
MAXCNTH=0xFF;
it's just a simple program that displays in a lcd POSCNT and QEICON.5 (rotation status bit)
All right now here comes the problem
When I turned my encoder CW or CCW , in every changes of phaseA and phaseB QEICON detects a change of rotation
with this I can't never get POSCNT to work, it always with 0 and 1 value because it increase and decrease
all along the time...
note: I'm not switching the direction, I'm just telling that it happens in both directions
Does anybody knows why this is happening?
Even when I turn encoder in the just one direction CW or CCW
the direction change interruption it's been called and that's why POSCNT
it's been varying in 0 ~1
I've counted 400 times that the interruption it's called in one single turn
(and I haven't change the direction ) |
|
![](templates/subSilver/images/spacer.gif) |
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
|
Posted: Thu Feb 21, 2008 4:16 pm |
|
|
I have only the 18F2331, so used the fuses shown in my test code. Also I am using version 3.249 of the compiler.
There were some problems with your #fuses. LVP should be NOLVP (unless you have a low voltage programmer), and I would use PUT instead of NOPUT to allow some time for the lcd to power up.
My test code has been modified. All that was needed was a change for the lcd, and the fuse from XT to HS for your 20MHz clock.
All I can suggest is to check that the encoder signals appear at the pic pins with a logic probe or oscilloscope. Preferably with the latter, to confirm that the correct 90 degree phase relationship exists between the two phases. Years ago some HP encoders required assembly and adjustment to get the phase relationship right.
Last edited by Kenny on Fri Feb 22, 2008 5:04 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
|
Posted: Thu Feb 21, 2008 7:46 pm |
|
|
thanks again kenny
well, about HS and XT it's already in HS you may see in the header, that I didn't change...
about LVP I've used that because in datasheet it asks to use low voltage programming for this piece, I've got a ICD2 programmer, and In programming "in-circuit" method external power supply
I'll try to use PUT instead of NOPUT.
(but the lcd printf routine it's working all right)
about the encoder I've doubt that...
I've checked and saw the following code
CW
phaseA 00110...
phaseB 01100...
CCW reverse movement... |
|
![](templates/subSilver/images/spacer.gif) |
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
|
Posted: Thu Feb 21, 2008 11:39 pm |
|
|
Can be programmed with LVP, but doesn't have to be
If LVP mode then RB5 would need to held low after programming.
Is the lcd on port d? |
|
![](templates/subSilver/images/spacer.gif) |
andredurao
Joined: 24 Apr 2006 Posts: 15
|
|
Posted: Fri Feb 22, 2008 7:05 am |
|
|
Well, I changed no NOLVP and back to program normally
and to fuses PUT
well at first sight nothing seemed to changed
but I noticed that qeicnt variable starts to increase
but not all the times, like it's random, sometimes increase
sometimes not...
well.. I'm almost giving up of this 18f4431 QEI, perhaps dspic QEI works better? I'm using 4.038 version, ... next step I will take a look at the assembly to see if the QEICON code is been right .... |
|
![](templates/subSilver/images/spacer.gif) |
|