Quad Encoder Problem


Closed Thread
Results 1 to 37 of 37

Hybrid View

  1. #1


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Oop. Yeah, of course that makes sense. Thanks.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    I incorporated your idea, Henrik, and all is well. I could have sworn this was working earlier this year when I last touched it but perhaps if using the same chip and saving too often to EEPROM means it starts to take longer to do the WRITE and hence only then really missed out on the IOC's. I thought it also incremented MotorRPM by 1 but I can't prove that now. In the end, it works with using a ISR counter and only on the 4th one does it increment MotorRPM.

    I upped the TimeToSave value to 50000 - seems like a good compromise.

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Should I be setting Old_Bits to New_Bits in the 'DoneRotEnc' label for the first 3 of 4 interrupts related to an IOC?

    Code:
    ' ***************************************************************
    ' [IOC - interrupt handler]
    ' ***************************************************************
    RotEncAdjust:
        New_Bits = PORTA & (%00000011)
    
        IF New_Bits = Old_Bits Then DoneRotEnc
    
        ' Increment ISR counter (since quad encoder throws 4 interrupts
        ' for every single detent), only want to update MotorRPM when counter
        ' reaches 4 (i.e. a single detent 'click')
        ISRCounter = ISRCounter + 1
        IF ISRCounter < 4 THEN DoneRotEnc
    
        RotEncDir = New_Bits.1 ^ Old_Bits.0
        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
        ISRCounter = 0                   ; Reset ISR entry counter
        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

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


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Hi,
    I'm afraid I don't quite understand. A quadrature signal consists of four states (00-10-11-01), from any one state there are TWO valid states which it can "transition" to, one in either direction. If you don't keep track of Old_Bits it doesn't know in which state it was and will get confused, count in the wrong direction etc - just as it did when you had the delay in there. Are you trying to keep the MotorRPM from incrementing by 4 for each click?

    Why don't you simply have an EncoderCount variable which is the one you save to EEPROM, and then you do MotorRPM = EncoderCount / 4. Also, instead of triggering on both the rising and falling edges you could trig on only the rising (or falling) which would give you two counts per click instead of four.

    /Henrik.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    But if the interrupts are meant to fire on either a rising or falling edge, then going from '00' to '10' has only one edge (A rises from 0 to 1; B stays the same). The 00 to 10 state change represents one detent, right?

    I got this ISR code from another post (http://www.picbasic.co.uk/forum/show...5396#post25396) and it seemed to work back then (incrementing MotorRPM by 1)
    Last edited by RossWaddell; - 17th March 2013 at 14:23.

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


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Hi,
    But if the interrupts are meant to fire on either a rising or falling edge, then going from '00' to '10' has only one edge (A rises from 0 to 1; B stays the same).
    Yes of course, one edge.

    The 00 to 10 state change represents one detent, right?
    It depends on the encoder used but most mechanical type encoders I've come across has a full quadrature cycle per detent. Here's cutout from the datasheet for a EN12-series encoder from TT Electronics:

    Name:  Encoder output.JPG
Views: 2181
Size:  18.2 KB

    As you can see, going from one detent to the next results in a full quadrature cycle or four edges. So if the IOC is setup to trig the on the rising and falling edge of both the A and the B input then you'll have four interrupts per detent so the MotorRPM variable will increase by 4.

    When it "seemed to work back then" was that with this very same encoder or have you changed it? Do you have a modelnumber or datasheet for the encoder you're using?

    /Henrik.
    Last edited by HenrikOlsson; - 17th March 2013 at 15:13.

  7. #7


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Quite possibly it was using an earlier rotary encoder. I switched to a CUI ACZ11 (datasheet) one because I needed the button. Perhaps the Grayhill one I was using before (datasheet) showed the single-increment-per-detent. The CUI datasheet doesn't explicitly state it goes through a full quadrature cycle but one of the diagrams seems to infer that.

    Again, thanks for your patience, Henrik. Your explanation makes sense to me now (I hadn't realized that different mechanical encoders behave differently. Should have checked that, of course).

    EDIT: I just replaced the CUI encoder with the Grayhill one on my breadboard and guess what - it increments by 1. Mystery solved. Sadly, there doesn't seem to be a cheap Grayhill encoder with a push button so I'll just have to add comments in case I ever switch encoders again to do this test (or read the data sheet more carefully).
    Last edited by RossWaddell; - 17th March 2013 at 18:39.

  8. #8
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,139


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    Are you sure this code does work on both directions?
    Quote Originally Posted by RossWaddell View Post
    Should I be setting Old_Bits to New_Bits in the 'DoneRotEnc' label for the first 3 of 4 interrupts related to an IOC?

    Code:
    ' ***************************************************************
    ' [IOC - interrupt handler]
    ' ***************************************************************
    RotEncAdjust:
        New_Bits = PORTA & (%00000011)
    
        IF New_Bits = Old_Bits Then DoneRotEnc
    
        ' Increment ISR counter (since quad encoder throws 4 interrupts
        ' for every single detent), only want to update MotorRPM when counter
        ' reaches 4 (i.e. a single detent 'click')
        ISRCounter = ISRCounter + 1
        IF ISRCounter < 4 THEN DoneRotEnc
    
        RotEncDir = New_Bits.1 ^ Old_Bits.0
        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
        ISRCounter = 0                   ; Reset ISR entry counter
        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
    By the time that ISRCounter is 4, both outputs of the encoder will be at 0. So the RotEncDir will be 0 too and only the ELSE expression will be executed.

    Maybe I am missing something here?

    Ioannis

  9. #9


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    I have to admit, Ioannis, the code was grabbed from an example here and implemented on my side using a Grayhill encoder which only triggered the interrupt once per detent. Works perfectly with that device, With the CUI ACZ11, I added the check on the ISRCounter but it **does** work - both CW & CCW rotations are captured correctly.

  10. #10


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    I tried CCW rotation again last night and it does seem to get confused every once in a while - either decrements by 2 or sometimes even increments. Doesn't happen often enough to be too much of a problem, but I would like to make the code as efficient as possible.

    Not sure what else I can do in the ISR, though. If I only need one edge to check the rotation direction then I could do as Henrik suggested and turn off 2 of the edge interrupts; that way, it would only hit the ISR twice. I could do the RotEncDir determination on the first interrupt then set a flag to ignore the 2nd interrupt, then reset those after the 2nd.

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


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    I stil cannot see how this piece of code can be true:

    Code:
    RotEncDir = New_Bits.1 ^ Old_Bits.0
        IF RotEncDir = 1 Then
    If you follow what Henrik has posted on that pulse train diagram at #21, you will see that after the above XOR, the IF RotEncDir = 1 statement will always fail and the ELSE will be executed.

    Ioannis

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