## How to read a quad dip switch with only one analog pin with Arduino

The DIP switch is a set of small switches in a Dual In-line Package. It finds numerous applications, such as address configurator, select a type of operation, enter a remote control code.

Normally the dip switches require as many digital input pins as there are dip switches used and also with pull-up resistors enabled. In the proposed circuit I use only one analog input for four dip switches.

After developing a project to read a 4x3 keypad with three analog inputs [1], I was thinking of applying this methodology to dip switches too but things are not at all similar. The buttons close only one at a time and are monostable while the dip are bistable and also can close all together.
After several attempts, simulated at computer, I arrived at the synthesis of the circuit shown in figure 1.
 Figure 1
In theory, the values of the R1-R4 resistors should be 1, 2, 4, 8 kΩ, but even with the standard values I used, good results are obtained. If we measure the resistance between Vo and Gnd, we have a value that is proportional to the binary number set, but the Vo voltage will be equal to:
Vo = Vcc*R14/(R5+R14)
Where with R14 I indicated the sum of the resistors R1 to R4 not short-circuited by the dip switches. As can be seen, now the law is not linear, but it suffices to put R5 large enough to minimize the current variation. This will reduce the output voltage, but by setting the Arduino reference voltage as "INTERNAL" we get a full-scale Arduino UNO ADC converter equal to about 1.1V.
Indicating with "ON" the closed switches and with "OFF" the open ones and setting Vcc = 5V the following table is obtained.
 D4 D3 D2 D1 N R14 I [mA] Vo [mV] DV [mV] NADC DN NADC_L NADC_H ON ON ON ON 0 0 0.073 0.00 0 0 0 0 30 ON ON ON OFF 1 1000 0.072 72.36 72.36 67 67 47 87 ON ON OFF ON 2 2000 0.071 142.65 70.29 133 66 113 153 ON ON OFF OFF 3 3000 0.070 210.97 68.32 196 63 176 216 ON OFF ON ON 4 3920 0.069 272.15 61.18 253 57 233 273 ON OFF ON OFF 5 4920 0.068 336.89 64.75 313 60 293 333 ON OFF OFF ON 6 5920 0.068 399.89 63.00 372 59 352 392 ON OFF OFF OFF 7 6920 0.067 461.21 61.32 429 57 409 449 OFF ON ON ON 8 8200 0.066 537.35 76.14 500 71 480 520 OFF ON ON OFF 9 9200 0.065 595.08 57.73 553 53 533 573 OFF ON OFF ON 10 10200 0.064 651.34 56.26 606 53 586 626 OFF ON OFF OFF 11 11200 0.063 706.18 54.84 657 51 637 677 OFF OFF ON ON 12 12120 0.062 755.42 49.24 703 46 683 723 OFF OFF ON OFF 13 13120 0.062 807.68 52.26 751 48 731 771 OFF OFF OFF ON 14 14120 0.061 858.67 50.99 799 48 779 819 OFF OFF OFF OFF 15 15120 0.060 908.44 49.76 845 46 825 865
Where NADC is the output number of the 10-bit ADC converter. With four dip we represent 2^4 = 16 different states that must be identified precisely. The program must discriminate each state with two thresholds NADC_L (lower) and NADC_H (upper). The number of 10 bits, at the converter output, must be between these two limits which I determined with ± 20 units with respect to the NADC value. The diagram in figure 2 clearly shows the intervals and the output voltage Vo as a function of the number set on the four dip.
 Figure 2
As can be seen, the trend is fairly linear and the intervals DN range from a minimum of 46 to a maximum of 71, so the thresholds of ± 20 do not overlap.
As shown in the table, by powering the circuit with Vcc = 5V, the maximum output voltage is 908.44 mV, lower than the maximum voltage (1100 mV) accepted by the converter.
If you need an 8-pin dip switch, just duplicate the circuit and use a second analog input. Figure 3 shows a connection diagram of the individual components.
 Figure 3

The circuit is realized with few soldered joints and it is also easy to draw the printed circuit. Figure 4 shows the appearance of my prototype seen from the component side and from the soldered side. I used a small perforated circuit board of about 40x30 mm.
I have optimized the circuit for Arduino / Genuino Uno and the program is fine for MCU type ATmega328 / 168. But it can also be used, with minor modifications, with other MCUs, such as SAMD21G18 mounted on Arduino Zero and Arduino MKR1000 boards and also ESP8266 and 32.
 Figure 4
I used a 3-pin strip connector for wiring with Arduino. The resistors must have a low tolerance, I used those with 1/4W metal film with a tolerance of ± 1%, very common and easy to find. Figure 5 shows the wiring between the DIP card and Arduino Uno.
 Figure 5

List of components
 component description component description R1 1 kW ± 1% metal film R5 68.1 kW ± 1% metal film R2 2 kW ± 1% s metal film - 0.1” perforated circuit board R3 3.92 kW ± 1% metal film - 3 pin strip connector R4 8.2 kW ± 1% metal film Dip4 DIP switch with 4 positions

The program
The sketch is an example of use of the circuit and provides both the number and the individual dip arranged in the DipSw char array. In this example I use Arduino Uno's pin A0 as an analogue input and in the setup I insert the analogReference (INTERNAL) instruction to set the internal Vref at 1.1V, more stable and less noisy than the default at 5V.
In the loop () function I set the discrimination to thresholds and in the readDIP function (byte mybyte) I create the array of characters ordered as the dip switches. This last function is useful to use every single switch.

/* program DIP4to1.ino
*  Giovanni Carrera - 20/08/2019
*/
// limits of DIP4 output values:
char DipSw[5];

void setup(){
analogReference(INTERNAL); // internal ADC reference input = 1100V
Serial.begin(115200); // used with serial monitor
}

void loop() {
for (int i=0; i < 16; i++){
if (val >= NADC_L[i] && val <= NADC_H[i]){// has found the right value
Serial.print(val);
Serial.print(" , N = ");
Serial.print(i);
Serial.print(" , Dip = ");
Serial.println(DipSw);
break;
}
}
delay(500);
}

for(int i=3; i >= 0; --i){
DipSw[i]= '1';
else
DipSw[i]= '0';
}
}

References
1.      “Very few wires for a numeric keypad for Arduino”, Giovanni Carrera, 10/11/18, http://ardupiclab.blogspot.it
2.       “Only Three Pins for a 4x3 Keypad”, Giovanni Carrera,  November 19, 2018, https://www.hackster.io