3 way switch on one pin?

I am doing a control pult with Arduino Mega. I need to place as many switches on it as I can. All analog pins are occupied by potentiometers, so it has to be digital pin. Handling normal switches, push buttons and similar items is not a problem, but is there a way to latch a 3 position switch to just a single arduino pin?

I know I can use multiplexors, but the electronic bay is small.. I thought if it might be feasible to use one pin to generate a 50% PWM signal, so one "on" position would provide +5V, and another "on" the pwm signal at 50%. But if you have another idea how to do it, I am open for this!

Did anyone try this yet?

You might use an external mutivibrator (555 timer?) to put a pulse string on one “ON” switch terminal and stable 5V on the other then test for 0V, 5V or pulses.

A capacitor and resistor.

Here's a quick circuit:

Here's the code for that circuit:

byte specialDigitalRead(pin) {
  //return 0, 1 or 2 depending on the state of the switch
  //0 is grounded LOW
  //1 is open or +5V
  //2 is the RC circuit: use 100pF in parallel with 500K
  //3 is "not sure"

  //first apply INPUT_PULLP to charge the capacitor
  //Don't use output mode as we could be trying to drive 5V into a grounded pin
  pinMode(pin, INPUT_PULLUP);
  bool pullupActive = digitalRead(pin);
  delayMicroseconds(10); //Need about 5-10 us to charge the capacitor
  bool pullupDelay = digitalRead(pin);
  pinMode(pin, INPUT); //switch off the drive
  bool inputActive = digitalRead(pin);
  delayMicroseconds(30); //need about 20-30us to discharge through 500k
  bool inputDelay = digitalRead(pin);

  //OK, so now we have 4 readings, how do we turn that into 3 output states?
  //If all the results were LOW then it's definitely grounded
  if(pullupActive == LOW && pullupDelay == LOW && inputActive == LOW && inputDelay == LOW) {
    return 0;
  //If the first 3 were HIGH then it's the open or 5V selection.
  //don't use the 4th result as leaving the pin floating for a few microseconds may give any random result
  if(pullupActive == HIGH && pullupDelay == HIGH && inputActive == HIGH) {
    return 1;
  //LOW - HIGH - HIGH - LOW is definitely the capacitor
  if(pullupActive == LOW && pullupDelay == HIGH && inputActive == HIGH && inputDelay == LOW) {
    return 2;
  //There may be other results, for example if the capacitance on the 'floating' option is high
  //or we used an incorrect delay for the capacitor and resistor chosen.
  //The code calling this should check for 3 and report an error.
  return 3;

The idea behind this circuit is to never use pinMode(..., OUTPUT) because it's always easier to just wire the switch directly to GND. There's many different equivalent circuits - the resistor or capacitor could be on the left side of the switch or you may use 5V as your reference instead of GND.

The size of the capacitor, resistor and the delayMicroseconds() is related. Any of them can be changed, for example if you only had a 100nF capacitor which is 1000x bigger. Then the delays would get kind of long.

If you were pretty sure that your other code isn't going to call this more often than every 30 microseconds then you could omit that last delay and significantly improve the speed of this function.

For another example of a similar circuit, look at SpakrFun's "digital" QRE1113 breakout

With many capacitors or resistors you could have many pins.

Personally though, with a project complex enough to use up all the pins on a Mega, there must be some subsystem (such as the front panel buttons) which could be usefully served by a shift register or multiplexer.

I think the resistor R1 in the circuit should be 100k rather than 1k. The way it's drawn you have an RC of 100 ns, too fast discharge to detect a lingering high. 100k would give an RC of 10 us which would work fine. Comments also mention 100k.

Oops, yes. I wrote the code after doing the drawing and changed the resistor value without updating the drawing. I've changed my previous post.

100pF * 500kOhm = 50 us so you won't have a proper discharge to guarantee a low in just 30 us. You need more like 150 us for that.

Thanks! Will try this! The free pin of S1 should be going to +5, right?

The project is actually a "non-critical" function extension for RC models. HC-12 433mhz communication, 2,7" display for telemetry, and as many switches, buttons, joysticks and potentiometers as possible. If I would need more inputs, I will just add multiplexers or additional nanos over I2C or so.

I would be etching or milling my own boards for each switch/potentiometer/button group, connected by a flat cable to Arduino.

The code I wrote should work without a connection to 5V. It won't be damaged if you do.

You may need to experiment with the resistors and capacitors you have available along with the delays to get it working right.


Will try it on a breadboard. I will however have to use a faster RC combo and shorter delays I fear, I want to send updates every 100ms, and will need to read 10 such switches in addition to 16 Potentiometers (XBOX joysticks ;)) and normal switches/push buttons, serialize json, and send it over the HC-12 serial.

10 of those? Then get a multiplexer chip or even a small Arduino as an I2C slave. This is kind of a last-ditch attempt to get one more pin. As you worked out, it wastes a lot of time in delays.

Indeed. A few port expanders will be much less work to set up, and run a lot faster.

Shift registers will do great, otherwise I2C based port expanders such as the PCF8574/PCF8575/MCP23008/MCP23017 work well, too.

Makes alot of sense. I just ordered a pair of MCP23017 boards for that.

I am doing a control pult with Arduino Mega.

What is a "control pult"?

I need to place as many switches on it as I can. All analog pins are occupied by potentiometers, so it has to be digital pin. Handling normal switches, push buttons and similar items is not a problem, but is there a way to latch a 3 position switch to just a single Arduino pin?

With 16 Arduino pins, you can easily read a matrix of 64 switch points, buttons etc. You need a diode for each to allow for multiple simultaneous presses. Much simpler than this capacitor timing stuff ...

Control Pult - A box with lots of switches and similar items attached to the RC control transmitter. Transmitters usually have too few channels to control all features of my RC ship (I have all cranes operating, lots of sounds, different gimmicks, individual lighting, as in real ship). RC transmitter is secure and fast to operate, but such functions like lighting and crane operation are not time critical, so I make my own "low speed" RC control in 433 Mhz range.

Receiver would be orange pi based (mainly due to need to operate complex polyphony), with a few Arduino nano strapped per I2C.

pult, pulpit.
Once worked on a German machine where the operators control stand was called a "pult" in the documentation, the German techs called it "the pulpit" in English.

Yeah, probably the same, operator control stand is Pult in both russian (my native language) and german (live here for 20 years)