Status
Not open for further replies.

Mosaic

Well-Known Member
Here is some code I tested in Proteus (using the motor encoder for the signal)
It is full quadrature with a variable debounce. Uses 3 GPR bytes.
Commented.
Code:
ScanEncoderPort   ;_________ Eg. Bourns PEC11 series_________________________________________________________________________________________________________
; Quadrature (full or detent) rotary encoder signals (A=RA0,B=RA1) , debounced. R_dbcount is an interrupt increment variable, used to tgt a >4ms debounce period.
; If rapidly turning the encoder causes a lack of response, try reducing the debounce time a bit. Use 10 - 47K weak pullups on pulse lines.
; R_Dbstate tracks the valid debounced condition of the encoder bits RA0,1.
; If the encoder bits cannot be placed on the matching portA bits as coded here, read the bits & map them into a RAM byte  (bits 0,1) and replace the below PORTA read with the RAM byte read.
; Returns W-register = 0 for no change, .255 for CCW and 1 for CW changes per pulse. Simple to add W-reg to any integer variables  afterward.
;______________________________________________________________________________________________________________________________
movf PORTA,w     ; replace with the mapped RAM byte as mentioned if required..
andlw d'3'         ; filter bit 0,1 for a change.
xorwf LastSample,w    ; set changed bits
xorwf LastSample,f    ; lastsample=currentsample. Affects zero flag.
andlw d'3'       ; w-reg filter bit 0,1 for a change. Refresh zero flag
skpz
clrf R_dbcount       ; start the debounce countdown.
btfss R_dbcount,2     ;Debounce  period in this example. Depends on particular interrupt speed. (suggest  this:  >4 ms by choosing an appropriate R_dbcount bit)
retlw 0
;______________________________________________________________________________________________________________________________
; debounce time has passed. Processing validated changes.
;______________________________________________________________________________________________________________________________
movf LastSample,w   ; fetch the recent encoder bits sample.
xorwf R_Dbstate,w   ; get changes bet. current state and debounced state.
xorwf R_Dbstate,f     ; apply them to DB state
andlw d'3'       ; w-reg filter bit 0,1 for any change.
skpnz
retlw 0         ; no debounced change.
;______________________________________________________________________________________________________________________________
;Else Test each Encoder bit to determine change direction.
;______________________________________________________________________________________________________________________________
clrc
andlw d'2'        ; filter bit 1
skpnz
;---------------------------------------------------------------------------------------------------------------------------------------------------
;********************QUADRATURE MODE CODE:  No Detent (full) or Detent mode (1/4)
;---------------------------------------------------------------------------------------------------------------------------------------------------
;goto Testbit0     ; ************* Enable this line for full quadrature, AND ALSO,
;--------comment out this block for full quadrature--------------
retlw 0
movf R_Dbstate,w;
andlw d'2';
skpnz;
retlw 0
;---------------block end -----------------

rlf R_Dbstate,w      ; align encoder debounced bits
xorwf R_Dbstate,w    ; compare bits
andlw d'2'        ; filter bit 1
skpnz
retlw 1         ; 1=> 1 clockwise pulse
retlw d'255'     ; 255=> 1 anticlockwise pulse.
Testbit0
rrf R_Dbstate,w     ; align encoder debounced bits
xorwf R_Dbstate,w    ; compare bits
andlw d'1'       ; filter bit 0
skpz
retlw 1         ; 1=> 1 clockwise pulse
retlw d'255'      ; 255=> 1 anticlockwise pulse.
;______________________________________________________________________________________________________________________________

Last edited:

Ian Rogers

User Extraordinaire
Forum Supporter
You don't need a debounce....

All I do is create a state machine.... Monitor the inputs and set the outputs accordingly..

Take the previous state and the new state and act accordingly... It doesn't need debouncing.

Code:
shift old input left twice
If the 4 bit code = 7, 1, 8, 14
then go in direction 1
If the 4 bit code = 9, 2, 4, 13
then go direction 2
If the 4 bit code = anything else
do nothing
If the edge bounces.... Who cares... it will just change the direction very quickly...

MikeMl

Well-Known Member
The output of a quadrature encoder is a two bit Gray code. By definition, a Gray code does not need to be de-bounced. If the encoder stops where one of the two signals is alternating between a 0 and 1 due to noise, the up-down counter gets count-up, count-down, count-up,... commands which just causes it to toggle between two sequential states, i. e. 357, 358, 357, 358,...

atferrari

