Hi there,
I wrote a C++ class to decode an “endless potentiometer” and would like to share it here, in the case it could be useful to someone.
An endless potentiometer is a kind of crossing between a regular potentiometer and a rotary encoder. It can rotate 360° without stop and has two outputs in phase quadrature, as shown on the picture below:
The only parts I could find so far are the Alpha RV112FF series. If someone finds other endless potentiometer parts, please tell us.
It is possible to retrieve the absolute angular position of the shaft, or a relative angular movement. They work similarly to rotary encoders, but the latter are very coarse, making them unsuitable to audio FX parameter adjustment (contrary to standard analog pots). These endless pot give you the best of both worlds, although they are a bit expensive (~4 €/part when writing these lines) and each unit uses 2 ADC channels from the microcontroller.
It’s a good solution to switch between different parameters on the same physical control, thus saving space. Or retrieve saved presets without having the current pot position altering the freshly restored settings.
The decoding is not very challenging but there are several pitfalls related to the taper imperfection if we want the angular position to be as continuous and monotonic as possible. The PotEndless
class takes measured voltages as input (output of the ADCs) and outputs two angular positions: one physical, and one counting the total number of turns from an initial physical position. A model with graphs and formulas is shown here, for the math interested people.
If a rotary encoder behavior is desired, it is recommended to filter out the noise from the result before trying to get relative movements (delta between two positions). Otherwise small variations will be completely buried into the noise. Filtering could be a low-pass filter, an adaptive band-pass filter (like the excellent smoother from Cytomic) completed by an hysteresis. But this is not the scope of this class.
The use is quite simple with the following methods:
set_safety_margin()
tells the object the extent of the “unsafe” values at the end of the taper range. Default should be O.K., and you can set it to 0 to bypass this processing if the result is good enough.set_dualpot_val()
feeds the object with a new measurement (2 × 16 bits from the ADCs).get_pos_phys()
retrieves the physical position of the shaft.get_pos()
retrieves the current logical position (number of integer turns + fractional position).set_pos()
resets the logical position.
Example of decoded position vs. ADC outputs:
There is another approach by Bjørn Brandal, but it focuses mainly on relative decoding.
I hope this will be helpful!