Author Topic: Rotary Encoders and interrupts  (Read 8317 times)

0 Members and 2 Guests are viewing this topic.

Offline Dan MoosTopic starter

  • Frequent Contributor
  • **
  • Posts: 359
  • Country: us
Rotary Encoders and interrupts
« on: October 18, 2016, 12:30:47 am »
I'm wondering if I really need to use interrupts for the rotary encoder in my project.

Atmega328 running at 8 mHz. Probably up that to sixteen in the end product.

When not getting input, this things his be sitting idle, so 99 percent of the time, the only task the mcu has I'd to wait for input. What's more, the encoder is only for user interface purposes, so the only thing competing with the encoder will be LCD updates through I2C, and a few variables being updated. The only time the mcu will really be working hard is when other buttons get pressed.

All this to ask if a rotary encoder can work well without interrupts in my scenario.

Another wrinkle. My reason for asking is I would love to put my entire user interface (~18 buttons and the encoder) on a single shift register chain. I don't NEED to do this, but it gives me some options if I save some pins.

Also, I'm leaning toward debouncing the encoder with Schmidt triggers. My guess is this is better for having the mcu keep up than a software debounce, but maybe bad because if it doesn't keep up, glitches can't be caught the way a proper software debounce might.

Bad idea?
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 10089
  • Country: us
Re: Rotary Encoders and interrupts
« Reply #1 on: October 18, 2016, 01:56:41 am »
I'm in the minority, I captured edge interrupts on all 4 transitions.  The code works fine but there are a number of folks who prefer polling or polling using a timer.
 

Offline obiwanjacobi

  • Super Contributor
  • ***
  • Posts: 1030
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Rotary Encoders and interrupts
« Reply #2 on: October 18, 2016, 06:13:55 am »
The thinking of polling your buttons is that when the buttons get old and wear their bounce may become more prominent. That could lead to the interrupt being fired a lot more than you anticipated - taking all the cycles. Your program will become sluggish because 'all' time is spent in the ISR.

If you keep that in mind and have some hardware debouncing in place (RC at the least), I think it could work well.

If you're gonna use shift regs, then polling is the only option. That polling can be triggered by a timer interrupt though...
Clocking in 3 bytes (24 bits: 18+encoder) should not be problem - you won't miss any button clicks/state changes.
(Remember to mark any variable shared between you main loop and the ISR as volatile.)
Wrong code should not compile!
 

Offline rs20

  • Super Contributor
  • ***
  • Posts: 2323
  • Country: au
Re: Rotary Encoders and interrupts
« Reply #3 on: October 18, 2016, 06:32:10 am »
The thinking of polling your buttons is that when the buttons get old and wear their bounce may become more prominent. That could lead to the interrupt being fired a lot more than you anticipated - taking all the cycles. Your program will become sluggish because 'all' time is spent in the ISR.

If you keep that in mind and have some hardware debouncing in place (RC at the least), I think it could work well.

Absolutely right about the issue I have with interrupt-based rotary encoders -- they are optimized for picking up contact bounce which has no useful information content. What I don't understand though, is why people start spending $$ on board space and components for RC debouncing when you can simply poll for free.  There seems to be a mistaken notion that interrupts "are for external events", and so if you have an external event, you "obviously use interrupts".  So people seem to be biased towards using them even when this use doesn't have any actual engineering reason behind it.

