I am trying to set up some reference encoder for my team. We are using MPLAB with Vex Controller.
Is there a way that I can get the interrupt to be triggered on the raising or falling edge of the resulting encoder square wave?
Right now my code (below) just looks to see if the signal is high (0) or low (1), but if the encoder happens to stop when the signal is high , the encoder count just runs.
Kevin Waston provides some modular code for setting up encoders on the IFI hardware. The EDU hardware is closest to Vex, so I’d download that workspace. Any of the code can be easily ported to work with Vex, so I guess it doesnt matter.
That code will work as long as rc_dig_int1 is defined as the interrupt flag you want to look at and it is placed in the interrupt handler found in user_routines_fast.c. I’m guessing you are looking directly at the input pin, which is causing the code inside the If to execute every time.
This code isn’t using an interrupt handler, and so it can miss transitions. If you want to use an interrupt handler to count ticks as they come in, here are some instructions on how to modify the default code. The following assumes that you’re hooking up two encoders, right side connected to interrupt pin 1 and the left side connected to interrupt pin 2. It should be clear how to modify things if your setup is different. Using the higher numbered interrupt pins is a bit more work since they used a share interrupt instead of the nice dedicated interrupts for pins 1 and 2.
To get the encoder values, just look at the two globals. It would be better to wrap that lookup in code that disable interrupts, so you don’t risk having the value change in the middle of reading it. I can post that bit of code later, but I need to run right now.
user_routines.c
in the function “User_Initialization” add this line:
EnableInterrupts();
user_routines.h
in the Function Prototypes section, add these lines:
extern volatile int g_distMotorLeft;
extern volatile int g_distMotorRight;
void EnableInterrupts(void);
user_routines_fast.c
below this line:
/*** DEFINE USER VARIABLES AND INITIALIZE THEM HERE ***/
add these lines:
volatile int g_distMotorLeft = 0;
volatile int g_distMotorRight = 0;
replace the entire InterruptHandlerLow function with a new version and two more functions:
void InterruptHandlerLow ()
{
unsigned char int_byte;
if (INTCON3bits.INT2IF && INTCON3bits.INT2IE) /* The INT2 pin is RB2/DIG I/O 1. */
{
INTCON3bits.INT2IF = 0;
++g_distMotorRight;
}
else if (INTCON3bits.INT3IF && INTCON3bits.INT3IE) /* The INT3 pin is RB3/DIG I/O 2. */
{
INTCON3bits.INT3IF = 0;
++g_distMotorLeft;
}
else if (INTCONbits.RBIF && INTCONbits.RBIE) /* DIG I/O 3-6 (RB4, RB5, RB6, or RB7) changed. */
{
int_byte = PORTB; /* You must read or write to PORTB */
INTCONbits.RBIF = 0; /* and clear the interrupt flag */
} /* to clear the interrupt condition. */
}
void ResetEncoders()
{
g_distMotorLeft = 0;
g_distMotorRight = 0;
}
void EnableInterrupts()
{
// interrupt 2, which is pin 1
TRISBbits.TRISB2 = 1; // make sure pin is configured as an input
INTCON3bits.INT2IP = 0; // interrupt is low priority
INTCON2bits.INTEDG2 = 1; // trigger on rising edge
INTCON3bits.INT2IF = 0; // make sure interrupt flag is clear before enabling
INTCON3bits.INT2IE = 1; // enable the interrupt
// interrupt 3, which is pin 2
TRISBbits.TRISB3 = 1; // make sure pin is configured as an input
INTCON2bits.INT3IP = 0; // interrupt is low priority
INTCON2bits.INTEDG3 = 1; // trigger on rising edge
INTCON3bits.INT3IF = 0; // make sure interrupt flag is clear before enabling
INTCON3bits.INT3IE = 1; // enable the interrupt
}