Quadrature on PIC16f684

Thread Starter

Dalaran

Joined Dec 3, 2009
168
Hello, I am working on a school project in which we will most likely be using an Optical Encoder with Quadrature output to sense angle position.

Is it possible to do this type of software on a PIC16f684 or similar? I only have the ability to program 14pin microchip devices. I notice it only has one line for external interrupts so I'm not quite sure how this would be accomplished.

Any help is appreciated.
 
Last edited:

BMorse

Joined Sep 26, 2009
2,675
for using a quadrature encoder, you only need an interrupt for 1 input to determine rotation direction of the encoder.....

With a quadrature encoder you will have 2 outputs from it that are 90 degrees off phase to each other, You can use an interrupt for OutPut1 and just a regular input for OutPut2.

To determine rotation direction:

If OutPut1 is High and a pulse starts on OutPut2 then the encoder is turning clock wise (CW).

If OutPut1 is Low and a pulse starts on OutPut2 then encoder is turning counter clock wise (CCW).

You can update steps taken by encoder when interrupt fires, afterward you can do your slope and angle calculations....
 

Thread Starter

Dalaran

Joined Dec 3, 2009
168
Thank-you BMorse. So for each rising edge of say Output1 I set the interrupt to occur, I then immediately check Output2 to see if it is high or low to determine rotation direction. I could then count from the starting "zero" position how many counts left or right it is. I guess you could also take some time differences in pulses here to determine the rate of rotation (not sure if that is necessary yet). Let me know if I've got something mixed up somewhere. Thanks. Looks like I will be studying external interrupts tonight.
 

BMorse

Joined Sep 26, 2009
2,675
There is not a quadrature encoder but a quadrature count.That means counting the transition from low to high and from high to low for both encoder channels (A & B). This cannot be achieved with PIC16f684 without external logic or you you will need a specific pic with quadrature inputs (series 18F)

Alberto

Quadreature Encoder also known as Sine / Cosine encoder or incremental encoder....
The most common type of incremental encoder uses two output channels (A and B) to sense position. Using two code tracks with sectors positioned 90 degrees out of phase, the two output channels of the quadrature encoder indicate both position and direction of rotation. If A leads B, for example, the disk is rotating in a clockwise direction. If B leads A, then the disk is rotating in a counter-clockwise direction. By monitoring both the number of pulses and the relative phase of signals A and B, you can track both the position and direction of rotation.
Some quadrature encoders also include a third output channel, called a zero or index or reference signal, which supplies a single pulse per revolution. This single pulse is used for precise determination of a reference position.
You can achieve this without any external components besides the encoder and a couple of pull up resistors..... any PIC would work as long as it has atleast 1 interrupt pin.


I just did this with a Pic16F887, and only using RB0 (connected to output1 of encoder) as the interrupt source, and I can tell when it is going clockwise or counter clockwise, and also resolve the steps and speed in either direction....
 

AlexR

Joined Jan 16, 2008
732
The 16F684 will be fine for the job as all its portA pins can be configured to interrupt on change.

If you only have one interrupt line working on one edge transition, you get a quarter of the possible resolution out of the encoder.

If you have one line doing an interrupt on change you get half the resolution that the encoder is capable of giving.

To get the most out of the encoder you should configure both inputs to interrupt on change.
 

THE_RB

Joined Feb 11, 2008
5,438
Or just poll the inputs in a fast loop, you don't need interrupts really unless your PIC is busy doing many other tasks.

Simple code to get full quadrature resolution;
Rich (BB code):
	//----------------------------------------------------
	// read encoder
	encoder = PORTB;
	//----------------------------------------------------
	// check for any change of X encoder pins
	newX = (encoder & 0b11000000);   // keep 2 pins only
	if(newX != lastX)   // if changed
	{
		// now check direction (if newA != oldB)
		if(newX.F7 != lastX.F6) x_value++;
		else x_value--;

		lastX = newX;
	}

	//----------------------------------------------------
The code is from my "mini trackball" project here;
http://www.romanblack.com/trackball.htm
 

Thread Starter

Dalaran

Joined Dec 3, 2009
168
Thanks all for the help. I currently have interrupt flagged on the rising edge of output1 and then compare it to the current state of output2 (to determine rotation direction) and then I add or subtract one to the counter. As mentioned above this only gives me 1/4 of the possible resolution.

I am going to look into PORTA interrupts on change to hopefully get the full 1440 resolution out of this. Thanks again for the help all.

edit: I guess this brings up one question I have. I notice there is only one flag for interrupt on PORTA change, yet there are 6 pins on PORTA that can be enabled for this interrupt. If more than one pin is enabled, what is the best way to determine which pin caused the interrupt? Would it make sense to have a variable equal to the last state of the pins and then check which one has changed? Thanks.
 
Last edited:

AlexR

Joined Jan 16, 2008
732
Alberto:
Who said anything about 1000 count/turn or 3000 rpm? I would assume the OP has the sense work out his maximum pulse rate and tailor his detector to suit.
 

Thread Starter

Dalaran

Joined Dec 3, 2009
168
Yup thanks all. This is a low speed application and am expecting ~5 rpms. Will not have to worry about the speed of the MCU here.
 

THE_RB

Joined Feb 11, 2008
5,438
5 RPM as in one revolution every 12 seconds?

I'm sure you can forget the interrupts and just use a polling code. And some debounce code too will be needed when working with a sensor that slow.
 

Thread Starter

Dalaran

Joined Dec 3, 2009
168
Debounce code?

And yes, it will be slow speed application. There will be alot going on in the background so I'm not sure if just constantly polling the 2 pins is the best idea. But definitely something I will keep in mind.

Appreciate the help.
 

THE_RB

Joined Feb 11, 2008
5,438
Yep you should debounce the encoder inputs at low speeds, because vibration etc can cause multiple triggering on an encoder edge. Especially if it is on an engine or gearbox.

If it will only revolve in one direction you can debounce by only accepting the next encoder pin combination in the sequence.

Otherwise you need to debounce by time, which involves knowing the maximum rotating speed VS number of encoder events etc to give the longest debounce time possible that won't cause encoder corruption.
 
Top