+ Post New Thread
Results 1 to 8 of 8
  1. #1
    Advanced Member level 2
    Points: 2,628, Level: 11
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    513
    Helped
    48 / 48
    Points
    2,628
    Level
    11

    How to read incremental rotary (quadrature) encoder?

    How to read incremental rotary (quadrature) encoder?

    The rotary encoder has two connections for signals namely A and B.

    I have to use 3 pins of microcontroller (PIC16F) to read it.

    I have used PIC16F877A and connections are also below.

    A -> RB1
    B -> RB2
    A xor B (using xor gate) -> RB0/INT

    I need to use external interrupt to detect change in rotary encoder state and increment or decrement a counter.

    This is the code that I have written but the counter is always 0.

    Code C - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    
    // LCD module connections
    sbit LCD_RS at RD4_bit;
    sbit LCD_EN at RD5_bit;
    sbit LCD_D4 at RD0_bit;
    sbit LCD_D5 at RD1_bit;
    sbit LCD_D6 at RD2_bit;
    sbit LCD_D7 at RD3_bit;
     
    sbit LCD_RS_Direction at TRISD4_bit;
    sbit LCD_EN_Direction at TRISD5_bit;
    sbit LCD_D4_Direction at TRISD0_bit;
    sbit LCD_D5_Direction at TRISD1_bit;
    sbit LCD_D6_Direction at TRISD2_bit;
    sbit LCD_D7_Direction at TRISD3_bit;
    // End LCD module connections
     
    sbit EncoderA_bit at RB1_bit;
    sbit EncoderB_bit at RB2_bit;
    sbit EncoderINT_bit at RB0_bit;
     
    signed char counter = 0;
    char msg[17];
    char txt1[] = " ROTARY ENCODER ";
    char txt2[] = "COUNT: ";
     
    void interrupt() {
        if((INTE_bit) && (INTF_bit)) {
            INTF_bit = 0;
            //counter++;
            if((EncoderA_bit != RB1_bit)||(EncoderB_bit != RB2_bit)){
                if(EncoderB_bit ^ RB1_bit){
                     counter++;
                }
     
                if(EncoderA_bit ^ RB2_bit){
                     counter--;
                }
     
                EncoderA_bit = RB1_bit;
                EncoderB_bit = RB2_bit;
        }
        }
    }
     
    void main() {
        TRISB = 0x07;
        TRISD = 0x00;
        PORTB = 0x00;
        PORTD = 0x00;
        
        Lcd_Init();
        Lcd_Cmd(_LCD_CURSOR_OFF);
        Lcd_Cmd(_LCD_CLEAR);
        Lcd_Out(1,1,txt1);
        Lcd_Out(2,1,txt2);
        
        Delay_ms(100);
        INTEDG_bit = 0;
        INTF_bit = 0;
        INTE_bit = 1;
        PEIE_bit = 1;
        GIE_bit = 1;
        
        while(1) {
              ByteToStr(counter,msg);
              strcat(msg," ");
              Lcd_Out(2,7,msg);
        }
    }

    Schematic

    •   AltAdvertisment

        
       

  2. #2
    Super Moderator
    Points: 78,759, Level: 68
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    12,896
    Helped
    4306 / 4306
    Points
    78,759
    Level
    68

    Re: How to read incremental rotary (quadrature) encoder?

    You only need two signals. A and B.
    1. Use one of them (lets call it A) to trigger an edge INT interrupt.
    2. In the ISR, read 'B', it tells you the direction
    3. change your 'counter' value accordingly.

    If you also want to incorporate acceleration, reset a timer at each interrupt and look at it's value on the next interrupt. If it is small enough (= rotating fast) add more to the counter.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.



    •   AltAdvertisment

        
       

  3. #3
    Super Moderator
    Points: 73,905, Level: 66
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    14,986
    Helped
    3415 / 3415
    Points
    73,905
    Level
    66

    Re: How to read incremental rotary (quadrature) encoder?

    Hi,

    It depends what you want to do with it.
    Brians solution is good for input devices like the ALPS EC11 encoders.

    But if you want to do position control it suffers from loss of position steps during change of direction.

    Klaus
    Please donīt contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



    •   AltAdvertisment

        
       

  4. #4
    Super Moderator
    Points: 255,118, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    44,446
    Helped
    13541 / 13541
    Points
    255,118
    Level
    100

    Re: How to read incremental rotary (quadrature) encoder?

    You have a serious confusion with RB1_bit and EncoderA_bit respectively RB2_bit and EncoderB_bit. Encoderxx is defined as alias of the RBx, but should be a variable holding the previous input state.

    Apart form this problem, the code should work. There's a possible complication with bouncing encoder outputs, RB1 and RB2 should be better copied to variables first, so that all instructions referring to it are using the same value.

    The XOR logic and INT input can be saved by using Port B interrupt an change function.

    You only need two signals. A and B.
    1. Use one of them (lets call it A) to trigger an edge INT interrupt.
    2. In the ISR, read 'B', it tells you the direction
    3. change your 'counter' value accordingly.
    Possible, but at the expense of loosing 3 of 4 available encoder steps. The simple logic also can't handle encoder rotated back and forth and gives potentially wrong counts.


    1 members found this post helpful.

  5. #5
    Advanced Member level 2
    Points: 2,628, Level: 11
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    513
    Helped
    48 / 48
    Points
    2,628
    Level
    11

    Re: How to read incremental rotary (quadrature) encoder?

    Thanks all. Betwixt's method works fine. I don't need acceleration or position control. I am just using Rotary Encoder to select 4 different PWM frequencies for DC-DC Converter.

    I removed the XOR gate and connected A to RB0/INT and B to RB1 and read in ISR.

    Code is working fine now.

    I need a little modification and I don't know how to implement it.

    The rotary encoder has one more signal connection that is:

    SW pin and it is used to provide signal for rotary encoder button press.

    I want to know how I can connect

    A
    B
    SW pins to PIC16F877A.

    A needs INT pin
    B needs DigitalInput pin
    SW needs INT pin

    and I have only one INT pin and I can't change the controller.

    I need to use same INT pin for A and SW signals and counter should not increment when SW signals is given.
    Last edited by baileychic; 18th April 2019 at 11:10.



    •   AltAdvertisment

        
       

  6. #6
    Super Moderator
    Points: 73,905, Level: 66
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    14,986
    Helped
    3415 / 3415
    Points
    73,905
    Level
    66

    Re: How to read incremental rotary (quadrature) encoder?

    Hi,

    Use a standard input for the SW.

    Poll the SW with with a frequency higher than 20Hz (50ms).

    Klaus
    Please donīt contact me via PM, because there is no time to respond to them. No friend requests. Thank you.


    1 members found this post helpful.

  7. #7
    Super Moderator
    Points: 78,759, Level: 68
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    12,896
    Helped
    4306 / 4306
    Points
    78,759
    Level
    68

    Re: How to read incremental rotary (quadrature) encoder?

    I agree with Klaus, you would need significant extra electronics to externally multiplex SW with the encoder output and for such a low priority function it isn't worth the extra effort. Just connect SW to another digital input and poll it.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.


    1 members found this post helpful.

  8. #8
    Super Moderator
    Points: 255,118, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    44,446
    Helped
    13541 / 13541
    Points
    255,118
    Level
    100

    Re: How to read incremental rotary (quadrature) encoder?

    How about using RB4 to RB7 interrupt on change function?

    Key detection needs only moderate scan rate, it's very unusual to use interrupt for it. Incremental decoder depends on the application, pulse rate can be between a few Hz and 10s of kHz.


    1 members found this post helpful.

--[[ ]]--