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.

optical encoders?

Status
Not open for further replies.

hjl4

Member
Hi,

I hope someone out there has done this in assembly before.
I took apart a mouse, and removed the encoder wheels, along with the IR Led's.
I want to use this, as an encoder for an accelerator, using 2 bit gray code.
In other words, when thumb pressure is applied to a spring returned knob, it send gray code to micro. 16f628.
I can't use interupt as it is all ready used by a safety switch. My delema is knowing the direction(accel or deccelerate)the encoder is going. As the encoder is moved clockwise, the micro needs to increase speed of dc motor, and decrease when moving ccw. My guess is ,I should get 4 different speeds. Right?

I have searched this forum, and others, and there search engines sucks..with no good results.
I have googled, and everybody including there dog, has done this.
Unfortunately, I don't have time learning CHBasic or even C. I write in assembly exclusively.
I hope someone can help.
Thank you!
 
hjl4 said:
Hi,

I hope someone out there has done this in assembly before.
I took apart a mouse, and removed the encoder wheels, along with the IR Led's.
I want to use this, as an encoder for an accelerator, using 2 bit gray code.
In other words, when thumb pressure is applied to a spring returned knob, it send gray code to micro. 16f628.
I can't use interupt as it is all ready used by a safety switch. My delema is knowing the direction(accel or deccelerate)the encoder is going. As the encoder is moved clockwise, the micro needs to increase speed of dc motor, and decrease when moving ccw. My guess is ,I should get 4 different speeds. Right?

I have searched this forum, and others, and there search engines sucks..with no good results.
I have googled, and everybody including there dog, has done this.
Unfortunately, I don't have time learning CHBasic or even C. I write in assembly exclusively.
I hope someone can help.
Thank you!

There's more assembler code than anything else available, so using assembler is an advantage.

However, I don't think your scheme will work?, a mouse encoder doesn't output grey code, it's just a quadrature encoder. So you only get speed and direction, NOT absolute position.

The conventional way for throttle control is to use a pot.
 
Correct me if I'm wrong, but, it seems you would like to use one of the encoders for a speed control by determining if there's been a change and by the direction of the change, clockwise or anti-clockwise...

Polling the encoder A and B lines is perfectly acceptable... You can determine if the encoder has moved simply by checking a saved ENCOLD value to the current encoder value... You can determine which direction the encoder has moved by exclusive-or'ing the A or B bit of the old encoder value with the opposite bit of the current encoder value... After determining direction, adjust your speed value or variable up or down accordingly...

Good luck with your project... Regards, Mike

Code:
;
;  check the Rotary Encoder A and B switches for a change (the
;  SWDATA variable contains debounced switch data)
;
ISR_Encoder
        movf    SWDATA,W        ; get switch data  '------BA'    |B0
        andlw   b'00000011'     ; mask for B and A switches      |B0
        xorwf   ENCOLD,W        ; same as last reading?          |B0
        bz      ISR_NextColumn  ; yes, branch (no change)        |B0
        xorwf   ENCOLD,W        ; else 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 with new AB	   |B0
;
 
Thanks Mike and Nigel.
Last night I was very tired, as I worked on this all day.
And I could'nt visualize how this could be done.
Your right Nigel when you say it would'nt be grey code. What was I thinking?
And Mike I will definately go your way. Now that I have slept, I am refreshed, and now I can see the whole picture.

What sleep can do.
If I get stuck on this, I'll make sure to follow up. And if success, I will post my code here, to see if it could be optimized in any way.

Thanks Guys.
 
Before we start finding solutions to your problem, I have some issues with your assumptions:

I can't use interupt as it is all ready used by a safety switch.

By decoding which interrupt flag was set, you can use interrupts from several sources simultaneously.

Unless you need response times in order of microseconds, you don't really need interrupts to detect the safety switch closure. With a properly designed program, you can poll the safety switch once every 1-10 msec for instance. This is still faster than how most mechanical systems can respond anyway.

I took apart a mouse, and removed the encoder wheels, along with the IR Led's.
I want to use this, as an encoder for an accelerator, using 2 bit gray code.

It might be more of a pain to remanufacture the mouse into an optical encoder. It will be easier to find a PS2 mouse program to receive the step and direction signals already encoded in the serial PS2 protocol. You will need to use interrupts here though. Hence, if you insist on using interrupts for the safety switch, you would need to decode the interrupt source to use two interrupts simultaneously. Or you could also use a serial mouse.

