I hooked up one of the detent potentiometers to an Arduino Nano and took some readings. I thought that with 11 positions in a range from 0 to 1023 that they would most likely be evenly spaced apart. Not so! The lowest position gives a pretty solid 0 but the next position is around 14. So I used a table of threshold values to map the readings to index values from 0 to 10 (11 distinct values).

The program (sketch) is in the attachments. Here's a run starting from the top and turning the pot CCW and then back. The index is shown first followed by the value obtained from the A/D conversion.

The sample time for the readings is set at 100 ms. And yes, you can miss a stop if you turn the pot fast enough. Once in position, the readings turn out to be pretty steady varying maybe 2 or 3 values. I'm not sure if all of them will work this well or if my table of threshold values will hold up in all cases; I arrived at the values using the GRJ method of observation.

The good news is that these will work out for what I have in mind. I mounted the pot in a plastic box and ran a 6 foot cable to the Arduino for these tests. They will be useful for controls on a front panel.


Images (1)
Files (1)

Another thing that I noticed about these pots is that the readings change as you lean toward the next stop position. While at rest, the values are steady with only slight variations. But just applying pressure against the stops will raise or lower the value significantly. They aren't going outside the range of values setup in the table and are not giving any false triggers so that seems to be okay.

These are just pots with mechanical stops and are subject to some wiggle room. My applications are not mission critical in that regard. So I think they're going to work out.

I'm guessing maybe the audio taper (or reverse taper), the A or C on this graph might have given you a better result with the steps.  I truthfully didn't think of what you experienced when you bought these.  I'm still a little confused about the wide range of values, what exactly does the circuit look like that's feeding the A/D?  Is there some loading we're not taking into account?  Maybe using a lower value pot would have minimized any loading effects.


Images (1)

GRJ: You may be right about the different tapers. The low and high ends of these linear pots have a tighter range of values. It would be interesting to try the others just to see what comes out.

I'm satisfied that these will do the job. Just a bit of a surprise that the spacing is so uneven. I plan to check some of the others from the lot that I got from Mouser. I expect that they will behave in a similar fashion.

In thinking about this, I still don't understand the results you're getting.  Take the following circuit feeding the Arduino A/D input.  I would expect the results to be more consistent across the steps, and I'm truthfully confused as to why they wouldn't be.  The input impedance of the analog inputs on the Arduino are claimed to be in the many megohm range.

The arduino analogRead() function should return a value consistent across it's range relative to the input voltage.

Reads the value from the specified analog pin. Arduino boards contain a multichannel, 10-bit analog to digital converter. This means that it will map input voltages between 0 and the operating voltage(5V or 3.3V) into integer values between 0 and 1023. On an Arduino UNO, for example, this yields a resolution between readings of: 5 volts / 1024 units or, 0.0049 volts (4.9 mV) per unit.

What am I missing?


Images (1)
Last edited by gunrunnerjohn

You've got the circuit for the pot to Arduino connection just as I set it up. I took this from a YouTube video series but mine goes to a Nano instead of a Uno. Other than that it's identical.

So as I understand it, the pot acts as a voltage divider to feed the analog input between 0 to 5 volts. But it's a ratio kinda thing so it could produce the short range of values at the end points? Anyway, that's all there is to the circuit.


Images (1)

leo pot

Here's your data.  The black line is the "ideal" straight-line.  Yikes! 

I realize you said this works for what you have in mind but I'm thinking, "No joy in Mudville."


Images (1)
Last edited by stan2004

I'd be interested in seeing the voltage values at each stop that are going into the Arduino.  I can't imagine why it's all over the map like that.  Maybe the switch with the resistors wasn't such a bad idea.

Could it be that the mechanical nature of the pot is what's throwing the values out of kilter? As I mentioned before, I have seen the readings (from analogRead) change just by applying pressure against the stop positions. So with the initial readings, which is what you are seeing in the program's output, the mechanical movement has not yet completed and it remains out of a settled state?

In other words, perhaps this is similar to switch bounce. It might give a more accurate reading after a short period of time has elapsed once there is an initial change that warrants further sampling. I could do that.

