Quadrature on PIC16f684

Discussion in 'Embedded Systems and Microcontrollers' started by Dalaran, Dec 3, 2009.

  1. Dalaran

    Thread Starter Active Member

    Dec 3, 2009
    168
    0
    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: Dec 3, 2009
  2. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234
    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....
     
  3. Dalaran

    Thread Starter Active Member

    Dec 3, 2009
    168
    0
    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.
     
  4. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234

    Quadreature Encoder also known as Sine / Cosine encoder or incremental encoder....
    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....
     
  5. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    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.
     
  6. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    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;
    Code ( (Unknown Language)):
    1.  
    2.     //----------------------------------------------------
    3.     // read encoder
    4.     encoder = PORTB;
    5.     //----------------------------------------------------
    6.     // check for any change of X encoder pins
    7.     newX = (encoder & 0b11000000);   // keep 2 pins only
    8.     if(newX != lastX)   // if changed
    9.     {
    10.         // now check direction (if newA != oldB)
    11.         if(newX.F7 != lastX.F6) x_value++;
    12.         else x_value--;
    13.  
    14.         lastX = newX;
    15.     }
    16.  
    17.     //----------------------------------------------------
    18.  
    The code is from my "mini trackball" project here;
    http://www.romanblack.com/trackball.htm
     
  7. Dalaran

    Thread Starter Active Member

    Dec 3, 2009
    168
    0
    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: Dec 4, 2009
  8. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    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.
     
  9. Dalaran

    Thread Starter Active Member

    Dec 3, 2009
    168
    0
    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.
     
  10. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    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.
     
  11. Dalaran

    Thread Starter Active Member

    Dec 3, 2009
    168
    0
    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.
     
  12. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    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.
     
Loading...