decoding quadrature encoders


Closed Thread
Results 1 to 40 of 94

Hybrid View

  1. #1
    cbrun17's Avatar
    cbrun17 Guest


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Thank you Richard. I will test this and let you know the results.

    Also, though the encoder is optical, I am going through a 74C14 hex Schmitt trigger with rc filtering to remove any stray noise. all cabling from the encoder is shielded. Monitoring the output results in clean square wave with fast rise and fall times.

    Chris

  2. #2
    cbrun17's Avatar
    cbrun17 Guest


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Hi Richard,

    The asm change you suggested worked like a charm. I now get the correct counts!

    Just had to make one other change that I hoped you could explain to me. Once I made the change to check the STATUS instead of _enc_tmp,7 bit, my counting was all backwards.
    By changing the direction test from "btfsc _enc_old,7" to "btfss _enc_old,7", the issue was resolved. So basically the bit value for _enc_old,7 is set rather than clear on cw.

    I can't express how grateful I am for all the help from both you and Henrik.

    Here is the working code. I hope others will find this useful.

    Code:
    'Read Quadrature Encoder and display value on LCD in .25 increments. for pic16f876
    
     '************************ DEFINES HERE *************************************
     DEFINE OSC 20 ' set to 20mhz
     DEFINE LCD_DREG PORTA ' Set Data Registers port
     DEFINE LCD_DBIT 0 ' Set starting data bit
     DEFINE LCD_RSREG PORTB ' Set LCD RS Port
     DEFINE LCD_RSBIT 1 ' Set LCD RS Bit
     DEFINE LCD_EREG PORTB ' Set LCD Enable Port
     DEFINE LCD_EBIT 2 ' Set LCD Enable Bit
     DEFINE LCD_BITS 4 ' Set LCD 4bit Mode
     DEFINE LCD_LINES 2 ' Set number of LCD Lines
     DEFINE LCD_COMMANDUS 2000 ' Set Command Delay time in uS
     DEFINE LCD_DATAUS 60 ' Set Data delay time in uS 
    
     clear 'clear out variables
    
     '*********************** CHIP REGISTER SETUP *******************************
    
     ADCON0 = 7 ' turn off analog porta, set to digital IO
     ADCON1 = 7 '
     CCP1CON = 0
     CCP2CON = 0
     
     TRISA = %00000000 ' output ports
     TRISB = %11000000 ' set input and output ports
     TRISC = %00100000 ' output ports
      
     portB.4 = 0
     portB.5 = 0
     
     '************************ PROGRAM VARIABLES HERE ***************************
    
     symbol   ledUp     = portC.2 ' status led
     symbol   ledDown = portC.3 ' status led2
     symbol   lcdbkl     = portC.4 ' lcd pannel backlight
     symbol   sw1        = portC.5 ' encoder switch
     symbol   ledTest   = portC.6
     
    
     enc_old                VAR BYTE
     enc_new              VAR BYTE
     enc_tmp              VAR byte
     enc_counter         VAR word bank0
     enc_counter_old   VAR word bank0
     enc_scaler            VAR word
     enc_dir                VAR enc_old.bit7
     Counter               VAR word bank0
     enc_SIGN            VAR counter.bit15
     Sign                    VAR BIT
    
    
     '*********************** ASSEMBLY INTERUPT VARIABLES ***********************
     wsave     VAR  byte $20 system
     wsave1   VAR  byte $a0 system ' Necessary for devices with RAM in bank1
     wsave2   VAR  byte $120 system ' Necessary for devices with RAM in bank2
     wsave3   VAR  byte $1a0 system ' Necessary for devices with RAM in bank3
     ssave     VAR  byte bank0 system
     psave     VAR  byte bank0 system 
    
     goto start 'skip over interupt handler
     '*********************** ASSEMBLY INTERUPT HANDLER *************************
    
     define INTHAND myint
     Asm
    
    myint 
     ; Save W, STATUS and PCLATH registers
     ;movwf wsave
     ;swapf STATUS, W
     ;clrf STATUS
     ;movwf ssave
     ;movf PCLATH, W
     ;movwf psave 
     ;CLRF PCLATH
    
    
     ;====== BEGINNING OF THE ROTARY ENCODER CODE ========
     ;The Rotary Encoder is connected to PORTB 
     ;The A signal of the encoder connected to the PIN portB.7
     ;The B signal of the encoder connected to the PIN portB.6
     ;
     ;The 4 variables used are declared in the PicBasic code.
     ;
     ; enc_new VAR BYTE
     ; enc_old VAR BYTE
     ; enc_tmp VAR BYTE
     ; enc_counter VAR WORD
     ;
     ;================================================
    
     ;Read latest input from PORTB & put the value in _enc_new.
     movf PORTB,W
     movwf _enc_new
    
     ;Strip off all but the 2 MSBs in _enc_new.
     movlw 0xc0 ;Create bit mask (bits 7 & 6). b'11000000' ?
     andwf _enc_new,F ;Zero bits 5 thru 0.
    
        ;Check to see if encoder has moved
            movf    _enc_old,W         ;move enc_old to W
            movwf   _enc_tmp           ;put W to enc_tmp
            movf    _enc_new,W         ;move enc_new to W for XOR
            xorwf   _enc_tmp,F         ;XOR enc_tmp to detect encoder movement
            btfsc   STATUS,Z           ;if result is not zero, encoder moved.      
            goto    Continue           ;no movement exit isr
    
     ;Determine the direction of the Rotary encoder. 
     rlf _enc_old,F ;left shift it into _enc_old to align bit 6 of _enc_old with bit 7 of _enc_new.
    
     movf _enc_new,W ;Move the contents of _enc_new to W in order to XOR.
     xorwf _enc_old,F ;XOR previous inputs (in _enc_old) with latest
     ;inputs (in W) to determine CW or CCW.
    
     btfsc _enc_old,7 ;Test bit 7 of result (in _enc_old). Skip next line
     ;if it is 0 (direction is CCW).
     goto Up ;Bit is 1 (direction is CW). Go around Down and increment counter.
    
    Down
     ;Decrements _enc_counter because the rotary encoder moved CCW.
     ;Decrements _enc_counter (16 bit value), sets Z on exit.
    
     decf _enc_counter,F ; Decrement low byte
     incfsz _enc_counter,W ; Check for underflow
     incf _enc_counter+1,F ; Update
     decf _enc_counter+1,F ; Fixup
     movf _enc_counter,W
     iorwf _enc_counter+1,W ; Set Z bit
    
    
     ;Add here code for the CCW LED if needed.
     bsf _ledDown ;turn on led
    
     goto Continue ;Branch around UP.
    
    Up
     ;Increments _enc_counter because the rotary encoder moved CW.
     ;Increments _enc_counter (16 bit value), sets Z on exit.
    
     incfsz _enc_counter,W ; Add one to low byte
     decf _enc_counter+1,F ; No carry (negates next step)
     incf _enc_counter+1,F ; Add one to high byte
     movwf _enc_counter ; Store updated low byte back.
     iorwf _enc_counter+1,W ; Set Z flag
    
    
     ;Add here code for the CW LED if needed.
     bsf _ledUp ;turn on led
    
    Continue 
     ;Assign the latest encoder inputs (in _enc_new) to _enc_old.
     movf _enc_new,W
     movwf _enc_old
    
     ; Restore saved registers
     movf  psave, W
     movwf PCLATH
     swapf ssave, W
     movwf STATUS
     swapf wsave, F
     swapf wsave, W
     bcf INTCON, RBIF ; Clear the Interupt Flag
     RETFIE ; Return from interrupt
     endasm
    
     '************************************************* **************************
     '************************* PROGRAM STARTS HERE *****************************
     '************************************************* **************************
    
     START: ' Main Program starts here
     INTCON = %10001000 ' Enable PortB Change Interupts 
     LCDOUT $FE,1 'Init The LCD
     pause 500 'wait for LCD to start 
    
     lcdout $FE,$80,  "TEST ANGLE DISP " 'display splash screen
     LCDOUT $FE,$C0,  "Initializing... " 
     high lcdbkl ' turn on backlight
    
    
     '************************** SET DEFAULT SETTINGS HERE **********************
     pause 2000 ' just wait a bit to read splash screen
     lcdout $FE,1
     enc_counter = 0 ' set default encoder value
     enc_counter_old = 0 
     Counter = 0
     
     
     lcdout $FE,$80, "Measurement   "
     lcdout $FE,$C0,"TST ANGLE: "
    
    
     '************************** TESTING ROUTINES HERE **************************
     test:
       If portC.5 = 0 then clearall
       
    if enc_counter <> enc_counter_old then 'see if value has changed
        enc_counter_old = enc_counter 'move new value to old
            Counter = enc_counter '(enc_counter */ 250)/2
            Sign = Counter.15   ' Save sign
            Counter = ((ABS Counter) * 25) ' Degrees is now 0 to 900
            
    
    If Sign THEN Counter = -Counter ' Restore sign, value is now -900 to 900
    
    
    If not sign AND (-Counter > 0 or Counter < 0) then
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", "-",sdec Counter /100 , ".", sdec Counter // 100, " " 
    else
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", " ", sdec -Counter /100 , ".", sdec -Counter // 100, " "
    endif 
    
     
     low ledUp 'turn off CCW led
     low ledDown 'turn off CW led
     endif
     
     goto test
    
     ClearAll:
     
        enc_counter = 0
        enc_counter_old = 0 
        Counter = 0
        clear
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", " 0.00 "
            high ledtest
                pause 1000
            low ledtest
     goto test
     
    @INT_RETURN

  3. #3
    cbrun17's Avatar
    cbrun17 Guest


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Hi Richard,

    The asm change you suggested worked like a charm. I now get the correct counts!

    Just had to make one other change that I hoped you could explain to me. Once I made the change to check the STATUS instead of _enc_tmp,7 bit, my counting was all backwards.
    By changing the direction test from "btfsc _enc_old,7" to "btfss _enc_old,7", the issue was resolved. So basically the bit value for _enc_old,7 is set rather than clear on cw.

    I can't express how grateful I am for all the help from both you and Henrik.

    Here is the working code. I home others will find this useful.

    Code:
    'Read Quadrature Encoder and display value on LCD in .25 increments. for pic16f876
    
     '************************ DEFINES HERE *************************************
     DEFINE OSC 20 ' set to 20mhz
     DEFINE LCD_DREG PORTA ' Set Data Registers port
     DEFINE LCD_DBIT 0 ' Set starting data bit
     DEFINE LCD_RSREG PORTB ' Set LCD RS Port
     DEFINE LCD_RSBIT 1 ' Set LCD RS Bit
     DEFINE LCD_EREG PORTB ' Set LCD Enable Port
     DEFINE LCD_EBIT 2 ' Set LCD Enable Bit
     DEFINE LCD_BITS 4 ' Set LCD 4bit Mode
     DEFINE LCD_LINES 2 ' Set number of LCD Lines
     DEFINE LCD_COMMANDUS 2000 ' Set Command Delay time in uS
     DEFINE LCD_DATAUS 60 ' Set Data delay time in uS 
    
     clear 'clear out variables
    
     '*********************** CHIP REGISTER SETUP *******************************
    
     ADCON0 = 7 ' turn off analog porta, set to digital IO
     ADCON1 = 7 '
     CCP1CON = 0
     CCP2CON = 0
     
     TRISA = %00000000 ' output ports
     TRISB = %11000000 ' set input and output ports
     TRISC = %00100000 ' output ports
      
     portB.4 = 0
     portB.5 = 0
     
     '************************ PROGRAM VARIABLES HERE ***************************
    
     symbol   ledUp     = portC.2 ' status led
     symbol   ledDown = portC.3 ' status led2
     symbol   lcdbkl     = portC.4 ' lcd pannel backlight
     symbol   sw1        = portC.5 ' encoder switch
     symbol   ledTest   = portC.6
     
    
     enc_old                VAR BYTE
     enc_new              VAR BYTE
     enc_tmp              VAR byte
     enc_counter         VAR word bank0
     enc_counter_old   VAR word bank0
     enc_scaler            VAR word
     enc_dir                VAR enc_old.bit7
     Counter               VAR word bank0
     enc_SIGN            VAR counter.bit15
     Sign                    VAR BIT
    
    
     '*********************** ASSEMBLY INTERUPT VARIABLES ***********************
     wsave     VAR  byte $20 system
     wsave1   VAR  byte $a0 system ' Necessary for devices with RAM in bank1
     wsave2   VAR  byte $120 system ' Necessary for devices with RAM in bank2
     wsave3   VAR  byte $1a0 system ' Necessary for devices with RAM in bank3
     ssave     VAR  byte bank0 system
     psave     VAR  byte bank0 system 
    
     goto start 'skip over interupt handler
     '*********************** ASSEMBLY INTERUPT HANDLER *************************
    
     define INTHAND myint
     Asm
    
    myint 
     ; Save W, STATUS and PCLATH registers
     ;movwf wsave
     ;swapf STATUS, W
     ;clrf STATUS
     ;movwf ssave
     ;movf PCLATH, W
     ;movwf psave 
     ;CLRF PCLATH
    
    
     ;====== BEGINNING OF THE ROTARY ENCODER CODE ========
     ;The Rotary Encoder is connected to PORTB 
     ;The A signal of the encoder connected to the PIN portB.7
     ;The B signal of the encoder connected to the PIN portB.6
     ;
     ;The 4 variables used are declared in the PicBasic code.
     ;
     ; enc_new VAR BYTE
     ; enc_old VAR BYTE
     ; enc_tmp VAR BYTE
     ; enc_counter VAR WORD
     ;
     ;================================================
    
     ;Read latest input from PORTB & put the value in _enc_new.
     movf PORTB,W
     movwf _enc_new
    
     ;Strip off all but the 2 MSBs in _enc_new.
     movlw 0xc0 ;Create bit mask (bits 7 & 6). b'11000000' ?
     andwf _enc_new,F ;Zero bits 5 thru 0.
    
        ;Check to see if encoder has moved
            movf    _enc_old,W         ;move enc_old to W
            movwf   _enc_tmp           ;put W to enc_tmp
            movf    _enc_new,W         ;move enc_new to W for XOR
            xorwf   _enc_tmp,F         ;XOR enc_tmp to detect encoder movement
            btfsc   STATUS,Z           ;if result is not zero, encoder moved.      
            goto    Continue           ;no movement exit isr
    
     ;Determine the direction of the Rotary encoder. 
     rlf _enc_old,F ;left shift it into _enc_old to align bit 6 of _enc_old with bit 7 of _enc_new.
    
     movf _enc_new,W ;Move the contents of _enc_new to W in order to XOR.
     xorwf _enc_old,F ;XOR previous inputs (in _enc_old) with latest
     ;inputs (in W) to determine CW or CCW.
    
     btfsc _enc_old,7 ;Test bit 7 of result (in _enc_old). Skip next line
     ;if it is 0 (direction is CCW).
     goto Up ;Bit is 1 (direction is CW). Go around Down and increment counter.
    
    Down
     ;Decrements _enc_counter because the rotary encoder moved CCW.
     ;Decrements _enc_counter (16 bit value), sets Z on exit.
    
     decf _enc_counter,F ; Decrement low byte
     incfsz _enc_counter,W ; Check for underflow
     incf _enc_counter+1,F ; Update
     decf _enc_counter+1,F ; Fixup
     movf _enc_counter,W
     iorwf _enc_counter+1,W ; Set Z bit
    
    
     ;Add here code for the CCW LED if needed.
     bsf _ledDown ;turn on led
    
     goto Continue ;Branch around UP.
    
    Up
     ;Increments _enc_counter because the rotary encoder moved CW.
     ;Increments _enc_counter (16 bit value), sets Z on exit.
    
     incfsz _enc_counter,W ; Add one to low byte
     decf _enc_counter+1,F ; No carry (negates next step)
     incf _enc_counter+1,F ; Add one to high byte
     movwf _enc_counter ; Store updated low byte back.
     iorwf _enc_counter+1,W ; Set Z flag
    
    
     ;Add here code for the CW LED if needed.
     bsf _ledUp ;turn on led
    
    Continue 
     ;Assign the latest encoder inputs (in _enc_new) to _enc_old.
     movf _enc_new,W
     movwf _enc_old
    
     ; Restore saved registers
     movf  psave, W
     movwf PCLATH
     swapf ssave, W
     movwf STATUS
     swapf wsave, F
     swapf wsave, W
     bcf INTCON, RBIF ; Clear the Interupt Flag
     RETFIE ; Return from interrupt
     endasm
    
     '************************************************* **************************
     '************************* PROGRAM STARTS HERE *****************************
     '************************************************* **************************
    
     START: ' Main Program starts here
     INTCON = %10001000 ' Enable PortB Change Interupts 
     LCDOUT $FE,1 'Init The LCD
     pause 500 'wait for LCD to start 
    
     lcdout $FE,$80,  "TEST ANGLE DISP " 'display splash screen
     LCDOUT $FE,$C0,  "Initializing... " 
     high lcdbkl ' turn on backlight
    
    
     '************************** SET DEFAULT SETTINGS HERE **********************
     pause 2000 ' just wait a bit to read splash screen
     lcdout $FE,1
     enc_counter = 0 ' set default encoder value
     enc_counter_old = 0 
     Counter = 0
     
     
     lcdout $FE,$80, "Measurement   "
     lcdout $FE,$C0,"TST ANGLE: "
    
    
     '************************** TESTING ROUTINES HERE **************************
     test:
       If portC.5 = 0 then clearall
       
    if enc_counter <> enc_counter_old then 'see if value has changed
        enc_counter_old = enc_counter 'move new value to old
            Counter = enc_counter '(enc_counter */ 250)/2
            Sign = Counter.15   ' Save sign
            Counter = ((ABS Counter) * 25) ' Degrees is now 0 to 900
            
    
    If Sign THEN Counter = -Counter ' Restore sign, value is now -900 to 900
    
    
    If not sign AND (-Counter < 0 or Counter > 0) then
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", "-",sdec Counter /100 , ".", sdec Counter // 100, " " 
    else
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", " ", sdec -Counter /100 , ".", sdec -Counter // 100, " "
    endif 
    
     
     low ledUp 'turn off CCW led
     low ledDown 'turn off CW led
     endif
     
     goto test
    
     ClearAll:
     
        enc_counter = 0
        enc_counter_old = 0 
        Counter = 0
        clear
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", " 0.00 "
            high ledtest
                pause 1000
            low ledtest
     goto test
     
    @INT_RETURN

  4. #4
    Join Date
    May 2013
    Location
    australia
    Posts
    2,632


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Just had to make one other change that I hoped you could explain to me. Once I made the change to check the STATUS instead of _enc_tmp,7 bit, my counting was all backwards.
    By changing the direction test from "btfsc _enc_old,7" to "btfss _enc_old,7", the issue was resolved. So basically the bit value for _enc_old,7 is set rather than clear on cw.
    Direction is a matter of interpretation.
    changing the direction test from "btfsc _enc_old,7" to "btfss _enc_old,7 OR
    changing the direction test from "btfsc _enc_old,6" to "btfsc _enc_old,6 OR
    swaping the "A","B" connections ,will all cause the "direction " to reverse


    I notice you are still incorrectly not saving the mcu context upon isr entry
    Warning I'm not a teacher

  5. #5
    cbrun17's Avatar
    cbrun17 Guest


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Hi Richard,

    Not sure why my last post went in twice... Sorry.

    When I added the mcu context save routine the display crashed. It will ~ work if I move the shaft slowly, however, moving quickly caused the code to trip over itself and lockup the screen.
    My first guess was that when jumping out of the ISR, the next return in the main program uses the most recent return address on the stack and returns to the point the interrupt occurred, crashing the program.

    However, I noticed my up/down LED indicators are still operational which suggests the code is still working okay and its either the formatting or calculations that are causing some latency. if I perform a display reset, the counting resumes normally.

    So I made two changes which seem to have resolved the issue.

    I removed the two LCD defines:
    DEFINE LCD_COMMANDUS 2000 ' Set Command Delay time in uS
    DEFINE LCD_DATAUS 60 ' Set Data delay time in uS

    And added a 50ms pause after the display routine to give the display time to settle.

    I know there must be a more efficient way to format the display to reduce the number of instructions necessary to accomplish the xx.xx by .25 increment, but this seems to smooth out he results.

    Thanks again for you feedback.

    Chris
    Last edited by cbrun17; - 11th February 2017 at 17:37.

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Hi Chris,
    In your test routine loop you're re-Writing alot of static text on the LCD and you're doing some "strange" things to get the correct formating. Here's an idea which probably is a bit more efficient:
    Code:
     ' Print static information on LCD once, then leave it alone.
     lcdout $FE,$80, "Measurement   "
     lcdout $FE,$C0,"TST ANGLE: "
    
    
     '************************** TESTING ROUTINES HERE **************************
     test:
       If portC.5 = 0 then clearall
       
    if enc_counter <> enc_counter_old then 'see if value has changed
      enc_counter_old = enc_counter  ' move new value to old
      Counter = enc_counter
      Sign = Counter.15              ' Save sign
      Counter = ((ABS Counter) * 25) ' Degrees is now 0 to 900
            
      ' Not doing this here, later (or not at all).
      'If Sign THEN Counter = -Counter ' Restore sign, value is now -900 to 900
    
      LCDOUT $FE, $CB   'Position cursor at 11th character on 2nd row.
      IF SIGN THEN
        LCDOUT "-"
      ELSE
        LCDOUT " "
      ENDIF
    
      LCDOUT DEC Counter / 100, ".", DEC Counter // 100, " " 
    
      ' To save execution cycles you're better off not using HIGH/LOW
      low ledUp 'turn off CCW led
      low ledDown 'turn off CW led
    
      ' If the only purpose of the Counter variable is to display the value 
      ' the there's no need to restore the sign of it so the following line
      ' could be deleted.
      If Sign THEN Counter = -Counter ' Restore sign, value is now -900 to 900
    
    endif
     
    goto test
    /Henrik.

  7. #7
    cbrun17's Avatar
    cbrun17 Guest


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Hi Henrik,

    I changed the display routine as you described and it does work much better. I sure do over think some of this stuff... I did have to increase the pause to 250ms to allow for the display to update since it seemed to trip over itself a little more frequently this way.

    I believe moving to either serial LCD or 7 seg LED might be the better solution.

    Thanks again for your expert advise.

    Chris
    Last edited by cbrun17; - 11th February 2017 at 19:28.

  8. #8
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,166


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Excuse me Henrik, If you read the spec. sheet you can set the interrupt edge for the INT0 and INT1. It is not required to set it each time. Also the interrupt routine look like:
    '************************************************* ********************
    INC_C: 'INTERRUPT SERVICE ROUTINE FOR EXTERNAL INTERRUPT-0
    '************************************************* ********************
    POSITION = POSITION + 1
    @ INT_RETURN

    '************************************************* ********************
    DEC_C: 'INTERRUPT SERVICE ROUTINE FOR EXTERNAL INTERRUPT-1
    '************************************************* ********************
    POSITION = POSITION - 1
    @ INT_RETURN

    That's all there is to it.
    Dave Purola,
    N8NTA
    EN82fn

  9. #9


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Quote Originally Posted by cbrun17 View Post
    Thank you Richard. I will test this and let you know the results.

    Also, though the encoder is optical, I am going through a 74C14 hex Schmitt trigger with rc filtering to remove any stray noise. all cabling from the encoder is shielded. Monitoring the output results in clean square wave with fast rise and fall times.

    Chris
    Out of curiosity, what R/C values did you find to be optimal on your schmitt triggers?

    Picster

  10. #10


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Quote Originally Posted by picster View Post
    Out of curiosity, what R/C values did you find to be optimal on your schmitt triggers?

    Picster
    Ok, I did some trials myself and ended up with R1=100k, R2=33k, C=0.1uF working well with Schmitt trigger inputs on the PIC I'm using (see circuit attached). That's with a detented encoder, using the same values for the two rotary outputs AND the built-in pushbutton.
    Name:  schmitt.jpg