If you convert the mouse into an optical encoder, you need to poll the signals at high speed to detect transistions. If you miss two transistions between polls, you can no longer determine the direction last taken. Interrupts will be useful here.

BTW, the quadrature signal from the encoder is in 2-bit gray code.
https://www.nist.gov/dads/HTML/graycode.html

Lastly, there are PICs with built-in quadrature decoders.
 
Polling could be hokey if the motor speed is significant. You need to dedicate a lot of time to polling.

Polling could be done, but from what you say, you may not need to do this. You say the ext interrupt is taken up by a safety switch, and in any case a single interrupt won't read gray code. That's what the interrupt-on-port-change RBIE/RBIF is for. This will cover any changes in portB<7:4> pins configured as inputs, so any of these 4 you don't use as encoder inputs should be used for an output to avoid useless interrupts.
 
Thanks Oznog,

I thought I had read that somewhere. So if I set up Portb as interupt, lets say bit 1 and 2 are inputs and the rest outputs, I can still have bit 3 and 4 as outputs?
If so, That would save me from trying to see what i can squeeze out of the Pic. I'll have plenty of pins left over.
The Datasheets can be so overwhelming sometimes.
I'll read it again, and see if I can set it up that way. It would save precious time, instead of frequent continuous polling.



Thanks.
 
Oznog said:
Polling could be hokey if the motor speed is significant. You need to dedicate a lot of time to polling.

We're only talking about polling the rotary encoder which is being used as a control, not polling a rotary encoder attached to a motor...

Polling (and debouncing) the encoder switches, or any switches for that matter, can be automated as a background task quite easily using an ISR (interrupt service routine)... I often use TMR2 1.0-msec interrupts and ISR code for switch management to provide such niceties as switchpress audio feedback (40-msec short beeps), 'short' and 'long' switchpress detection, and rotary encoder translation to pseudo "INC" and "DEC" switches...

Kind regards, Mike
 
I'd definitely use RBIF but timer driven sampling should work as well. You can pretty easily estimate the speed of of the quad encoder pulses. 1mS might be a bit slow as you should be sampling at least 2X the max rate.

I've played with mouse encoders and some of them can be flakey. I wound up building a state machine that factored in glitches and it worked pretty well. just consider all possible transitions and you should be fine. I used the RBIF (int on change) feature of a midrange PIC.
 
hjl4 (and gang),

As you can see, there's many many different ways to accomplish the same thing... Don't be afraid to experiment and try different methods... The interrupt on change method is certainly just as viable as an interrupt driven polling method and there are subtle and not so subtle advantages and disadvantages to each method... Many times your hardware design may force you to use a particular method...

I've found rotary encoders with a built-in push button switch on the shaft (PEC11 series and NSE120 series) can provide rather simple and elegant single front panel control solutions for some projects... Rotate the encoder to scroll through LCD menus, select values from a list, or to increment or decrement values... Decode 'short' and 'long' encoder push button switch presses for <OK>, <ESC>, or <TAB> type functions...

Regards, Mike
 
Hi Mike,

I have'nt had time to work on my encoder or program.
I 'm trying to read thru your first reply, and I'm having a bit of problem making sense of it.
If I use quadrature encoder, and turn it beyond it's 2 bits(3h), how does the Pic know if I am rotating it clockwise or ccw if I go beyond the 2 bit limit. I mean after 01,11,10,00, and then what???. Does the Pic see this as a reset back to 01?
I have an encoder with total of 25 steps.(optical that is).

Maybe I'm way over my head here.
I can't seem to grasp the concept.

Anyways,Thanks for your replies.
 
hjl4 said:
Hi Mike,

I have'nt had time to work on my encoder or program.
I 'm trying to read thru your first reply, and I'm having a bit of problem making sense of it.
If I use quadrature encoder, and turn it beyond it's 2 bits(3h), how does the Pic know if I am rotating it clockwise or ccw if I go beyond the 2 bit limit. I mean after 01,11,10,00, and then what???. Does the Pic see this as a reset back to 01?
I have an encoder with total of 25 steps.(optical that is).

It's a question of which bit changes first, this tells the program which way it's turning.
 
You can define a rectangular area so that you can create absolute positions with your mouse.

In your code, you need to compare whether each and every mouse move goes out of the area, and if it does, have it return to the last spot in the area.

It's just like the mouse arrow on your screen. It never falls off of the screen completely. You still see at least one pixel even if you moved it to the bottom right.
 
you don't have to kill yourself with loads of code if you can live with one more chip (dual D-type flip flop). this way all you have to do is count up or down:
**broken link removed**
 
