Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

The BEST way to use 2 interrupts on a PIC?

Status
Not open for further replies.

bigal_scorpio

Active Member
Hi to all,

I have for quite a while being scouring the net for a way to use a Rotary Encoder on a PIC microcontroller.

The problem I'm having isn't a lack of info, just different ways of doing it keep popping up and I don't know which is best!

I have seen or gates used and even diodes to get the 2 bits of grey code to the single interrupt pin of the PIC, and seeing as this is the first time I have used an Encoder and I am certainly NOT a PIC genius I thought I would ask the experts, some of you no doubt have experience of these.

Is there a tried and trusted or should I say widely accepted method of doing this?

The encoder will be used to determine the position of a car seat moved by a motor. The Encoder is a standard type with 20 detents and will not be turning fast, I'm guessing about 10RPM and maybe a couple of complete rotations from limit to limit, depending on how I gear the linkage, giving me about 40 positions in all. Hopefully I will have 3 control switches for the positions, 2 giving me the separate positions and the third to let me set the position in memory.

So which is the best way in this forums opinion.

Your humble student...........Al
 
Don't use interrupts.

Ok, I know others people would not agree but here's how I would do it.

Have a loop that runs round fast enough that it can't miss a cycle of the encoder.

Have a register that stores the last known position of the encoder. When the bits from the encoder differ from what they were, based on the register, increment of decrement the register.

For example, if the bits are:-

Code:
Last 2 bits of register        encoder bits
 00                                   00
 01                                   01
 10                                   11
 11                                   10
Say you have a register that is at 0x21, so the last two bits are 01
If the signal from the encoder is 01 do nothing.
If the signal from the encoder is 00, decrement to 0x20
If the signal from the encoder is 11, increment to 0x22

As long as your loop gets round fast enough, that will keep count. The register is available to other parts of the code to decide when to start and stop the motor.
 
Last edited:
That approach doesn't use all of the data.

Use 2 of the interrupt on change pins. at interrupt time, take the previous value of the pins and the current value to determine rotation (cw or ccw) using a lookup table to determine rotation direction. Increment position for cw, decrement for ccw.

the lookup table has 16 entries. These encode all possible combinations of current and previous value. Some are "impossible" but define error conditions (like 10 to 01 transition). Each array entry can take one of 4 states - cw, ccw, resample, error. error is when 2 bits change, cw and ccw are 1 bit changes, resample is when there are no changes (wont happen with interrupts). You could use 16 bytes for the table. If you wanted to save space you could use 4 or even 2 bit entries at the cost of some additional code.

Code:
cur prev    state
00  00      resample
00  01      cw
00  10      ccw
00  11      error
01  00      ccw
...
You'll have to fill in the rest of the table. You may need to switch cw and ccw depending on how you connect the input pins to the encoder. If you decide to not use interrupts, the resample entry becomes useful.
 
Last edited:
Hi to all,

I have seen or gates used and even diodes to get the 2 bits of grey code to the single interrupt pin of the PIC, and seeing as this is the first time I have used an Encoder and I am certainly NOT a PIC genius I thought I would ask the experts, some of you no doubt have experience of these.

Is there a tried and trusted or should I say widely accepted method of doing this?

The encoder will be used to determine the position of a car seat moved by a motor. The Encoder is a standard type with 20 detents and will not be turning fast, I'm guessing about 10RPM and maybe a couple of complete rotations from limit to limit, depending on how I gear the linkage, giving me about 40 positions in all. Hopefully I will have 3 control switches for the positions, 2 giving me the separate positions and the third to let me set the position in memory.

..Al

hi Al,
You say a 2 bit Grey code and the encoder has 20 detents.???

How many wires are coming from the encoder.?
 
hi Al,
You say a 2 bit Grey code and the encoder has 20 detents.???

How many wires are coming from the encoder.?

Hi Eric,

There are 5 pins altogether on the encoders, 2 of them are the switch (momentary on) and the other 3 are A, B and Common, below is the link to where I bought them.

thanks for the input so far guys. :)

**broken link removed**

Regards..........Al
 
Hi Eric,

There are 5 pins altogether on the encoders, 2 of them are the switch (momentary on) and the other 3 are A, B and Common, below is the link to where I bought them.

thanks for the input so far guys. :)

Regards..........Al

hi Al,
UIGC something dosnt add up.?

Using a meter on ohms can you map out the code appearing on the two wires with respect to the Common for each detent of the rotation.?
 
hi Al,
UIGC something dosnt add up.?

Using a meter on ohms can you map out the code appearing on the two wires with respect to the Common for each detent of the rotation.?

Hi Eric,

Its difficult with the meter as the pulse is between detents, so I'll breadboard it with a couple of LEDs and map it out like that, I'm hoping that will be easier?

Al
 
Last edited:
Hi Eric,

Its difficult with the meter as the pulse is between detents, so I'll breadboard it with a couple of LEDs and map it out like that, I'm hoping that will be easier?

Al

hi Al,
It sounds like an Incremental encoder rather than a Rotary encoder.

The Incremental version will give a 2 bit repeating Grey code, whereas a Rotary encoder would give an absolute code.

So for 20 detents the 2bit Grey will repeat 5 times for one full rotation.
This is not a problem but your program will have to 'calculate'/store the rotational angle.

EDIT: Al look at this link for incremental encoders.
**broken link removed**

The pattern you measure should look like this image.
 

Attachments

  • esp02 Oct. 10.gif
    esp02 Oct. 10.gif
    13.7 KB · Views: 150
Last edited:
Hi folks,

Eric, here is the results you wanted.

But I am a bit mytified by them!

With a ground on the middle pin (c) and an LED through a reistor on each (a) and (b) the result when I turn the shaft is not what I expected.