Still, you would think that the spacing of values would be more uniform than going from 0 at the low end to just 14 in the second position. It's a bit puzzling.

93 * 11 = 1023

Last edited by Consolidated Leo

This could be a mechanical effect from slop or backlash of the detent and possibly the wiper of the pot.  Have you checked the repeatability of the readings across several tests?

For comparison you could do a test with a regular 10K pot.  It is not critical to match the exact positions of these readings, only need enough points to draw curve similar to the one above. 

The DFRobot switch uses fixed resistors and should have better repeatability.  However this circuit cheats by driving the LEDs from the voltage divider.  This will introduce non-linearity to the output curve.  Also each LED sees a different input voltage/resistance.



penn station posted:

For comparison you could do a test with a regular 10K pot.  It is not critical to match the exact positions of these readings, only need enough points to draw curve similar to the one above.

Cam: I could get readings from a 10k pot. That would give a good x value. But the positioning would be ballpark and not very good for a y value. That's if I am understanding what you are proposing.

I have some other ideas. Let me try a few changes. I'll at least give you guys some more to look at.

I'd still like to see a set of voltage readings with 5V on the post and just a voltmeter on the output.  A set from either direction would be useful.

One thing you might want to do is loop on the read until the value settles and not just take the first value.  I have to believe something is off here, there would be no point in putting detents on the pot if it was that flaky!  I'm having a real problem with the voltage varying by a 10:1 ratio between stops on a linear taper pot, that makes no sense to me.  If the A/D is getting true values, I would expect maybe a 10-20% variance in the step sizes, but not what you're seeing!

Leo, I was just proposing that as a test.  The positions are not critical and not critical to be the same position in the other direction.  The idea is the get the shape of the curve.  If this is much better than the detent pot it would point to problems with the latter.

I'd just like to see the voltages from a bare pot with 5VDC on it through the stops in each direction.  Something just doesn't ring true about the wacky readings you're getting.

GRJ: I'll see if I can get those readings together.

I'm currently trying to modify the test program to show the readings that show up after the initial value. The idea is settle time. But now it's not working. Something about my wiring into a breadboard.

Just a loose connection. Here's part of the output that extends the test program to show the next 4 readings following the one that detects a change in the position; based on the table of values. Each reading occurs every 100 ms.

Again, the test program is in the attachments.


Images (1)
Files (1)

Can you do a simple bench test of one pot with just a voltmeter connected?  Use this diagram and just connect the voltmeter on the center wiper and ground and do a reading for each detent going up and going down.  I'm very curious what you're actually getting for voltage steps.

gunrunnerjohn posted:

Can you do a simple bench test of one pot with just a voltmeter connected?  Use this diagram and just connect the voltmeter on the center wiper and ground and do a reading for each detent going up and going down.  I'm very curious what you're actually getting for voltage steps.

That's my next plan of attack. I don't have a bench power supply to work from but I think I can manage to get the readings from the Arduino setup that I'm using. The 5 volts comes from the USB port. Stay tuned...

If you have two decent voltmeters, monitor both the 5V supply and the wiper voltage.  This will allow us to see if the supply voltage varies.  With a decent power supply, that might not be necessary.

With one meter I would connect one probe to GND so it is hands free.  Use the other probe to take a reading from the top and middle of the pot for each step.  You can do this while it is still connected to the arduino.  Then disconnect the wire to the analog input and do another run.  This will show the results in-circuit and the pot by itself.

I disconnected the wiper from the analog input pin and took the readings between that and ground. The voltage on the rails is 4.61 that's from the USB connection. Here are the values I got; I've only got one meter:

0 - 0.00
1 - 0.06
2 - 0.54
3 - 1.11
4 - 1.71
5 - 2.35
6 - 2.96
7 - 3.56
8 - 4.11
9 - 4.55
10 - 4.61

10 - 4.61
9 - 4.55
8 - 4.10
7 - 3.54
6 - 2.94
5 - 2.33
4 - 1.70
3 - 1.10
2 - 0.52
1 - 0.06
0 - 0.00