a quadrature state machine is a tiny bit of code.

there are 4 input values: 00, 01, 11, 10 in that sequence. its a gray code. if its rotating one direction, the sequence goes forward (and loops around). the other direction, the sequence goes backwards (and loops around). if you have the space for it, create a 4x4 array with the current and previous input values as the the indexes. the value of that entry is one of {error, cw, ccw, no-change}. You can do it in less code/table space but that's the simplest way to do it. There is a very tight solution that uses xor but its a bit hard to follow for a newbie.

Once you have direction, you accumulate pulses - add them for CW, subtract for CCW. Your pulse count will tell you where you are.
 
panic mode said:
you don't have to kill yourself with loads of code if you can live with one more chip (dual D-type flip flop). this way all you have to do is count up or down:
**broken link removed**
I guess it's a matter of opinion and preference (grin)...

Why throw expensive hardware at a problem that can be solved with a dozen lines of 'free' code (grin)?

Kind regards, Mike
 
hjl4 said:
Hi Mike,

I have'nt had time to work on my encoder or program.
I 'm trying to read thru your first reply, and I'm having a bit of problem making sense of it.
If I use quadrature encoder, and turn it beyond it's 2 bits(3h), how does the Pic know if I am rotating it clockwise or ccw if I go beyond the 2 bit limit. I mean after 01,11,10,00, and then what???. Does the Pic see this as a reset back to 01?
I have an encoder with total of 25 steps.(optical that is).

Maybe I'm way over my head here.
I can't seem to grasp the concept.

Anyways,Thanks for your replies.

Yes, it goes back to 01... As Philba mentioned, it's a repeating pattern of four values that the encoder moves through in either direction... As mentioned earlier, one method for determining encoder direction is by exclusive or'ing the A or B bit of the last encoder value (my ENCOLD var) with the opposite bit of the new encoder value...



If the old encoder position was AB=11 and the new encoder position is AB=01 (moving to the right in the graph above), then the direction is '1' (B_old^A_new=1^0=1)... Save the new encoder position '01', use the direction bit to branch to your increment speed or decrement speed code, then wait for another encoder change... If the next new encoder position is '00' (another move to the right) the direction will again be '1' (B_old^A_new=1^0=1) and if the new encoder position is '11' (a move to the left in the graph) the direction will be '0' (B_old^A_new=1^1=0)...

Pick any spot in the graph above as your old encoder position and then pick a position to the left or right as your new encoder position and work through the B_old ^ A_new logic (^ is the "exclusive or" operator)... You'll always get a '1' when moving the encoder in one direction and a '0' when moving the encoder in the other direction...

Philba mentioned that the "exclusive-or" code might be a little difficult to understand for a newcomer compared to "table" code but he didn't post a code example... I've always found table code examples confusing but I suspect either (or any) code method might be difficult for a newcomer to grasp if you don't have a good understanding of the quadrature AB signals...

Good luck on your project... Have fun... Kind regards, Mike

<added>

BTW, which PIC are you using? What oscillator/frequency (INTOSC, XTAL)?
 

Attachments

  • encoder_waveform.jpg
    encoder_waveform.jpg
    9 KB · Views: 636
philba said:
I'd definitely use RBIF but timer driven sampling should work as well. You can pretty easily estimate the speed of of the quad encoder pulses. 1mS might be a bit slow as you should be sampling at least 2X the max rate.
He'd have to spin the knob on his 25-pulse/revolution encoder more than 40 times per second (2400 rpm) to miss a pulse when polling with 1-msec interrupts...

Kind regards, Mike
 
Thanks Mike,

I have to say I am now grasping the concept of all this. All my PWM's will be via discreet components. The Pic is actually just choosing which frequency is to be chosen.

Why did I go this way?Because for me and my limited programming knowledge of Pic's, it seemed like an easier way of getting things done.
Why not go discreet all the way?
Because the company I work for, received samples from Microchip.
They used (or chose) the one's they needed and had leftovers. So I decided to try my hand at this.
I'm using 16f628 for this project. I have16lf877a, 12f629,12f675 and an old 16f84. To make an LED flash or alarm sound off, or stepper motor control, with 7 segment display, I have done that. Now just trying to get digital encoder to work with DC motor, as a speed control.
Sometimes to grasp the concept of things, is the hardest. The algorithym is also challenging, and I've spent many hours getting it right. I know there is always a better way.

So that is my story.

Thanks to all for your inputs as they are very appreciated.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top