On each notch CW first a then b lights momentarily.

On each notch CCW first b then a lights momentarily.

This is exactly the same for each subsequent notch, is this right?

BTW I would have replied earlier but we had the film crew in again today! No joke, we are going to be on Channel 4s Cutting Edge program sometime between now and Xmas! The reason? We have a very big cat!

So in the near future you will all be able to put a face to the words, especially Eric who has been a great freind to me but I have sadlynever met in person.

Anyway, any thoughts on the results Eric?

Regards Al
 
Hi folks,

On each notch CW first a then b lights momentarily.

On each notch CCW first b then a lights momentarily.

This is exactly the same for each subsequent notch, is this right?

Regards Al

hi,
Strange readings.

Note: the contacts are only rated at 1mA, how much current is the LED passing.?

On each notch CW first a then b lights momentarily.
Is this momentary for 'a' and 'b'
On each notch CCW first b then a lights momentarily.
Is this momentary for 'b' and 'a'
 

Attachments

  • esp04 Oct. 10.gif
    esp04 Oct. 10.gif
    5.1 KB · Views: 128
Last edited:
Hi Al,

The few encoders I've tried these last few years would generate all four states between the detent positions and I always have the '00' or '11' bit patterns, depending on type of encoder, when sitting in the detent position.

Many people don't know that you can easily determine the 'direction' of rotation by simply exclusive-or'ing the A or B bit of the current sample with the opposite bit of the previous sample. This method isn't better or worse than the "table" method but it codes very nicely. The following code for example only uses a single variable for the "previous" encoder state;

Regards, Mike

Code:
;
;  poll the Rotary Encoder A and B switches
;
ISR_Encoder
       movf    PORTB,W         ; get switch data                 |B0
       andlw   b'00000011'     ; mask encoder B and A switches   |B0
       xorwf   ENCOLD,W        ; same as last reading?           |B0
       bz      ISR_Next        ; yes, branch (no change), else   |B0
       xorwf   ENCOLD,W        ; restore encoder bits in W       |B0
       rrf     ENCOLD,f        ; prep for B-old ^ A-new          |B0
       xorwf   ENCOLD,f        ; ENCOLD bit 0 = direction        |B0
       rrf     ENCOLD,f        ; now Carry bit = direction       |B0
       movwf   ENCOLD          ; update ENCOLD (new BA bits)     |B0
;
;  encoder position has changed but we only act on a change
;  that occurs when the encoder falls into one of the detent
;  positions (we ignore the changes between detents)
;
       xorlw   b'00000011'     ; detent position (BA = 11)?      |B0
       bnz     ISR_Next        ; no, branch, else                |B0
;
;  increment or decrement position variable based on direction
;  in the Carry bit
 
hi Al,

Nows a good time to use that scope.!

Connect the common of the encoder to a 0v line, connect A to +5V via a 10K, do the same with B.

Connect the Y1 scope lead to the junction of the A and 10k and the Y2 scope lead to the junction of B and 10k.

Set the scope timebase to say, 10mSec/div for starters and rotate the encoder.

You should see the code on the scope traces... OK.?:)
 
Or you could check the encoder Data Sheet or simply verify that you have the same '00' or '11' pattern in each detent position.

Mike
 
hi,
Strange readings.

Note: the contacts are only rated at 1mA, how much current is the LED passing.?

Hi Eric, just used a 2k2 resistor on the red LEDs, so at 5v the current should be inside 1mA, and yes to the other two questions, they light momentarily one after the other, break before make.

EDIT just put a large knob on the encoder and can turn it more delicately and they DON'T break before make and if I'm carefull I can keep them on constant by holding between detents.

Sorry was rushing before with film crew here! Very stressfull! But finished now!

Still wondering if something is iffy though, can't see how that is grey code can you?

Al
 
Last edited:
Still wondering if something is iffy though, can't see how that is grey code can you?

Al

Hi Al,
Its most likely as Mike says, 4 bytes/indent.

Can you try the scope, you should clearly see a pattern.
Its important that you know before you write any code.:)
 
Still wondering if something is iffy though, can't see how that is grey code can you?

Al

Grey code is any code that varies only one bit at a time

The following table compares "normal" binary code with Grey:

Code:
#      binary      Grey
0       00           00
1       01           01
2       10           11
3       11           10

In binary, the transitions from #1 to #2 and from #3 to #0 change two bits at the same time. BUT there is no such a thing as "at the same time", if one bit changes shightly before the other the µcontroler may read the wrong code.

The grey code ensures that, when one bit is changing, the other is at a steady value.
 
Last edited:
Hi Al,
Its most likely as Mike says, 4 bytes/indent.

Can you try the scope, you should clearly see a pattern.
Its important that you know before you write any code.:)

Hi Eric,

I tried my scope but I am baffled as to what I'm seeing! Between every notch I get a deviation to the top then one to the bottom, reversed if I turn the other way of course. On the detents there is nothing on either channel.

I cant make out a pattern other than up down up down etc.

If you think its strange and maybe I'm doing something wrong I will try to video the scope display if it will help?

Regards.........Al
 
Hi Eric,

I tried my scope but I am baffled as to what I'm seeing! Between every notch I get a deviation to the top then one to the bottom, reversed if I turn the other way of course. On the detents there is nothing on either channel.

I cant make out a pattern other than up down up down etc.

If you think its strange and maybe I'm doing something wrong I will try to video the scope display if it will help?

Regards.........Al

I'm also trying to understand encoders, but don't the detents provide a positive stopping point after a A/B state change?

e.g.

Detent
A=0
B=0
Detent
A=1
B=0
Detent
A=1
B=1
Detent
A=0
B=1
Detent

and so on?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top