Telling them apart
Seven levels on one pin: six buttons and nothing. A sketch reads BTNS and asks which level it is nearest, by drawing a line halfway between each pair of neighbours. The closest pair, U8 and U6, are 0.11 V apart, which is about 22 counts on an Uno and 34 on a Pico: plenty, if the lines sit halfway and 3V3 is on 3V3.
Seven levels, six lines
BTNS can sit at seven levels: all of 3V3, a half, a third, a quarter, a fifth, a sixth, and 0. A sketch reads it and has to say which. The simple way is to draw a line halfway between each pair of neighbours; a reading above a line and below the one over it is that button.
In millivolts, with 3V3 on the header, the six lines are:
| Above | and below | is |
|---|---|---|
| 2475 mV | U11 | |
| 1375 mV | 2475 mV | U10 |
| 963 mV | 1375 mV | U5 |
| 743 mV | 963 mV | U7 |
| 605 mV | 743 mV | U8 |
| 275 mV | 605 mV | U6 |
| 275 mV | nothing |
The sketches carry exactly this list, highest first, and stop at the first line the reading is above:
const int LIMIT_MV[] = {2475, 1375, 963, 743, 605, 275};Millivolts, so one list fits every board
An Uno counts against 5 V, a Pico against 3.3 V, and an ESP32 against a
reference of its own. A count means something different on each, so the
sketches convert to millivolts first. On an ESP32 and an ESP32-S3,
analogReadMilliVolts does it with calibration stored in the chip; on an
Uno and a Pico the count is scaled by the ADC's full scale, 5000 mV or
3300 mV. Then one list of lines works everywhere.
The ESP32's ADC reads nothing below about 0.1 V and tops out near 3.1 V at the Arduino core's default setting. Neither end matters here: the lowest button, U6, is at 0.55 V, and U11's full 3.3 V reads as the top of the scale, far above its line at 2475 mV.
How much room there is
The tightest pair is U8 and U6, a fifth and a sixth of 3.3 V: 0.66 V and 0.55 V, 0.11 V apart. Their line is halfway, so a reading can wander about 55 mV either way before it is misread. In counts that is roughly:
| Board | U8 | U6 | apart |
|---|---|---|---|
| Arduino Uno | 135 | 113 | 22 |
| Raspberry Pi Pico | 205 | 171 | 34 |
Ordinary noise on a breadboard is a few counts, so both are comfortable. What eats the margin is a wrong supply: 5V on the header's 3V3 pin raises every level by half and puts most of them over the wrong line.
When it does not work
They are the closest pair, a fifth and a sixth of 3V3. Check that the header's 3V3 pin is on 3V3, that the sketch's lines are the ones in this article, and on an Uno that FULL_SCALE_MV matches your 5V pin; a USB supply a little under 5 V shifts every millivolt reading up a few per cent.
The header's 3V3 pin is on 5V. Every level is half as high again, and lines drawn for 3.3 V name most buttons as one nearer BTNS: U5 as U10, U6 as U7. Move it to 3V3. Only U11, which reads the top either way, still comes out right.
The contacts bounce as they close, and a reading taken in the middle of that can land anywhere. Believe a button only when two readings in a row agree, or read once per frame of your program, which is slower than the bounce.
Edit this page — content/books/slim-joystick/telling-them-apart.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Slim Joystick
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.