Well-Known Member
The output of a quadrature encoder is a two bit Gray code. By definition, a Gray code does not need to be de-bounced. If the encoder stops where one of the two signals is alternating between a 0 and 1 due to noise, the up-down counter gets count-up, count-down, count-up,... commands which just causes it to toggle between two sequential states, i. e. 357, 358, 357, 358,...

Hola Mike

May I take for granted that any quadrature encoder will output Gray code?

Tony Stewart

Well-Known Member
Yes and quadrature is the precursor to modem schemes called Trellis encoding with minimal bit changes in parallel codes bigger than 2.

MikeMl

Well-Known Member
Hola Mike

May I take for granted that any quadrature encoder will output Gray code?
quadrature = (special case of) Gray

JimB

Super Moderator
ATF wrote:
May I take for granted that any quadrature encoder will output Gray code?
Sadly no, I have been burnt with this a couple of times, most recently in the past week or so.

The first instance was a CHEAP encoder which uses mechanical switches which bounced and scratched in an horrific manner.
Not only that, but at the detent position both of the switch contacts were open circuit. Thus the output was not a standard two bit Grey code.
I gave up on these and abandoned them in favour of a more expensive encoder with optos.

Recently, and also touching on the current milling machine thread, as part of my rebuild of the controls for my mill I am implementing an MPG (Manual Pulse Generator). In CNC speak this is a rotary control used for manually jogging the machine axes to the required position.
I found a suitable encoder on ebay and the published specifications appeared to show that it gave the two bit Gray code.
However, on testing it out, when the control is sitting at the detent positions, both outputs are 0v.
Turning the control one way gives pulses on one of the outputs and a 0v on the other output.
Turning the control the other way gives the pulses again but the other output is now at 5v.
Happilly there is no contact bounce or other nastiness, just nice clean edges.

Of course this discovery gave rise to a very ill tempered outburst on my part, I think that it even caused my parrot to blush!

However, all was not lost as I am using a PIC to direct the MPG pulses to one of three inputs in the control software. One input for each of the three machine axes. As a result I just had to write the PIC code to read the Step and Direction from the encoder and output Gray code to the machine controller software (Mach3).

JimB

MikeMl

Well-Known Member
Re Jim's: Not all encoders are quadrature...

A lot of ham radios use a (cheap) rotary encoder (to control a synthesiser) as the main tuning dial. Over time, as something wears, these stop putting out proper quadrature, and tuning gets erratic...

I once paid several thousand \$ for an optical incremental encoder that had 2^18 steps per revolution.

manoj soorya

Member
can someone provide the schematic too for the code shown in the first thread?

Thank you very much

atferrari

Well-Known Member
quadrature = (special case of) Gray
Well, it seems that I need to do some reading... The closest I've been was when playing with a mouse and the scroll wheel. I did not dig too much as I can see.

Gracias Mike.

JimB

Super Moderator
I suggest that "quadrature" is a subset of Gray Code.

Two bits, modulo 4

JimB

MikeMl

Well-Known Member
Gray wheel encoders output Gray code!!

Quadrature encoders output A and B signals at 90 degrees shift....
Incremental encoder = 2 bit quadrature = 2 bit output = 2bit Gray code

I have some 12bit parallel (4096 counts per rev) absolute Gray-code encoders, too.

The older style "blind altimeter encoder" used to encode aircraft altitude had an aneroid bellows rotating a glass wheel coded with a 10bit Gray code shadow mask, where each 100ft altitude change causes one bit of the Gray code to change. This is another example of an absolute, parallel output, Gray Code encoder.

Last edited:

I agree with Jim

Mosaic

Well-Known Member
ATF wrote:

Sadly no, I have been burnt with this a couple of times, most recently in the past week or so.

The first instance was a CHEAP encoder which uses mechanical switches which bounced and scratched in an horrific manner.
Not only that, but at the detent position both of the switch contacts were open circuit. Thus the output was not a standard two bit Grey code.
I gave up on these and abandoned them in favour of a more expensive encoder with optos.

JimB
I guess that implies that debounced code would accommodate such encoders?

JimB

Super Moderator
I guess that implies that debounced code would accommodate such encoders?
I do not know, maybe.

It would be worth a try if I have time to devote to it sometime.

JimB

Mosaic

Well-Known Member
Ok, well here is the proteus file with the asm.

It does a few other things, but is fairly well commented. It is a test circuit for a PIC breakout board I designed.

Attachments

• 207.5 KB Views: 185