recent
Hot News

Measure the voltage on the VIN pin of an Arduino board

Home

 


In this tutorial, we will see how to measure the supply voltage VIN of an Arduino / Genuino board. By the end of this article, you will be able to determine a low battery level or a power failure before it becomes a problem.


Hello everyone !

In my previous article, we saw how to measure the supply voltage of the microcontroller of an Arduino / Genuino board. We will now see how to measure the voltage on the VIN pin of an Arduino / Genuino board.

We saw in my previous article that knowing the supply voltage of the microcontroller allows you to make precise analog measurements, but does not allow you to know if the power supply to the card is reliable. We are therefore going to use this knowledge today to design a system making it possible to measure the supply voltage of the card at the level of the VIN pin, or of the power supply jack for cards having one.

The theory

Diagram of the divider bridge

The circuit for measuring the voltage on the VIN pin is very simple. It is a simple voltage divider bridge.

In the divider bridge above, I use resistors of different values ​​to form a divide by 4 bridge (i.e. Voutput = 0.25 * Vinput): R1 = 3300 ohms (3.3K ohms) and R2 = 1100 ohms (1.1K ohms ).

If we have fun doing the calculation of the dividing bridge with Vin = 20v (i.e. 18v maximum admissible, with 10% margin "in case"), we obtain: Vs = 20 * (1100 / (3300 + 1100)) = 20 * (1100/4400) = 20 * 0.25 = 5.0 volts.

A classic Arduino board is supplied with a voltage ideally 9 volts, or 12 volts at most. With a divider by 4 bridge and a classic Arduino board (operating at 5 volts), we can measure VIN voltages of 20 volts maximum (in theory, in practice we will not exceed 18 volts to keep a safety margin). Thanks to a very simple circuit, it is possible to measure the supply voltage of the board coming from a mains supply, a battery or even a solar panel.

Watch out for car batteries
I have heard many times from readers who do not understand why their edits are heated to the point of scorching. Each time, the assembly was powered by a 12-volt car battery, directly or via a cigarette lighter socket.

Be careful ! Car batteries generate voltages well above 12 volts. It is not uncommon for a car battery to reach voltages of 15 volts, or sometimes more, depending on the car model and battery.
At 25 € the Arduino board, it's a bit expensive for the paperweight or the bbq lighter, be careful

A typical Arduino board can be safely powered with a 9 volt power supply on the VIN pin. The practical maximum is 12 volts and the minimum is 7 volts. Above 12 volts, the card will heat up sharply, then deteriorate. Below 7 volts, the card will not work properly.

 

The above circuit draws about 2mA with a 9 volt supply, 3mA with a 12 volt supply. If you need a low consumption circuit, you can multiply the resistance values by two to reduce the electrical consumption accordingly. The sum of the two resistors must remain around 10K ohms so as not to have a problem with the analog to digital conversion.

The assembly

Necessary material

To carry out this assembly, we will need:
  • An Arduino UNO board (and its USB cable),
  • A 3.3K ohm resistor - color code orange / orange / red,
  • A resistor of 1.1K ohms - color code brown / brown / red,
  • A test plate and wires to wire our assembly.
Prototyping view of the assembly

Schematic view of the assembly

To wire the assembly, simply connect the 3.3K ohm resistor between the VIN pin of the Arduino board and the A0 pin of the same board.

The finished assembly

Then, we finish the circuit by connecting the resistance of 1.1K ohms between the A0 pin of the Arduino board and the ground (GND pin).

The code

The code is nothing more than an analog read with analogRead () and a bit of math (a simple cross product) to do the conversion to volts.

The code uses the function shown in my previous article to measure the internal reference of the Arduino board. It is this reference voltage that is used for the cross product for more precision.

PS For optimum precision, it is possible to modify the coefficient of the divider bridge in the code. Thus, if you have an ohmmeter, you will be able to measure the real resistance of the divider bridge and determine its effective coefficient.

The code with comments:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
 * Arduino code allowing to measure the supply voltage of the board in VIN.
 */

/* The analog pin number for voltage measurement in VIN */ 
const byte BROCHE_CAPTEUR_VIN = A0;

/* Resistance bridge divider coefficient */
const float COEFF_PONT_DIVISEUR_VIN = 4.0;


/* Function setup() */
void setup() {
 
  /* Initializing the serial port */
  Serial.begin(115200); 
  Serial.println(F("VIN-O-Meter"));
}

/** Measures internal reference at 1.1 volts */
unsigned int analogReadReference(void) {
  
  /* Eliminates all residual charges */
#if defined(__AVR_ATmega328P__)
  ADMUX = 0x4F;
#elif defined(__AVR_ATmega2560__)
  ADCSRB &= ~(1 << MUX5);
  ADMUX = 0x5F;
#elif defined(__AVR_ATmega32U4__)
  ADCSRB &= ~(1 << MUX5);
  ADMUX = 0x5F;
#endif
  delayMicroseconds(5);
  
  /* Selects the internal reference at 1.1 volts as measurement point, with VDC as high limit */
#if defined(__AVR_ATmega328P__)
  ADMUX = 0x4E;
#elif defined(__AVR_ATmega2560__)
  ADCSRB &= ~(1 << MUX5);
  ADMUX = 0x5E;
#elif defined(__AVR_ATmega32U4__)
  ADCSRB &= ~(1 << MUX5);
  ADMUX = 0x5E;
#endif
  delayMicroseconds(200);

  /* Activate the analog -> digital converter */
  ADCSRA |= (1 << ADEN);
  
  /* Starts an analog -> digital conversion */
  ADCSRA |= (1 << ADSC);
  
  /* Wait for the end of the conversion */
  while(ADCSRA & (1 << ADSC));
  
  /* Get the result of the conversion*/
  return ADCL | (ADCH << 8);
}

/* Function loop() */
void loop() {
  
  /* Measures voltage in VIN and internal reference at 1.1 volts */
  unsigned int raw_vin = analogRead(BROCHE_CAPTEUR_VIN);
  unsigned int raw_ref = analogReadReference();
  
  /* Calculation of the real tension with a cross product */
  float real_vin = ((raw_vin * 1.1) / raw_ref) * COEFF_PONT_DIVISEUR_VIN;
 
  /* Display */
  Serial.println(real_vin, 3);
  delay(1000);
}

Do not use analogReference () / AREF with this code!
To work, the code above (and below) needs to set the voltage reference to GND then to VCC. If a voltage is injected on the AREF pin, a short-circuit will be created. If you are using the AREF pin, do not use this code.

The result

Here is what the above code gives on an Arduino UNO board powered via a 12 volt AC adapter:

1
2
3
4
5
6
7
8
9
VIN-O-Meter
11.010
11.029
11.010
10.971
11.010
11.029
11.010
10.990

My multimeter measures a voltage of 11.17 volts on the VIN pin. We are therefore very close to the real value.

N.B. There is always between 0.6 volt and 1 volt of difference between the battery voltage and that on the VIN pin. This is due to the presence of a protection diode in series with the jack plug of the Arduino boards. This is completely normal.

Conclusion

This tutorial is now complete.

If you enjoyed this tutorial, feel free to comment on it on the forum, post it on social media, and support the site if you like it.






google-playkhamsatmostaqltradent