Quad Encoder Problem


Closed Thread
Results 1 to 37 of 37

Hybrid View

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


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

    I'll try this out. At first glance, though, the ISR is always setting TimeToSave to 5000 so I think it needs a check like:
    Well, yes, that was the whole idea. As long as the user keeps turning the knob (generating interrupts) the counter will get reset to 5000 (or whatever). But as soon as the user has NOT changed the RPM for the duration of 5000 iterations thru the Main loop the value is saved. When the knob isn't being turned no interrupts are being generated so the Main routine eventually gets the counter down to 0 and saves the value.

    /Henrik.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: Quad Encoder Problem

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

  3. #3


    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.

  4. #4


    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

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,621


    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.

  6. #6


    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.

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,621


    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: 2235
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.

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


    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.

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