Is non contiguous possible on the Rotary Object?
T Chap
Posts: 4,223
In the rotary object, I have pins 21 and 22 on an encoder. I need to connect a second encoder. 23 and onwards are doing other things and can't be modified. 0/1, 15/16, 13/14 pairs are open for the second encoder. There are no more cogs. Does anyone have an opinion on the PASM as to whether the pins could be hard coded in PASM to reflect noncontiquous inputs? IE Encoder 1 = 21/22 Encoder 2 =0/1. No delta support required.
PUB Start(StartPin, NumEnc, NumDelta, PosAddr, direction): Pass ''Record configuration, clear all encoder positions and launch a continuous encoder-reading cog. ''PARAMETERS: StartPin = (0..63) 1st pin of encoder 1. 2nd pin of encoder 1 is StartPin+1. '' Additional pins for other encoders are contiguous starting with StartPin+2 but MUST NOT cross port boundry (31). '' NumEnc = Number of encoders (1..16) to monitor. '' NumDelta = Number of encoders (0..16) needing delta value support (can be less than NumEnc). '' PosAddr = Address of a buffer of longs where each encoder's position (and deta position, if any) is to be stored. ''RETURNS: True if successful, False otherwise. Pin := StartPin TotEnc := NumEnc TotDelta := NumDelta Pos := PosAddr Stop SetDir(direction) longfill(Pos, 0, TotEnc+TotDelta) Pass := (Cog := cognew(@Update, Pos) + 1) > 0 DAT 'Read all encoders and update encoder positions in main memory. 'See "Theory of Operation," below, for operational explanation. 'Cycle Calculation Equation: ' Terms: SU = :Sample to :Update. UTI = :UpdatePos through :IPos. MMW = Main Memory Write. ' AMMN = After MMW to :Next. NU = :Next to :UpdatePos. SH = Resync to Hub. NS = :Next to :Sample. ' Equation: SU + UTI + MMW + (AMMN + NU + UTI + SH + MMW) * (TotEnc-1) + AMMN + NS ' = 92 + 16 + 8 + ( 16 + 4 + 16 + 6 + 8 ) * (TotEnc-1) + 16 + 12 ' = 144 + 50*(TotEnc-1) 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 ' add or substraction the count to the accumulator :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
Comments
Each pair of pins need to be together but the pairs can be on any set you wish.
Here's the output of the demo program.
The speed is no particular units. I'm working on improving the speed section to work better at low speeds. (I don't know if you even need speed feedback.)
The encoder code is based on JonnyMac's SpinZone article Spinning It Up with Encoders (or something like that).
The encoder object receives the pin settings as a pointer.
As you can see there are a total of three address passed to the encoder object.
The pins are set as constants.
But these constants need to be placed in an array so they can be passed to the child object.
I'm pretty sure the object I posted doesn't include a provision to turn off a channel. Since it just reads the pin as an input it won't interfere with other parts of your code. You can just set extra channels to the previous channels' pins.
Edit: Both the objects in post #2 of the above linked thread are encoders only.
Use @EncPins as the parameter in start(). You can use -1 in the 2nd and 3rd pin sets, the first (encoder 0) must be defined.
I hope this helps.
This should toggle bit 26 and swap ADDS and SUBS. I was hoping someone could confirm that this is correct thinking.
Below you can see the PASM with the numbers including for counting back from the first declared long in DAT, leaving out some info that is not needed here: