Quad Encoder Problem


Closed Thread
Results 1 to 37 of 37

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Hi,
    Change the code so that you interrupt on one edge of one channel - only. (The rising edge of channel A for example).
    In the ISR, poll "the other" channel, if it's low you're moving in one direction, if it's high you're moving in the other.
    Verify that it works at "any" speed you may turn the encoder.

    /Henrik.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    I tried this but nothing happens - the display changes erratically with encoder movement and only really goes up or down by 1:

    Code:
    #DEFINE USE_CUI_ROTARY_ENCODER  ; comment out if using Grayhill rotary encoder
                                    ; which triggers an interrupt only once per detent
    
    ' Enable interrupts on RPM control now that motors are fully spun up
    INTCON   = %10001000        ' Global int enabled, IOCI enabled, 
                                ' INTF flag bit 0 clr, IOCI flag bit 0 clr
    
    #IFDEF USE_CUI_ROTARY_ENCODER
        IOCAP.1  = 1                ' Enable positive (rising edge) change, PORTA.1
    '   The CUI encoder goes thru a full quad cycle with 1 detent turn,
    '     so only need to capture 1 edge (A channel, rising)
    
    '   CH A
    '   ====
    '       ------        ------
    '      |      |      |      |
    '      |      |      |      |
    '   ---        ------        ------
    
    '   CH B
    '   ====
    '          ------        ------
    '         |      |      |      |
    '         |      |      |      |
    '   ------        ------        ---
    
    '   Detent markers
    '   ==============
    '   |               |              |
    '   |               |              |
    
    '   If interrupt is triggered, it means A had a rising edge:
    '           If B = 0 Then CW
    '           If B = 1 Then CCW
    #ELSE
        ' For Grayhill encoder, 1 detent triggers only 1 edge
        IOCAP.0  = 1                ' Enable positive (rising edge) change, PORTA.0
        IOCAP.1  = 1                ' Enable positive (rising edge) change, PORTA.1
        IOCAN.0  = 1                ' Enable negative (falling edge) change, POARTA.0
        IOCAN.1  = 1                ' Enable negative (falling edge) change, PORTA.1
        IOCAF.0  = 0                ' Clear interupt-on-change flag
        IOCAF.1  = 0                ' Clear interupt-on-change flag
    #ENDIF
    
    @ INT_ENABLE  IOC_INT       ; Interrupt-on-Change interrupt
    
    Main:
        ' Check if motor RPM has changed
        IF MotorRPM <> Old_RPM Then
            Old_RPM = MotorRPM
            GOSUB ChngMotorHPWM
        EndIF   
      
        If ValueDirty = 1 THEN
            TimeToSave = TimeToSave - 1
            If TimeToSave = 0 THEN           ' Time to save ?
                WRITE EE_MotorRPM, MotorRPM
                
                ValueDirty = 0               ' Clear the flag
    
                #IFDEF USE_LCD_FOR_DEBUG
                    HSEROUT [LCD_INST, LCD_CLR]
                    pause 5
                    HSEROUT ["Saved RPM=", DEC MotorRPM, "  ", 13, 10] ' Send text followed by carriage return and linefeed
                #ENDIF
            ENDIF
        ENDIF
     
        GOTO Main
    
    ' ***************************************************************
    ' [IOC - interrupt handler]
    ' ***************************************************************
    RotEncAdjust:
        #IFDEF USE_CUI_ROTARY_ENCODER
            IF PORTA.0 = 0 THEN
                RotEncDir = 1                 ; CW rotation if B channel is 0
            ELSE
                RotEncDir = 0                 ; CCW rotation
            ENDIF
        #ELSE
            New_Bits = PORTA & (%00000011)
        
            IF New_Bits = Old_Bits Then DoneRotEnc
        
            RotEncDir = New_Bits.1 ^ Old_Bits.0
        #ENDIF
    
        IF RotEncDir = 1 Then
            ; CW rotation - increase speed but only to a max of 'MaxDuty'
            IF MotorRPM < MaxDuty then MotorRPM = MotorRPM + 1
        Else
            ' CCW rotation - decrease speed to a min of 0
            IF MotorRPM > 0 Then MotorRPM = MotorRPM - 1
        EndIF
    
        ValueDirty = 1                  ; Set dirty flag
        TimeToSave = 50000              ; Set value to begin countdown to EEPROM save
    
    DoneRotEnc:
        Old_Bits = New_Bits
    
        IOCAF.0 = 0                     ' Clear interrupt flags
        IOCAF.1 = 0
    
    @ INT_RETURN
    (I left out the rest of the code)
    Last edited by RossWaddell; - 21st March 2013 at 02:31.

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,605


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    In theory it should work... Perhaps the interrupt latency is just too large to be able to catch the correct state of the 'other' channel once you get to the ISR. One way to test that is to try it with the Grayhill encoder, then it should count every 4th click. If it does then it's a timing problem, if it doesn't it's something else.

    Nice demonstration of conditional compilation!

    /Henrik.

  4. #4
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,116


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Maybe an DSO can help here. Do you have access to such an instrument?

    By the way as Henrik noted, I liked the conditional compilation too. Great example!

    Ioannis

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    If you mean an oscilloscope, no I don't have one (I'd like one, mind, but they're pretty darned expensive).

    And thanks for compliment, Henrik & Ioannis! Although I got the idea from a Darrel Taylor post, I believe - this forum is such an excellent source of ideas.

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


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    From a price/performance standpoint the Rigol DS1052E is quite hard to beat at around $350 and a very popular entry level scope. A very handy tool to have when working with electronics.

  7. #7


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Quote Originally Posted by HenrikOlsson View Post
    From a price/performance standpoint the Rigol DS1052E is quite hard to beat at around $350 and a very popular entry level scope. A very handy tool to have when working with electronics.
    Closer to $470 here in Canada, I'm afraid.

Similar Threads

  1. RF600E & RF600D encoder/decoder problem
    By Megahertz in forum Off Topic
    Replies: 0
    Last Post: - 17th April 2012, 17:18
  2. using Quad UART
    By harryweb in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 30th April 2011, 00:13
  3. quad encoders
    By cpayne in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 13th March 2007, 17:49
  4. Quad encoder problems
    By smitty505000 in forum mel PIC BASIC Pro
    Replies: 51
    Last Post: - 5th October 2006, 22:44
  5. Encoder problem
    By precision in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 12th September 2006, 22:21

Members who have read this thread : 0

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