Interrupts Vs. Polling in Embedded Software

(article continued from previous page)

Thus far, the encoder counter software has been manually checking the values of the encoder sensor pins over and over. This is called “polling”. Polling is perfectly acceptable for slow signals. Polling is also acceptable in tight loops where the processor can be dedicated to the task.

But, the most optimal solution for reading digital pin changes is to switch from polled reading to interrupt reading. Almost all microcontrollers include a hardware feature to interrupt the current software routine and run a different routine when a pin changes states. By relying on the hardware to notice a change, the software doesn’t have to spend any time watching the pins.

For example, using hardware interrupts, the software can be dividing a number by 10 or displaying something on the LCD and suddenly jump to the read routine. When the read is finished, the software will return and continue where it left off. Pretty elegant, huh?

Reading pin changes with interrupts rather than polling produces the perfect minimum number of reads.

Reading pin changes with interrupts rather than polling produces the perfect minimum number of reads.

In the above trace, the read routine is called automatically by the hardware interrupt each time encoder sensor A or encoder sensor B changes state. The result is that the program only reads the pins when they change -- no more often and no less often. Four reads per complete encoder wave.

If there is a glitch or roll-back on the encoder outputs, the read routine will be called automatically beyond the four minimum reads. Why? Because the hardware is always watching the encoder pins.

Let’s test the interrupts by speeding up the motor to 8300 RPM. That’s a change of 2.44x from 3400 RPM.

When the test motor is sped up, the logic analyzer trace shows that the frequency of reads automatically increases to match the motor speed.

When the test motor is sped up, the logic analyzer trace shows that the frequency of reads automatically increases to match the motor speed.

As you can see, the encoder pulses occur more frequently due to the motor running faster. But, since the interrupt hardware is constantly watching the encoder pins, the read routine is automatically called more often.

And remember, the accumulated count is converted to a string and displayed on the screen several times a second during non-interrupt time. The program is now capable of both reading the encoder perfectly and displaying the value.

A slight delay between encoder signal changes and read routine completion is shown on a logic analyzer trace.

A slight delay between encoder signal changes and read routine completion is shown on a logic analyzer trace.

The Read pin (top line in the above trace) is toggled by software after the read routine and computations are completed. That is, the read pin changes state when work is complete and ready for a new read. The logic analyzer trace shows this as a slight delay in the read line after an encoder sensor has changed states. It appears that the motor speed could be doubled again and the processor could keep up.

Because the Counter Project is so flexible, the encoder read routine is difficult to enhance to the microcontroller’s theoretical maximum without giving up some options. The read routine performs a lot of “if” statements to determine the type of encoder mode  (analog, digital, single channel A, single channel B, either channel, dual-channel quadrature). And, after incrementing the count, the routine must check to see if the motor needs to be automatically turned off. In the meantime, non-interrupt code is watching the dial and switches, and updating the display.

With the algorithm and methodology firmly established, the implementation was further optimized to eliminate as much work as possible during interrupt time without sacrificing functionality. The final Counter Project read routine performs all of the work necessary in less than 10 µS. After some testing, it was determined that the device is responsive to user input and works well as long as the total time between interrupts is 15 µS or more (meaning the non-interrupt processing gets some time).

Therefore, the maximum quadrature encoder count per second is:

1 / 0.000015 = 66666 digital pulses per second
66666 / 4 = 16666 quadrature encoder counts per second

That’s about 1 million RPM with a 1 count-per-revolution quadrature encoder. Or, 62,000 RPM with a 16 count-per-revolution quadrature encoder.

Even so, specialized off-the-shelf counters are capable of 10 to 1000 times faster digital counting. Those devices usually use dedicated hardware to perform the counting.

Without revising the circuit, performance of my counting device could be improved by:

Overall Results

I really like the project box with all the labels, switches, and buttons. It looks like a device out of Ghostbusters.

BroMatic™ 2000 Electronic Counter or possibly an ectoplasmic diffuser.

BroMatic™ 2000 Electronic Counter or possibly an ectoplasmic diffuser.

After many days of optimizations, the digital counting performance is accurate and reasonably speedy. The analog performance is okay, but could use a little bit more work.

The motor speed control and auto stop feature is very useful. A full H-bridge would have allowed the motor to stop faster and be reversible. But, that’s probably overkill.

The OLED display is absolutely fantastic to look at. No ambient or backlighting is required. It is more modern looking than an LCD. UPDATE: The OLED failed.

The Adjust Dial rotary encoder is smooth and easy to use. I'll probably incorporate a rotary encoder dial into future projects.