# Arduino: read different voltage values in a range from -12 to +12V

I would like to trigger different functions in Arduino related to the following voltage values: -12V, 0V, 6V, 9V, 12V (the range is from -12V to +12V).

According to the value of the voltage read (-12V, 0V, 6V, 9V, 12V) I have to show instantly different light animations on a LED strip.

Considering that the Arduino is not able to read a such voltages directly, I suppose that probably I have to use a voltage divider, but I don't know how to calculate the resistors to use. Can anyone help me?

Thank you.

I was suggested also to use 1 dual op amp do the following:

1. Create inverting amplifier with a gain of 1, but insert a offset of 12V to the + (non inverting pin), this will max your -12 to 12V range change to a -24-0V range.

2. To the output of stage 1, connect another inverting amplifier with gain of 0.2 you would get a a positive voltage range of 0-4.8V which is fine to work with the arduino's 0-5V ADC tolerance.

• You need more than a voltage divider, as Arduino will not deal with voltages below zero. You will need to use an active amplifier of some sort. Oct 19 '18 at 12:40
• I don't get this. You should add more details. Do you want interrupts when the level changes, or when someone connects 6.0 volts but not 5.9 or 6.1, or what do you mean?
– pipe
Oct 19 '18 at 13:34
• The AVR hardware does not offer multiple analog-level determined interrupts (it's hard to think of any MCU that does). You'd probably need to do an ADC conversion on a regular schedule and have software in that ISR consider if the converted voltage is "interesting". And this would need to be downstream of an op-amp providing offset and scaling to the AVR ADC's range. Otherwise you'd need external comparators for each threshold of interest feeding an interrupt line. Oct 19 '18 at 15:18
• @ScottSeidman - the AVR (at least the common ATmega328p) has a single comparator interrupt. I did in fact mention the possibility of using multiple comparators, but they'd likely have to be external. Now that we know more about the application this does not really look advantageous compared to adapting the signal to the ADC and reading it periodically. Oct 19 '18 at 15:36
• @Filippo - it was not previusly clear that these are pulses. Given that they are, you must provide some constraints on their timing and interval. Also realize that "instantly" in terms of a visual display and "instantly" in terms of a computer are two extremely different things. Oct 19 '18 at 18:41

Figure 1. The voltage levels to be detected.

Since you never have to detect 0 V you can treat any voltage below 6 V as -12 V.

simulate this circuit – Schematic created using CircuitLab

Figure 2. Level converter circuit. D1 protects the ADC against negative voltage inputs. The R1 / R2 divider gives an output of 5/12 times the input voltage.

On your logic you could set thresholds of 10.5 V, 7.5 V and 3 V for each of the analog 'windows'. For a 10-bit ADC these would correspond to $$\ 1024 \frac {10.5 \times 5}{12} \$$ for the 10.5 V threshold, etc.

If you have the comparator then you could use this to detect each positive going edge - set the threshold to 3 V (1024 * 3 / 12) - and after a short delay sample the voltage.

Note that I chose 7k and 5k to make the voltage divider ratio blatantly obvious. Choose some standard values close enough to do the same job.

Since we have zero information about the timing of the pulse train, let's assume that it's always a 50% duty cycle 1kHz square. Since we also have no information on how the pulses should or shouldn't affect your sensor circuit, let's assume that they shouldn't, because vaguely that's how your question reads.

The most reliable way to detect these levels would be two Schmitt triggers - one to detect the difference between 9V and 12V, and one to detect the difference between 6V and 9V. Each would be preceded by a diode, RC lowpass and divider to get the proper threshold voltages. Here I don't show the schmitts or the dividers, only the lowpass:

The passive values will need to change based on the actual timing of your input. Use a Schottky for the diode to minimize forward drop.

• The question suggests that -12 V and 0 V are also values to be detected. The graph doesn't show any occurrence of 0 V so I ignored that in my answer but did cover the -12 V. Oct 19 '18 at 20:30
• @Transistor It's pretty ambiguous. My interpretation is that the "-12V" just means that voltage-low is always -12V, and it's the voltage-high he needs to detect. Oct 19 '18 at 20:33

it depends what you are using these voltages for, if you are using them with serial transmission you can use a max232 converter, if you are using them in general for inputs and outputs, bearing in mind and arduino can usually handle a voltage of up to 12v using its internal regulator, you could in therory use voltage dividers for inputs, the equation for using a voltage divider is Vout = Vs x R2 / (R1 + R2), this means that you have your supplied voltage (e.g 12v) and for the arduino pins to interpret this you need the voltage to be between 0v - 5v. To rearange the voltage divider, here is a useful website : http://www.ohmslawcalculator.com/voltage-divider-calculator

• According to the value of the voltage read (-12V, 0V, 6V, 9V, 12V) I have to show instantly different light animations on a strip led. Oct 19 '18 at 15:25
• Many thanks for your reply. I had a look at your link containing the formula but I don't understand how to use it. In the input boxes I'm asked the values of the resistors but it's actually the values of the resistors I'm looking for and the Vout is variable according to the Vin (-12V, 0V, 6V, 9V, 12V). For me it's absolutely fine to reduce the scale of the Vin (-12V, 0V, 6V, 9V, 12V) in something more appropriate for the Arduino while these values are read by a single pin and mapped in order to trigger a light scene on the LED strip. Do you have any link to suggest me with an example? Oct 19 '18 at 15:55

So you have a range -12V to 12V that you want to map into 0V to V (supply). You need three resistors:

R1 goes from the ADC to ground, and has a value R which you can choose.

R2 goes from the ADC to V, and has a value of R*(12-V)/12.

R3 goes from the ADC to the 24V signal, and has a value of R*(12-V)/V.

You can increase R3 slightly to limit the range to less that 0 to V.