OK, here's another thought...
What's the MAXIMUM rate of change of what you want to detect? I mean, is it 1000 state changes per second? Obviously with a detented dial it may be on the order 10 to 20 state changes per second, and then only if it's 'cranking along'.
If it's less than 100 per second, seriously consider a timer tick at 1/1000 sec to just look at two pins and walk a state machine to match...
Message Edited by airswit on 03-08-200609:13 PM
Hello Trevor,
Here is another quite simple possibility, that appears to avoid the "creep" issue. The idea is similar to the first proposal by Mike, where an interrupt only occurs on Channel A, and Channel B is monitored during the ISR. The difference is that the edge on which the next interrupt will occur is toggled, before exiting the ISR.
For example, if the current interrupt is on a positive edge, the next edge of Channel A has to be negative, either one half cycle later for continued rotation in the same direction, or sooner if the direction reverses, as detected by the state of Channel B. So any random movement back and forth on the edge of the Channel A transition, should result in the counter incrementing and decrementing in quick succession, with no significant net creep. If the toggling of the counter is unacceptable for the particular application, simply ignore the LS bit of the counter.
With this method, there are two transitions per cycle, giving twice the number of counter increments/decrements.
Here is some pseudo-code to implement this concept within the ISR -
if (A_edge == 1)
if (Ch_B == 1) Count++;
else Count--;
else
if (Ch_B == 1) Count--;
else Count++;
Toggle A_edge;
Clear interrupt flag;
It would seem feasible to use an input capture channel for channel A, and a general purpose input for channel B. So timing data would be available to allow for calculation velocity, if required.
To allow for de-bounce of a non-optical rotary encoder, I would simply inhibit further Channel A interrupts, and start a timer with 20-50 ms timeout, before exiting the ISR. The timeout can then be monitored from within the main program loop, before the interrupt is re-enabled.
Regards,
Mac
Message Edited by bigmac on 03-09-200610:26 PM
bigmac wrote:OK, I LIKE that approach. It would work. It does require that the ISR toggles the edge-sensitivity before the edge can change, but a filter cap could do that. Unfortunately (only for me) the HC08GP32's IRQ pin doesn't allow you to detect rising edges.Here is another quite simple possibility, that appears to avoid the "creep" issue. The idea is similar to the first proposal by Mike, where an interrupt only occurs on Channel A, and Channel B is monitored during the ISR. The difference is that the edge on which the next interrupt will occur is toggled, before exiting the ISR.
Quote:... It does require that the ISR toggles the edge-sensitivity before the edge can change, but a filter cap could do that. Unfortunately (only for me) the HC08GP32's IRQ pin doesn't allow you to detect rising edges.
if (A_edge == 1)
if (Ch_B == 1) Count++;
else
if (Ch_B == 1) Count--;
Toggle A_edge;
Clear interrupt flag;
Regards,
Mac
airswit wrote:
well, i did some more digging (reading of the 550page datasheet), and found out that the interrupt pins can be edge triggered. now, should i just trigger on 1 edge (the positive edge) or both positive and negative edges?
now i am thinking to have the a channel on an interrupt pin and trigger on the positive edge. inside the isr I will test the B channel (on a regular GPI) and adjust my count accordingly.
as a side question, if i want to create a button interrupt (for user input, or whatever), and I trigger on the edge, can i leave off debounce circuitry, or is it still necessary to put a filter capacitor on the line?
Quote:Now, should i just trigger on 1 edge (the positive edge) or both positive and negative edges?
now i am thinking to have the a channel on an interrupt pin and trigger on the positive edge. inside the isr I will test the B channel (on a regular GPI) and adjust my count accordingly.
As a side question, if i want to create a button interrupt (for user input, or whatever), and I trigger on the edge, can i leave off debounce circuitry, or is it still necessary to put a filter capacitor on the line?
Mac and Trevor,
I think that the timer method Mac proposes is more complicated than needed.
Sampling the inputs on a timer interrupt and applying one of the debounce methods discussed in the 01-26-2006 12:05 PM part of the "Switch Debounce Software" topic in this forum.
In particular the simplest method, which is just sampling at an interval longer than the bounce period should work pretty well for a human interface device.
If you sample at a 1 ms to 10 ms interval and do the decoding by comparing with the last state, you will be able to get velocity information easily.
I don't know the details of the encoder, but most contact arrangements seem to bounce for less than 10 ms.
Some systems of my experience don't promise an absolute dial position, but just take the dial motion as the indication of the velocity to move the indicator. This has the advantage that missing counts at high velocity are not noticed by the user.
Steve Russell
Nohau Emulators
Hello Steve,
I agree that the sampling method is potentially simpler and will provide integral de-bounce, but for the rotary encoder decoding it may not be adequate, depending on the type of encoder. In particular, there would be no protection against "creep", as previously discussed in the thread.
I think it would be valid to summarize the situation as follows:
You are probably correct about bounce being typically less than 10 milliseconds, and minimising this is probably more important for the rotary encoder applications. However, I do not know how much unit-to-unit variation there is, and how the switch is affected as it ages, so I think it better not to "skimp" too much. Yes, I agree that a rotary encoder of this type cannot, in itself, provide absolute position control.
For individual pushbutton switch operation, I concur that the sampling method would be satisfactory, unless the operation of the switch requires the MCU to wake up from stop mode. Perhaps I was partly reacting to other theads within this forum, where attempts have been made to utilize the KBI module, wihout proper debounce measures.
Regards,
Mac
Actually, the sampling method that I use has no creep and misses no transitions. But my debounce algorithm is not that simple.
bigmac wrote:I agree that the sampling method is potentially simpler and will provide integral de-bounce, but for the rotary encoder decoding it may not be adequate, depending on the type of encoder. In particular, there would be no protection against "creep", as previously discussed in the thread.
Message Edited by rocco on 03-12-200603:14 PM
If it were me, I'd just use two pins on the processor and make sure you don't run over limit, like trying to feed 20v to them. Make sure one is an interrupt.
As to amplifiers or whatever, usually the rotary devices will already have signal shaping components in place and you can usually just tie them to input pins (a pullup MAY be required). If you're talking direct from some kind of photodetector, then yes, you should have an amplifier of some kind with a schmidt trigger buffer in the way.
If you want a SIMPLE interface, just set the interrupt to be in one direction, and in the ISR if the other pin is low it's one direction, if it's high it means the other direction. Use the direction to inc or dec a 'position' counter. Then on a timer tick throw out low position count values to keep from 'creeping'. Or use a 'double pass' routine where one routine passes the count to another with a limit based on time.
If your knob has no detents, and you can support it, use interrupts in BOTH directions on the pin. (I don't know your processor) Even if it means you need THREE pins. When you get a low-going interrupt, do the processing as before. When you get a high interrupt, however the inc or dec will be opposite. (Depending on interrupt direction). If you do the interrupt in both directions, then you shouldn't get ANY creep on your position, even if you're sitting right on a boundary.
Actually, I didn't think. If you just use 2 int pins... Call them pin A and pin B. Int on the A pin, get pin B state and if 0 dec your count, 1 means inc. Int on the B pin and read pin A. 0 means inc and 1 means dec your count. Sorry, had a brain fade.
Smart use of the timer in the routine can even give you 'acceleration' on your 'knob'. Like 'fast tuning' on a radio if you spin the knob.
Message Edited by mke_et on 03-07-200604:50 PM