The main disadvantage of polling is that you are spending a certain percentage of your CPU time looking for rotary encoder events, even when there is nothing happening on the rotary encoder. Having said that, a fixed CPU load is preferable to a spiky, unpredictable CPU load any day of the week -- especially with most MCU firmware, which has nothing useful to do with spare cycles anyway. So in most cases (including the OP's), the only difference is a marginal saving in power consumption.
 

Offline filssavi

  • Frequent Contributor
  • **
  • Posts: 433
Re: Rotary Encoders and interrupts
« Reply #4 on: October 18, 2016, 07:04:39 am »

 What I don't understand though, is why people start spending $$ on board space and components for RC debouncing when you can simply poll for free.  There seems
First of all you have to consider that for all but the highest volume products (as in 10's of million of units) r' and C'è are practically free (you are talking fractions of a cent), you would obviously use values you already have uses in the desig, so they will not take up any additional PnP reels
As for board space of course you need some, but with 0402/0201 components it is not that bad in most cases

As for polling, if the MCU is doing nothing most of the time un production, you probably have chosen an mcu that is too powerfull, for some applications like household appliances they still use 4 bit MCU's (yes 4 bits it's not a mistake), those parts are usually not in the catalogo/on website though so you might need to ask a Sales Rep
There are cases then where the MCU is already working hard enough and adding debouncing isn't that helpful

We come now at the other big problem with polling, if not done at supidly high frequencies (and then Power consumption is an issue) you might have delays between switch closing and action, for a UI it might br fine,but for example on an interlock in n X-ray macchine (of any kind) it certainly is not ideal
 

Offline obiwanjacobi

  • Super Contributor
  • ***
  • Posts: 1030
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Rotary Encoders and interrupts
« Reply #5 on: October 18, 2016, 07:17:56 am »
I have seen more bugs in software debounce routines than hardware debounce circuits.
Also, developing software is relatively more expensive for smaller production runs.
Another reason why I think people lean towards using interrupts, is because its a 'free' way to let your MCU do multi-tasking.
Having to poll a lot of inputs may turn you program into spaghetti.
Wrong code should not compile!
 

Offline rs20

  • Super Contributor
  • ***
  • Posts: 2323
  • Country: au
Re: Rotary Encoders and interrupts
« Reply #6 on: October 18, 2016, 07:57:03 am »
No debouncing required, hardware or software. Just poll. And polling isn't spaghetti if you use a timer interrupt.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1916
  • Country: se
Re: Rotary Encoders and interrupts
« Reply #7 on: October 18, 2016, 08:27:01 am »
All this to ask if a rotary encoder can work well without interrupts in my scenario.
[...8<...]
Also, I'm leaning toward debouncing the encoder with Schmidt triggers. My guess is this is better for having the mcu keep up than a software debounce, but maybe bad because if it doesn't keep up, glitches can't be caught the way a proper software debounce might.

The attached code contains the user input handling in my power supply: encoders' rotation, push buttons (long and short presses) and UART - which I edited out, as not relevant here.

It's for a STMF042, and uses the dreaded HAL, but should be fairly readable and portable.

The core is the Debounce() function, which I call more or less every 1ms, triggered by the SysTick.
Since only one button and one encoder is served in each call, the actual sampling interval is 2ms.
The Debounce() function is fast enough to be called in the SysTick handler, but it could be also called in the main loop.

No need for edge interrupts, and input events are delivered in a queue (inputRing) the application can read with ReadInput() (no spaghetti here).
Excess events are simply discarded.


As for the Schmitt triggers: the encoders are HW debounced with RCs (10kohm/47nF IIRC)+74HC14.

Events are not lost even when turning the encoders at highest speed possible (for my fingers, at least...I did not try attaching a drill to the shaft).

As the encoders are the 30-detents 15-pulses type, only a very simple direction detection routine is needed (and, indeed, possible).
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Rotary Encoders and interrupts
« Reply #8 on: October 18, 2016, 10:25:57 am »
Quote
Bad idea?

it depends on the application. the key here is to understand that the incoming pulses are unpredictable so the polling has to be done sufficiently fast. that means that 1) the main loop needs to be done sufficiently fast if the polling is done there; or 2) the polling routine needs to be called periodically.

I would say that it takes 80 ticks to process a input, and 20 ticks for isr overhead. So if you have to execute the polling routines once every 1ms on a 1MIPS mcu, the "cost" to the mcu is 80 / 1000 = 10%.

You can similarly estimate the cost via isr and I'm fairly confident that unless you are in a situation of constantly rotating encoder (a motor sensor for example), you are going to spend less via interrupts, even if you factor in the isr overhead and debouncing.

on debouncing: I generally do it in hardware - problems are best handled locally.
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Rotary Encoders and interrupts
« Reply #9 on: October 18, 2016, 10:28:03 am »
for individual keys, the kahn debouncing routine I posted here a while ago is quite good.

for encoders, use the state machine approach (I posted an example here as well) - it is incredibly resistant to bounces.
================================
https://dannyelectronics.wordpress.com/
 

Offline madires

  • Super Contributor
  • ***
  • Posts: 9223
  • Country: de
  • A qualified hobbyist ;)
Re: Rotary Encoders and interrupts
« Reply #10 on: October 18, 2016, 10:55:58 am »
As the encoders are the 30-detents 15-pulses type, only a very simple direction detection routine is needed (and, indeed, possible).

Those work fine with polling every 5ms, which are also sufficient to get the turning velocity, if you like to support a dynamic change of steps. Something developers often miss, is the diameter of the knob attached to the rotary encoder. With a larger diameter the encoder becomes slower, i.e. you can increase the polling delay, For multiple encoders you would simply poll all in a row every few ms. From what I've seen, good encoders got a bounce period of about max. 2-3ms. Encoders with detents = pulses, i.e. all four Gray code steps per detent, are harder to handle.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1916
  • Country: se
Re: Rotary Encoders and interrupts
« Reply #11 on: October 18, 2016, 11:04:04 am »
for individual keys, the kahn debouncing routine I posted here a while ago is quite good.

for encoders, use the state machine approach (I posted an example here as well) - it is incredibly resistant to bounces.
Ah, yes, for four-phases-per-click encoders (detents == pluses  ;D) that's a really good way.
For two-phases-per-click (detents == 2*pulses) there's very little you can do...once the state machine is adapted, it is equivalent to my code.
Unless you want a detection every two clicks  ;).


