Shop OBEX P1 Docs P2 Docs Learn Events
Need help modifying Rotary Enc Object — Parallax Forums

Need help modifying Rotary Enc Object

T ChapT Chap Posts: 4,223
edited 2012-06-17 20:55 in Propeller 1
DAT
                        org     0
                                                                                                
Update                  test    Pin, #$20               wc      'Test for upper or lower port
                        muxc    :PinSrc, #%1                    'Adjust :PinSrc instruction for proper port
                        mov     IPosAddr, #IntPos               'Clear all internal encoder position values
                        movd    :IClear, IPosAddr               '  set starting internal pointer
                        mov     Idx, TotEnc                     '  for all encoders...  
        :IClear         mov     0, #0                           '  clear internal memory
                        add     IPosAddr, #1                    '  increment pointer
                        movd    :IClear, IPosAddr               
                        djnz    Idx, #:IClear                   '  loop for each encoder
                                                                
                        mov     St2, ina                        'Take first sample of encoder pins
                        shr     St2, Pin                
:Sample                 mov     IPosAddr, #IntPos               'Reset encoder position buffer addresses
                        movd    :IPos+0, IPosAddr                               
                        movd    :IPos+1, IPosAddr
                        mov     MPosAddr, PAR                           
                        mov     St1, St2                        'Calc 2-bit signed offsets (St1 = B1:A1)
                        mov     T1,  St2                        '                           T1  = B1:A1 
                        shl     T1, #1                          '                           T1  = A1:x 
        :PinSrc         mov     St2, inb                        '  Sample encoders         (St2 = B2:A2 left shifted by first encoder offset)
                        shr     St2, Pin                        '  Adj for first encoder   (St2 = B2:A2)
                        xor     St1, St2                        '          St1  =              B1^B2:A1^A2
                        xor     T1, St2                         '          T1   =              A1^B2:x
                        and     T1, BMask                       '          T1   =              A1^B2:0
                        or      T1, AMask                       '          T1   =              A1^B2:1
                        mov     T2, St1                         '          T2   =              B1^B2:A1^A2
                        and     T2, AMask                       '          T2   =                  0:A1^A2
                        and     St1, BMask                      '          St1  =              B1^B2:0
                        shr     St1, #1                         '          St1  =                  0:B1^B2
                        xor     T2, St1                         '          T2   =                  0:A1^A2^B1^B2
                        mov     St1, T2                         '          St1  =                  0:A1^B2^B1^A2
                        shl     St1, #1                         '          St1  =        A1^B2^B1^A2:0
                        or      St1, T2                         '          St1  =        A1^B2^B1^A2:A1^B2^B1^A2
                        and     St1, T1                         '          St1  =  A1^B2^B1^A2&A1^B2:A1^B2^B1^A2
                        mov     Idx, TotEnc                     'For all encoders...
:UpdatePos              ror     St1, #2                         'Rotate current bit pair into 31:30
                        mov     Diff, St1                       'Convert 2-bit signed to 32-bit signed Diff
                        sar     Diff, #30
        :IPos           add     0, Diff                         'Add to encoder position value
                        wrlong  0, MPosAddr                     'Write new position to main memory
                        add     IPosAddr, #1                    'Increment encoder position addresses
                        movd    :IPos+0, IPosAddr
                        movd    :IPos+1, IPosAddr
                        add     MPosAddr, #4                            
:Next                   djnz    Idx, #:UpdatePos                'Loop for each encoder
                        jmp     #:Sample                        'Loop forever

'Define Encoder Reading Cog's constants/variables

AMask                   long    $55555555                       'A bit mask
BMask                   long    $AAAAAAAA                       'B bit mask
MSB                     long    $80000000                       'MSB mask for current bit pair

Pin                     long    0                               'First pin connected to first encoder
TotEnc                  long    0                               'Total number of encoders

Idx                     res     1                               'Encoder index
St1                     res     1                               'Previous state
St2                     res     1                               'Current state
T1                      res     1                               'Temp 1
T2                      res     1                               'Temp 2
Diff                    res     1                               'Difference, ie: -1, 0 or +1
IPosAddr                res     1                               'Address of current encoder position counter (Internal Memory)
MPosAddr                res     1                               'Address of current encoder position counter (Main Memory)
IntPos                  res     16                              'Internal encoder position counter buffer

I want to modify the rotary object to allow the start pin and second pin of the inputs to be swapped if needed. It would be OK just to write the code above with the pins reversed and I can just save it as Reversed Direction version. The object works by setting PIN in it's main method, then the code above used PIN + 1 as the second pin of the pair. There is only ever a single rotary encoder. I cannot tell from the code where the second pin is being calculated by PIN + 1, else it could just be changed to PIN - 1, then use for the first pin in the start method the result of PIN + 1, effectively reversing the inputs.

Comments

  • AribaAriba Posts: 2,690
    edited 2012-06-16 11:40
    For a single encoder you get a reversed pin version if you add a reverse instruction after every read of the pins (and shift):
    so after every of these instructions in the original code:
         shr  St2, Pin
    
    add an instruction so that you get:
         shr  St2, Pin
         rev  St2, #32-2
    
    This will reverse the 2 lowest bits in St2 and swap therefore A and B of the first (single) encoder.

    Andy
  • AribaAriba Posts: 2,690
    edited 2012-06-16 11:54
    Another idea. I think with the pins of the encoder swapped the value just counts in the wrong direction, so you can reverse that with replacing ADD with SUB in the value write loop:
    instead of
        :IPos           add     0, Diff                         'Add to encoder position value
    this:
        :IPos           sub     0, Diff                         'Add to encoder position value
    
    If it works, it will then work also for more than 1 encoder.

    Andy
  • T ChapT Chap Posts: 4,223
    edited 2012-06-16 14:55
    Thanks Ariba, I will try out the second idea. I assume you meant the second idea replaces the first, not in addition too.
  • JonnyMacJonnyMac Posts: 9,194
    edited 2012-06-17 12:18
    I needed a straightforward encoder object for a project so I rewrote one of my old ones. This code may be easier to follow. It allows you to use arbitrary pins, account for detented ("clicky") encoders, and set low and high limits for the encoder value. I've done variations on this for two and three encoders; updating is pretty easy.
  • T ChapT Chap Posts: 4,223
    edited 2012-06-17 20:17
    Thanks Jonny, I will look at it. This is for an encoder on a motor shaft.
  • JonnyMacJonnyMac Posts: 9,194
    edited 2012-06-17 20:55
    Well, then, you will be able to use the full range of a signed, 31-bit value (negx to posx) with it. I wrote a variant of this code for a friend for three encoders (for pan, tilt, and trolley) that is used on a camera control platform. Using the encoders and a background cog we get very precise speed control and the ability to record and playback moves in the system.
Sign In or Register to comment.