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 QEI mismatch Direction of Rotation Status Bit
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

pic18f4431 QEI mismatch Direction of Rotation Status Bit
PostPosted: Thu Feb 14, 2008 6:30 pm     Reply with quote

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
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 14, 2008 10:23 pm     Reply with quote

See this topic, and look at the FAQ article in Darren's post:
http://www.ccsinfo.com/forum/viewtopic.php?t=18356
Guest








PostPosted: Fri Feb 15, 2008 5:07 am     Reply with quote

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
Ken Johnson



Joined: 23 Mar 2006
Posts: 197
Location: Lewisburg, WV

View user's profile Send private message

PostPosted: Fri Feb 15, 2008 9:35 am     Reply with quote

Guest, delay_xx() will not disable interrupts.

You may want to use the restart_wdt option in your #use delay line.

Ken
andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Mon Feb 18, 2008 6:55 pm     Reply with quote

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)

andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Tue Feb 19, 2008 6:35 pm     Reply with quote

Any rags, any bones, any bottles today? Laughing Laughing
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

PostPosted: Tue Feb 19, 2008 9:50 pm     Reply with quote

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
andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Wed Feb 20, 2008 5:30 am     Reply with quote

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
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

PostPosted: Wed Feb 20, 2008 4:38 pm     Reply with quote

I have an old bag of bones. Genuine one owner, had them for 62 years Very Happy

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
andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Thu Feb 21, 2008 5:43 am     Reply with quote

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);
   }
   

   

}
andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Thu Feb 21, 2008 8:40 am     Reply with quote

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 )
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

PostPosted: Thu Feb 21, 2008 4:16 pm     Reply with quote

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
andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Thu Feb 21, 2008 7:46 pm     Reply with quote

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...
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

PostPosted: Thu Feb 21, 2008 11:39 pm     Reply with quote

Can be programmed with LVP, but doesn't have to be Smile

If LVP mode then RB5 would need to held low after programming.
Is the lcd on port d?
andredurao



Joined: 24 Apr 2006
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Fri Feb 22, 2008 7:05 am     Reply with quote

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 ....
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  Next
Page 1 of 2

 
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