Views: 862
Size:  11.2 KB

  11. #11
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,125


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    I would use 10th of this values.

    Ioannis

  12. #12


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Quote Originally Posted by Ioannis View Post
    I would use 10th of this values.

    Ioannis
    You certainly could. Yet this works great in my application, for which I am using switch polling, not interrupts. I would imagine it also depends on the characteristics of the encoder.

  13. #13
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,125


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Of course it does. But I am worried about the input impedance of the PIC and leakage currents.

    Ioannis

  14. #14


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    Hey Ioannis,

    I'm hoping you can shed some additional light on this for me.

    I know the "design standard" is to use a 10k pullup for PIC inputs that switch to ground - which from my understanding is really not so much about leakage, but more about noise on the "antenna" that an input wire or trace can become. The internal weak pullups tend to work on a breadboard or on a PC board, as long as the system isn't subject to much electrical noise, but "guaranteeing" that environment is far from possible in real world applications. The internal "weak pullups" have equivalent impedance ranges from 200k to 16k, per PIC specs. Meanwhile, input impedance for ports works out to around 50Mohms per specs. I agree, it is always good to have a "solid" and unquestionable pull-up instead of something where spurious glitches can put you into nebulous range, particularly with an input that's NOT configured as a schmitt trigger and you can get all kinds of undefined questionable results. Absolutely makes sense to use "tried and true" 10k in these situations.

    However, despite the above, part of the benefit of using a capacitor on the input (again, only with the schmitt trigger config) is that it will help to eliminate spurious noise, effectively shunting spikes to ground and only letting relatively persistent voltage levels through. Hence the reason, I believe, why these values may be demonstrated to work for a schmitt trigger input configuration. I picked these values around the 0.1uF capacitor since I have a ton of them.

    Does this make sense, or am I missing something else that I should be considering?

Similar Threads

  1. Quick thoughts: DT Ints with encoders
    By kevlar129bp in forum mel PIC BASIC Pro
    Replies: 19
    Last Post: - 7th January 2010, 01:01
  2. PMDC SERVO MOTOR WITH quadrature encoder DRIVE ?
    By phoenix_1 in forum Schematics
    Replies: 37
    Last Post: - 22nd November 2009, 19:45
  3. 32-bit Quadrature Counter With Serial Interface
    By precision in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 10th June 2008, 02:49
  4. quad encoders
    By cpayne in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 13th March 2007, 17:49
  5. "momentary" IR decoding
    By sporker in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 20th June 2005, 01:53

Members who have read this thread : 4

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts