decoding quadrature encoders


Closed Thread
Results 1 to 40 of 94

Hybrid View

  1. #1
    Join Date
    May 2013
    Location
    australia
    Posts
    2,643


    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

  2. #2
    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.

  3. #3
    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.

  4. #4
    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.

  5. #5
    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

  6. #6
    Join Date
    May 2013
    Location
    australia
    Posts
    2,643


    Did you find this post helpful? Yes | No

    Default Re: decoding quadrature encoders

    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.
    I have not tried your code but can assure you that it is essential to save the mcu context upon isr entry and to restore it on exit . restoring the context without saving it can only lead to tears, not saving it can only lead to tears.

    so good luck with that


    dave
    the chip used here in this somewhat hijacked thread is a 16F876 it has only one "INT" pin your suggestion just cannot work in that case.
    afaik no pic16 chips can respond to rising and falling levels on an INT int pin simultaneously
    its one or the other. as henrik says to do a full quadrature decode every edge needs to cause an interrupt.
    RBC int can do it a single INT int cannot , the intx edge would need to be toggled on every interrupt .

    secondly that circuit with all its extra bits cannot use the full resolution of a encoder its a 1x decode.

    thirdly since the portb rbc pins on a 16F876 are schmidt trigger type inputs and if the chip is close enough to
    the re (opto type not mechanical)no other components are required at all to do a full 4x decode , why complicate it ?
    Warning I'm not a teacher

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


    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:
    Dave, I think you're misunderstanding what I'm saying.
    The circuit you linked to is x1 decoder, effectively provoding 1/4 of the encoders available resolution. Your simply counting the individual lines of the A and B channels respectively. If that's enough, perfect go right ahead but if you need the full resolution of the encoder (as is the case here) then it's not going to cut it.

    To use the full resolution of the encoder each and every edge of the two signals needs cause the counter the change up or down. If the encoder is connected directly to INT0 and INT1 it means that the edge causing the interrupt needs to changed on every interrupt so that it "catches" the falling edge after a rising edge etc. It's certainly doable if the PIC allows you to do it (not all do) but it does complicate things.

    By using interrupt on change this is handled automatically because ANY change on ANY pin causes an interrupt so you will "catch" every edge (rising AND falling) automatically and you just need to decode the gray code in the ISR. From any given state (there's only four) you can only get to two other (valid) states, one is forward the other is backwards.

    Look at this NI page on qudrature encoders, about half way down is a comparison of x1, x2 & x4 decoding.

    /Henrik.

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