Encoder programming

Hi folks, Im having great trouble in pic programming and hope someone can help me.Im designing a motor controller circuit using pic 16f877a. Iv got a single ended quadrature encoder (It has 5 outputs - a channel, b channel, z channel, 5v, ground). Iv finished the coding for the motor controller part in mikroc. NowI dont know how to do the programming for this encoder. Have to get the feedback(Pulses) from this encoder compare it with the expected pulses and make adjestments. Can someone show me a sample coding for this in mikroc. Iv googled this for last several days and read so many articles but I still couldnt do the coding.

This is the coding in mikroc iv written so far. This works. If possible can someone integrate the encoder components in this

void m1(int forward) { if(forward) { PORTC.F4=1; PORTC.F5=0; } else { PORTC.F4=0; PORTC.F5=1; } }

void m2(int forward) { if(forward) { PORTC.F6=1; PORTC.F7=0; } else { PORTC.F6=0; PORTC.F7=1; } }

void setup_timer0() //for encoder 1 { //should be called after configuring the ports(coresponding tris) TRISA.F4=1; //encoder signal input bit OPTION_REG=0x80; OPTION_REG.T0CS=1; //timer0 counter mode }

void setup_timer1() { TRISC.F0=1;//encorder signal input bit T1CON=0;//configure prescale of timer1 T1CON.TMR1CS=1;//To set RC0 as input source for timer1 T1CON.T1OSCEN=0;//internal oscillator disabled T1CON.T1SYNC=1;//disable synchronization T1CON.TMR1ON=1;//start timer1 } void main() {

PORTC=0; TRISC=0; setup_timer0(); setup_timer1(); PWM1_INIT(5000);//Both pwm generators share one pulse width value. So one

//initializing is enough PWM1_change_duty(80); pwm2_change_duty(200); pwm1_start(); pwm2_start(); m1(1); //m1 forward m2(0); //m2 backward

while(1) { delay_ms(1000); PORTB=TMR0; //Encorder1 value PORTD=TMR1L; //Encorder2 value } }

--------------------------------------- This message was sent using the comp.arch.embedded web interface on

formatting link

Reply to
vibz86
Loading thread data ...

I can _help_ you, but if you want me to do your work you may contact me professionally and I'll charge for it.

An encoder produces a 2-bit gray code that counts up or down depending on the direction of the encoder. The algorithm that has always worked best for me is to take that gray code, translate it into 2 bits of straight binary, then have a nice wide position register that follows those two bits.

To translate into straight binary you just need to xor the least significant bit by the most significant bit (just arbitrarily choose whether A or B is most significant, then if the position doesn't 'go' in the right direction reverse them).

So do something like this. This code must be called either every time an encoder input changes (which would require that you set up the encoder inputs to interrupt on change) or often enough that you're guaranteed to catch every encoder change (which requires that you figure out the maximum possible speed of the encoder and make sure you call this code at least once for each encoder output state -- I'd aim for twice).

Don't just copy this code in and expect it to work. In fact, don't _touch_ this until you've worked out the operation on paper and understand _why_ it works. Working with encoders is easy, once you've turned your brain upside down.

static int position; int x, diff;

x = (port capture such that x.0 = A and x.1 = B, and all higher bits are zero); x ^= x >> 1; // xor x.0 with x.1 diff = (position - x) & 0x0003; // get the difference in the LSB switch (diff) { case 1: --position; // encoder has decremented, follow it break;

case 2: // encoder has incremented or decremented twice, // we're lost (insert your error recovery here) break;

case 3: ++position; // encoder has incremented, follow it break;

case 0: // encoder hasn't moved break; }

--
www.wescottdesign.com
Reply to
Tim Wescott

an

The fun of course being that it requires either interrupts that can be set to trigger on either edge, or keeping the interrupt configuration register up to date with which edge should be expected next, or running each signal into two pins one set to trigger on rising and the other on falling...

Reply to
Chris Stratton

Unless I'm extremely constrained by cost or board space or whatever, I've found that life is simpler by letting an external chip handle reading quadrature encoders. Nowadays it's usually this guy:

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

The fun of course being that it requires either interrupts that can be set to trigger on either edge, or keeping the interrupt configuration register up to date with which edge should be expected next, or running each signal into two pins one set to trigger on rising and the other on falling... Isn't it just as effective to do it in hardware with flipflops.... giving step and direction ?

Reply to
TTman

A bunch of microcontrollers now have QEI hardware on-board. For example, dsPIC3x, ARM7 Cortex from Luminary/TI and ST, and I'm sure many others. Some of them may even handle the index pulse correctly.

Reply to
Spehro Pefhany

Good point. I haven't used any lately (although I did have a brief, unhappy fling with a member of the DSP56800 family) but "an external chip" probably should be changed to "an integrated or external peripheral."

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

Or if the need for absolute position is not that great one can interrupt on only A or B changes, then poll both to check the current state.

Recently used an encoder that was prone to signal bouncing. IIRC my solution was when A (or B) changed state (and therefore subject to further bouncing) I disabled the IRQ on A (or B) and enabled on B (or A). When one channel was unstable the other was quite stable.

Because my CPU didn't have an IRQ-on-change mode for these inputs I would poll the pin first and set the IRQ for the level it was not.

At low-to-no RPM most any encoder is prone to bounce. Haven't wrapped my head around Tim's pseudo code but possibly case 2 or case 0 will handle A (or B) toggling repeatedly before B (or A) changes again.

Reply to
David Kelly

Both of the methods you mention are prone to false motion when something is bouncing.

With my method you only need to capture the 'real' transitions. If you get bouncing then my method will see alternating case 1 and case 3, and will (quite properly) let the measured position oscillate by one LSB until the bouncing settles.

I see a lot of different ways to do this; the ones that work end up being logically identical to mine. There are innumerable ways to do it with varying degrees of wrongness.

--
www.wescottdesign.com
Reply to
Tim Wescott

Look on my website under examples. Unfortunately there is so much noise on search engines now you are not very likely to find it with any obvious keywords.

formatting link

Reply to
MK

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.