Those work fine with polling every 5ms, which are also sufficient to get the turning velocity, if you like to support a dynamic change of steps. Something developers often miss, is the diameter of the knob attached to the rotary encoder.
I though about that, but then preferred to keep it simple (I should have attached a timestamp to each event).
I just press the shaft to change step. Long press for preset mode and other functions.
Smallish knobs (~2cm diameter).

The whole thing work remarkably well (no bounces, no jitter, very responsive).
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline rs20

  • Super Contributor
  • ***
  • Posts: 2323
  • Country: au
Re: Rotary Encoders and interrupts
« Reply #12 on: October 18, 2016, 11:39:28 am »
You can similarly estimate the cost via isr and I'm fairly confident that unless you are in a situation of constantly rotating encoder (a motor sensor for example), you are going to spend less via interrupts, even if you factor in the isr overhead and debouncing.
What exactly is being "spent" here? Again, unless we're talking about marginal power savings, those "wasted" cycles weren't going to be doing anything useful anyway -- or at least, it's bold to make that claim without knowing details of the project.
 

Offline filssavi

  • Frequent Contributor
  • **
  • Posts: 433
Re: Rotary Encoders and interrupts
« Reply #13 on: October 18, 2016, 11:49:46 am »
There seem to be a strange focus on HMI, in that case the user is so slow that anything can be done in software, if we step out of that area things get hairy fast,for example let's say that the encoder (100 pulses per rotation)  is attached to an electric motor running at 3k rpm (and keep in mind that i've been  very generous choosing a lowish motor Speed and not a top notch encoder (500, 1000 pulses per rev) then you need to poll at al least twice the frequency of the encoder signal  (Shannon) or you'll miss pulses and the control isn't precise any more, so after few simple calculations you'll find that the polling frequency has to be at least 10 kHz, now that Number could very easily go up by a factor ~10 or more if we up rpm's and encoder resolution or if direction detection is needed (in that case you need to sample both A and B so double the polling frequency again)

Now is such a load on the processor fine just to read the sensors depends on the application, keep in mind that you will have also to do also a couple of pi(d) loops and more often than not clarke,park,anticlarke,antipark (if you are controllino all but a dc/bldc motor)

Now there is a point where a dedicated hardware encoder detector is necessary and then the polling vs interrupt depate is not relevant any more...
 

Offline filssavi

  • Frequent Contributor
  • **
  • Posts: 433
Re: Rotary Encoders and interrupts
« Reply #14 on: October 18, 2016, 11:58:39 am »
You can similarly estimate the cost via isr and I'm fairly confident that unless you are in a situation of constantly rotating encoder (a motor sensor for example), you are going to spend less via interrupts, even if you factor in the isr overhead and debouncing.
What exactly is being "spent" here? Again, unless we're talking about marginal power savings, those "wasted" cycles weren't going to be doing anything useful anyway -- or at least, it's bold to make that claim without knowing details of the project.

Money is spent, as in I'll have to specify a faster MCU since in a real product (as in not an hobbist/maker project) you will buy a MCU which is just capable enough to do the job, not a faster one, just to waste some Power

And the "marginal Power savings" might  not be as marginal as you think first because using interrupts enables you to go in Deep sleep mode, with polling sleep is not an option, secondly in a battery powered devices ant Power saving is important even marginal  ones since they add up
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4606
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: Rotary Encoders and interrupts
« Reply #15 on: October 18, 2016, 12:32:24 pm »
STM32's have timers with Encoder input mode. Simply read the timer to see how much it has moved.
Could be an option. I used the cheapest I could find for a project with two hmi rotary encoders. A STM32F051.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1916
  • Country: se
Re: Rotary Encoders and interrupts
« Reply #16 on: October 18, 2016, 12:49:53 pm »
STM32's have timers with Encoder input mode. Simply read the timer to see how much it has moved.
Could be an option. I used the cheapest I could find for a project with two hmi rotary encoders. A STM32F051.
Yup,
I also had a version with that (should do some git commit message scavenging to dig it out), but it's not useful for the OP on an ATmega.

In the end, though, I preferred this version as the code is much simpler: the controller has plenty of time to handle the LCD, the encoders and buttons and the OCP (hardware CC mode, but SW controlled OCP with 5 selectable delay 1ms-10s).
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 10089
  • Country: us
Re: Rotary Encoders and interrupts
« Reply #17 on: October 18, 2016, 02:50:38 pm »
Here is code for an ATmega128 (I think) that uses the 4 edges to count and measure distance.  I have used the identical code with an encoder on one of the Digilent AVR boards when I was adding switches, knobs and dials to Microsoft Flight Simulator.  That was a few years back...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->