using PIC16f628A with an incremental rotary encoder - Help getting started

Status
Not open for further replies.

radioshack

New Member
Hi Can someone point me in the direction of some related code for these type of encoders - in C please.

MECHANICAL ROTARY ENCODER SWITCH (INCREMENTAL TYPE)

I have experimented using a 16-way rotary switch hexadecimal rotary (4-bits) on an interrupt (TMR0) to flash an LED on pin-18 (RA1) either faster or slower depending on position.

Now I want to do the same kind of thing (initially) with a inc. encoder (2-bit gray - is this right?) - ideally using the encoder's push button for a zeroing operation.

I have had quite a good look over google to find something similar but must be typing in the wrong search criteria somehow.

I am using a PicKit2 with MPLab and PICC compiler.

Thank you.
 
There a a few sites on the net for this.. however the gray code for a two bit or even a four bit encoder is minimal... you can use a simple lookup table to convert..

Binary 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E.F
Gray 0,1,3,2,6,7,5,4,C,D,F,E,A,B,9,8

So read portx lookup the equivalent..buda bing your done

Ian
 
Thanks Ian.

I really meant to ask about how to start off writing code for incremental encoders.

I am genuinely confused as to why the encoder's description (admittedly it's not a full datasheet, but) actually mentions gray code, as the encoder doesn't appear to have any actual absolute encoding, only incremental - with two square waves, one lagging or leading the other to denote direction of rotation. Afterall, the encoder boasts 20-positions & so would require 5-bits not 2.


Although I have got my head around the simple TMR0 interrupt, I am aware that the interrupts I should be using would probably be looking for' a rising edge on a pin. I'm not sure if the PIC I'm using can handle two of these type interrupts that (I think) need to see both a rising edge and then later falling edge.

Of course I can just keep polling the ports on a timer event, but this seems less eloquent & also may cause problems if later on I start carrying out other functions from main().

Sorry if I haven;t explained this too well.
 
hi,
Post the datasheet for the encoder or a link.
I would say the encoder you have that gives a quadrature signal, even though it has 20 index positions, will only be a 2 bit code.
 
hi rs,
With that type of quadrature switch you have to detect the switching edges in order to determine inc or dec [ CW/CCW] rotation.
You could use interrupt on change on two of the PORTB pins.
Looking at the amount of bounce on the contacts some program delays will be required.

Also I would say also the current inc/dec count will have to be saved in EEPROM at power down, recall on power up.
 
That's not true Eric. You can also poll for a change in level.

The nice thing about that quadrature signal is that after detecting a change, you can easily determine direction by exclusive-OR'ing the current A or B bit with the opposite bit from the previous sample. The result, 0 or 1, is the direction.
 
Last edited:

hi Mike,
What part have I said that is not true.?
Which ever method he uses he will have to detect a change in A or B to determine direction.

I said he 'could' use interrupts on PORTB, I didn't say thats the only way.

I would use the interrupt option.

Eric
EDIT:
Note the Indent positions for the 20
 

Attachments

  • AAesp02.gif
    3.5 KB · Views: 240
Last edited:
Thanks guys.

just viewing the section in '628A datasheet on:
PORTB INTERRUPT

In the code I basically copied out when using TMR0 the interrupt conditions a reset in this manner
TMR0 = 0; // Timer (or counter) TMR0 returns its initial value
INTCON = 0x20; // Bit T0IE is set, bit T0IF is cleared
//T0IF = 0; // clear timer0 flag
//T0IE = 1; // re-enable timer0 interrupt

For the on-change intpt I need to set RBIE in main()
then RBIF will go high if there is any change on pins RB4:7 - rising or falling, is this right?
RBIE will need to be set again at the end of the isr routine for the next change to be caught (?).

For a CW rotation the pin for A (say RB4) will see an event before the pin for B (eg RB5), but it's this double visit that I can't get my head around - what if I miss one or the other?

Although I should probably put this together from scratch myself I could sure use an bit of example code right now.

I might try some more googling!
 
Last edited:
hi rs,
Look thru this pdf.
 

Attachments

  • RotaryEncoder.pdf
    31.5 KB · Views: 405
Perhaps nit-picking, but, you said;

But you can also detect changing levels.

Mike,
Please feel free to nit pick.

But as a retro nit-pick, you say But you can also detect changing levels , which suggests that you can also detect edges as an option.

Personally I dont mind which solution the OP chooses, I just suggest options.
 
I am having trouble with using the PortB Interrupt to pick up the pulses from the encoder.
I think this is, as was suggested as a likely problem previously, there is a debounce issue - so at the moment I am trying to allow the code to run a a timer interrupt once a pulse is seen on the RB7:4 pins to stop this.
What I want to know is: Can I not have both the OnPortChange interrupt running at the same time OnTimer interrupt? As when I switch both ON in the INTCON register the TMRO event stops getting called...?
Thanks for any advice
 

Attachments

  • HexCodeInput_Coded.c
    2.8 KB · Views: 238
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…