Pretty much the same in both directions.

I need to get some alligator clip probes! I'm beginning to grow a third arm!

In the middle of the pot, they look fine, but at the ends, it's kinda' ugly.  Obviously, not an ideal solution, I think I'd go with the rotary switch.   At least now I understand why the A/D was giving you such odd values, it was just doing what it was told!

leo detent pot voltage

What he said.  Looks great in the middle but the two stops on each end have such a small zone.  Sure, you can adjust the thresholds to "center" the thresholds to the compressed ends, but to each his own.  I like GRJ's idea of cutting your losses (in my opinion) and using a 1P10T rotary switch with 1-cent equal-value resistors in a ratiometric-potentiometer configuration as was suggested early on. 

Of course to beat the dead-horse, I still favor the idea of using a rotary-encoder switch with 3-resistors albeit being an incremental vs. absolute encoder as discussed earlier. 


Images (1)

I have tweaked the threshold table to be more in line with the "mid-points" between the values that I'm getting in the resting state. Even with my rough guessing it's been fairly reliable in detecting the change of position. The top and bottom get a range of 6 values. The rest was a calculation.

int table [] = {
  6, 64, 180, 311, 448, 586, 721, 850, 962, 1017

Thanks, once again guys. An interesting discussion.

  -- Leo

One other thought on this. The big "reveal" for me was that you can use the A/D converters in this way at all. Like the rotary switch that Cam presented and the keypad from Adafruit, this is a great way to externally control a program without taking up much real estate. I'm planning to make use of this technique as best I can.

That's a fairly common usage for an A/D, lots of inexpensive products use a resistor ladder to provide a one-line input to the chip.

Consolidated Leo posted:

Stan: Understood. I'm all in for a discussion of alternatives.

For my application, where I want a small integral value between 1 and 10, it would be better to have a more certain form of feedback on what number that is exactly. The rotary position switch with numbers on it would be better, I think. A 7 segment display would be okay but then you have to drive it and that almost requires an MPU just to do the work.

Just a quick update on this idea. I have come across a decade counter and seven segment driver on a single chip that might be useful for the feedback that I'm looking for. It's the CD4026BE from Texas Instruments.

It is an up counter only but will display 0 to 9 and then roll over (back to zero). Using a single pin from the Arduino, the correct number of clock pulses should display the position of the detent pot as it changes. Even though there are 11 selections, a 0 at the full CW position and a 0 at the full CCW position are noticeably different enough to do the job.

I've ordered the parts that I need from Mouser and will test this out when I can. I've got the Arduino code together and have started a DipTrace project to go with it. A one digit display.

Last edited by Consolidated Leo

If I understand your idea, when turning knob 1 click CW you increment the 7-segment display by sending 1 pulse to the CD4026.  When going 1 click CCW you decrement the display by sending 9 pulses.  My comments:

The CD4026 has limited output current drive capability on the 7 segment pins..maybe only 1 mA or so when operating at 5V.  This may actually be enough if you have an efficient display but maybe not in which case you'd need, say, 7 transistors or buffer gates to boost the current drive to, say, 5 or 10 mA per segment for a generic 7-segment display. YMMV.

You need to set the starting count of the CD4026 upon startup.  This can be as simple as a power-on reset pulse from an Res-Cap, or an unused Arduino output pin.  

The display will momentarily flicker when decrementing as the 9 clock pulses advance the count through all the digits rolling over the decade.  Of course the flicker will be faster than the eye can see and over in less than a millisec.

I assume you settled on this approach because it only requires 1 output pin...sort of mirroring the use of only 1 input pin to detect the rotary switch position.

So far so good; it will work.  However, as you're all in for discussing alternative:

Suppose you use an 8-bit serial-in, parallel-out shift register like the 74AC164.  You could use 7 of the 8 outputs to directly drive the 7-segment display since the 74ACxxx digital chip family can drive 5-10x more current at 5V than a CD4xxx chip.  In this case, rather than sending some number of clock pulses to change the display, you send the actual 7-segment pattern serially.  Usually one thinks of serial output data as having a clock pin and a data pin thereby requiring 2 Arduino pins.  But using a Res-Cap "filter" you only need 1 output pin.  That is, to change the pattern of the display, you send a burst of 8 pulses Morse code style (long and short).  You always send 8 pulses to change the display with each pulse corresponding to the on or off state of 1 segment of the display.  The filter decodes the long and short pulses to become the data pin to the shift register.  As with your method, there is a flicker when the shift register is updated but this is so short that the eye will never perceive it.  You will need to store the 7-segment patterns to send out but that's just a table of 11 bytes in your case of 11 states.  But note that rather than just 0...9, you have complete control over each segment so you can generate 0..9,A,b,C,d,E,F or the full hexadecimal range on a 7-segment display.  The 8th output bit can even drive the decimal point which might have some use to indicate status or whatever. So if only needing 11 states, you can choose to send the range 1..9,A,b corresponding to 1..11.  You can completely blank the display whereas the CD4026 is always displaying something (unless you wire up another display disable input which of course requires another Arduino output).

If the 1-wire shift register method is new to anyone following along, there have been zillions of articles and application notes written on it.  I found this one that is pretty comprehensive.




Stan: Thanks for the feedback and the article on the shift register ideas. That's a good web site. I'll have to spend some time checking that out.

You've got the correct notion of what I'm trying to accomplish. I've seen videos of the CD4026 in action here. And I purchased some low current 7 segment displays shown here. I hope that they will work together to give me what I need.

You have also correctly pointed out some of the question marks in this scheme. What if it goes out of sync at any time from the clock pulses? How do you ensure that we start at zero? These are things that I want to tackle one at a time. I may need to use more than one pin after all; and that might be okay.

The shift register method does seem to have some advantages. I'll have to give that some thought.

You might have guessed that this all stems from a desire to construct a controller box for the Arduino at some distance; say about 10 feet. So the fewer wires in the cable the better. I'm beginning to think that an mpu in the box itself may be an alternative.

Here's a mock-up of the type of control box that I have in mind.

I have a plan to use it to control a modern version of a station stop. It's not a well developed plan but what is in it's initial stages. Nevertheless, it gives me something to work on.


Images (1)

You could use the single output pin method driving 3 cascaded CD4026.  That is, you have a 3-digit decade counter that counts 000...999 by using the carry-out pin to drive the clock of the next counter.  Can get a bit messy since changing just the left-most digit involves sending 100 (to increment) or 900 (to decrement) clock pulses!  Changing just the right-most digit (without affecting the other digits) can get interesting too!  But it does meet the single-output pin criteria.  Obviously you could set up the 3 displays as 3 independent CD4026s but that would require 3 output pins.

So in this example the shift-register method might make more sense.  That is you cascade 3 74AC164 serial-in, parallel-out registers to create a 24-bit output.  You always need to send exactly 24 Morse-code pulses to change any display.  But it does meet the single-output pin criteria.

To your point, if the box is 10 feet away, having a separate Arduino becomes attractive.  As I recall there was angst in reliably decoding the analog voltage from the potentiometer using an A/D input of the Arduino.  Having that analog voltage run 10 feet down a cable would not help matters!

Stan: I was thinking of the 4026 for each digit using up 3 Arduino outputs. The plan would be to design a 2 digit circuit board and then NOT populate the second digit where only one is needed. But the shift register route sounds better all the time.

I was not planning to cascade the 2 digit circuit to wrap around at 100 but that could be done also. The Arduino would convert the standard pot through an A/D pin and then scale it as a percentage of the full range; 0 to 99. That would become the number of seconds that a train would remain at the station once it is stopped.

I'm going to have to read up on the shift register approach.  And I need to consider if there would be an  advantage to doing a single circuit board for the entire control box.

Also, I did have the detent pot on a 6 foot cable for those tests that I ran previously. That's key to this operation. I don't want to have to work with line drivers unless it is absolutely necessary.

Having done some homework, there is no doubt about it, the shift register method is the way to go for reducing the number of output pins on a microprocessor. And the fact that the number of shift registers strung together is linear, it has definite advantages in operation as well.

I have trouble with arriving at the data based on long and short duration pulses superimposed on the clock input through an RC filter. My research says that it works but I don't know how I could output the difference in pulse width from the Arduino that the published information says is in the range of microseconds. That's hard to figure without an oscilloscope. But given the alternatives, using 2 pins (for clock and data) seems quite reasonable.

So a bit of experimentation will determine how I end up driving the seven segment LED displays. The good news is that 2 pins can do all of the displays. But I may decide on 3 pins just to keep the display sets independent.

Then there are the toggle switches and push button(s) which may require a parallel in serial out shift register or a resistor ladder to an analog input pin. I'll figure it out.

After some experimentation, this is what I've learned.

First, the CD4026BE does a good job at driving the seven segment displays that I have. I used a low value resistor (22 ohms) on the common cathode of the display and that produces a nice bright output. I attached the detent pot (over a 6 foot cable) to an Arduino Mega 2560 and the input from that is sent via clock pulses to the display. Checking the pot every 100ms gives a good response on the display as the pot is rotated from one position to another.

However, with only the clock to the 4026 connected to the Arduino, if the display got out of sync, there was no way to program it back to a known state. It would roll up and down in response to the potentiometer movements but the value was wrong. So I added a second connection to the RESET input of the 4026 and changed the display code to use it quite a bit (to generate fewer clock pulses to affect a change). And that worked perfectly. But now it used 2 connections for the one digit display.

How did it get out of sync? Just by modifying the program and downloading the Arduino code would start it up with the wrong digit. I found that if I rotated the pot so that the display showed zero and then hit the reset button on the Arduino, it would go back to the correct value. But that's not an acceptable way to operate.

I did not try the power on reset technique that Stan mentioned earlier. That may have helped with this situation. Instead, I decided to move on to the shift register approach which makes more sense in this case where there are really 3 digits involved.

So I got some CD74AC164E chips and set up 3 of them on a separate breadboard each feeding the display digits. Wow! Two connections to the CLOCK and DATA inputs of the shift register and a new class for the Arduino code base was all it took to convince me that this was how this should be done. I added hexadecimal digits to the seven segment display table of values to push to the shift registers and controls for decimal points and blank displays. Everything works great! And the whole thing is tied to the Arduino over an 8 foot cable.

There is no noticeable intermittent flashing of the displays at all no matter what I try to make it do. I've had the one digit display flashing on and off at a 200ms interval while the two digit display counts down in hexadecimal every second  without any problems. Nice!

Using just 2 Arduino pins for 3 digits with some distance is what I was after. The shift register approach is flawless. So the control box is now Power and Ground plus 2 pins for the displays then 2 analog inputs for the pots. That's 6 wires so far. Now the switches and button. It's odd that I found some cable in the basement that has 7 conductors. Keep your fingers crossed!


Images (1)

Yet another update. I've been working on the switches for the control box using voltage division to feed a single analog input to the Arduino. With the resistor values that I used, I got a pretty good range from the 10 bit ADC shown below:

That takes care of the electronics design part of this project. I will be doing some DipTrace for the displays and ordering electronic enclosures for the construction of this thing. That's all for now.


Images (1)

Here's a display that attaches to the Arduino with shift registers and uses just 2 output pins. There's the normal power and ground along with a data and clock output.

I used DipTrace to design the PCB and sent the files to JLCPCB for production. It took about 3 weeks to arrive here in Western Pennsylvania. Total cost with shipping was eight dollars for 5 pcbs.

The plan is to mount the display inside an ABS plastic project box along with potentiometers, a push button and 2 toggle switches. Making the cuts in the box may be a challenge. I have brass mounting hardware available for the display.

The display is built sunny-side up with the shift registers all on the bottom.

I wrote an Arduino class called ShiftDisplay that allows me to write just about anything to the two display areas. The test program and class code is included in the attachments. Everything is working according to plan. When I get the box together, I'll have another update.


Add Reply

OGR Publishing, Inc., 1310 Eastside Centre Ct, Suite 6, Mountain Home, AR 72653

Link copied to your clipboard.