Using a ModeMCU as a voltmeter

Last modified 12 months

Measuring volts with an ESP8266

Don't have a multimeter? No problem! Did you know that you can use your NodeMCU (or any ESP8266) as if it were a voltmeter?

Sometimes a voltmeter is almost essential to be able to solve any problems that arise when working with microcontrollers, or with any electronic circuit in general.

In this article we will look at how we can using the NodeMCU as a basic voltmeterThe following table provides a list of the most common types of multimeters that can help us if we do not have a multimeter.

What is an Analogue to Digital Converter (or ADC)?

I'm sure you know that, in the world of computers and microcontrollers, what these strange wire-legged animals handle are zeros and ones.

Among the wonders that the ESP8266 has in such a small space, there is one pin (the A0 or ADC0) which includes an analogue-to-digital converter o ADC (from Analog Digital Converter).

An ADC is an electronic circuit that converts a real-world analogue signal that can have any value, with an infinite number of decimal places, into a sequence of ones and zeroes that the microcontroller can understand.

And, yes, inside the ESP8266 is an ADC circuit.

The ESP8266 ADC

I want this blog post to be eminently practicalfor beginnersso I won't go into the details of the fine print of the ADC (which is a lot, and very small). Just to give you the basics, so that you can use it:

The ACD of the ESP8266, which is the microcontroller found on boards such as NodeMCU, Wemos D1 Mini and similar boards, includes a 10 bit ADC and 1 volt max..

What does it mean that the ADC is 10bit?

What has that "resolution".

The numbers in decimal that can be represented with 10bits range from 0 to 1023 and that means that no matter what we do, the ADC will be released on one of those 1023 jumps (without the possibility of decimals, or intermediate points, so that we understand each other).

In other words, if we wanted to measure from 0 to 1023 volts, the ADC would give a resolution of 1 volt. (we could not measure 534.7 volts, only 534 or 535 volts). If we wanted to measure a range of 5 volts, the ADC would give us a resolution of 1024/5 = 0.00488 volts.

What does it mean that the ADC is 1 volt maximum?

This means that the maximum voltage we can apply directly to the ADC is 1 volt (in other words, it has a range from 0 volts to 1 volt).

In practice, this means that if we put exactly 1 volt into the ESP8266 ADC, without using an external voltage divider, it will give us the maximum value which is 1023.

What if we want to measure voltages of more than 1 volt?

No problem. We'll just have to use a voltage dividerwhich consists of two resistors(later on we will see how to calculate these resistors, and I will give you some examples already calculated so that you don't have to do it yourself).

You are probably not using an ESP8266 microcontroller directly, you are most likely using a board such as NodeMCU (in any of its variants) or Wemos D1 Mini and I have an ESP8266 microcontroller. great news for you: These plates come with the resistors already in place..

The problem you will encounter is that most of these boards have been fitted with resistors by the manufacturer to create the voltage divider we were talking about earlier, suitable for measuring a maximum of 3.3V (in other words, it will give us a value of 1023 when we put 3.3 volts into it).

Logically, in many cases this does not work for us. You will want to measure many times, more than 3.3 volts. You will want to measure voltages of 5 volts, 12 volts, or more.

The solution is easy, we only have to modify the voltage divider, by attaching an external resistor to measure the voltage of your choice.

Limitations of the ESP8266 ADC

ADC circuits are available on the market with a accuracy unbelievable, an resolution incredible and a repeatability incredible. The ESP8266 ADC is unfortunately not among them, but for our purposes it is sufficient.

The ESP8266 ADC has relatively low resolution (only those 1024 jumps, which we talked about before), low precision (we don't know very accurately if the measurement it indicates is the correct one) and the worst thing is that it is quite noisy.

The fact that it is quite noisy causes the ESP8266 ADC to be a little "myopicand that the voltage we put in is not completely clear to him, but he sees it as if he were looking at it through a "...".broken glass"and that means that it can sometimes get it wrong. This is of little importance for most of the uses we are going to make of it (measuring voltages). because that's what we are there for, with our privileged brainIn this case, we will ignore erroneous measurements very easily when we see them, almost without noticing them.

There are some other limitations such as the linearity and others that I am not going to go into, but if you are interested in this subject, you can find a lot of information on the internet.

Practical: How do I measure voltage with the NodeMCU?

To measure any voltage, you'll need two parts: The hardware and software.

As hardware, in this first explanation, we are going to use only one NodeMCU without any additional resistors because we are going to measure a maximum of 3.3 volts Remember what I told you about the NodeMCU already having the voltage divider on board to measure up to 3.3 volts?

As software, I'm going to teach you how to There are two ways to do this:

With ESP Easywhich does not require any programming and allows you to do a lot of things with that voltage, such as graphs, calculations, rules, sending it to other systems and more.

In C++ (the Arduino language) which gives you more flexibility about what you can do and allows you to include it in other projects.

How to measure voltage with ESP Easy

The first thing to do is to install ESP Easy on your NodeMCU (you can see how to do this at the article I wrote on ESP-Easy).

Now you have to tell ESP Easy that you want to use the ADC pin (A0) to read voltage. Just go to the "Devices" (Devices) and add the analogue input and configure it:

Adding the analogue input in ESPEasy
Configure ESPEasy analogue input

And now look at one thing: Do you see that I have written a formula that says %value%*0.3125?

I use this formula to give me the actual voltage value that I apply to it, instead of the number from 0 to 1023 that we talked about before (which is used internally by the ESP8266).

What ESPEasy will do is, before displaying the internal value from 0 to 1023 (that %value% in the formula), multiply it by the number 0.3125.

Imagine that we put into ESPEasy the voltage of a 1.5V batteryinstead of showing us a number like 465 (which would be 1024 / 3.3 * 1.5) will show 1453.1 which is the actual voltage. approximate (in millivolts, if we wanted to see it in volts we would use 0.003125 instead of 0.3125 in the formula).

We'll talk about that later approximation of the actual voltage and the formula used.

By the way, I didn't tell you where to connect the battery in the example:

The voltage to be measured (the battery) has to be connected to GND (which is the negative) and pin A0 (which is the analogue input of the NodeMCU).

How to measure voltage with C++ (the Arduino language)

The way to read the voltage in Arduino, is through the instruction analogRead()

Here is a super simple ESP8266 code just to show you how to read the voltage on the A0 pin and print it on a web page generated by the ESP8266 itself.

   #include <ESP8266WiFi.h>
   #include <ESP8266WebServer.h>

   const char *ssid = "your_wifi_network_name";
   const char *password = "your_wifi_network_password";

   ESP8266WebServer server(80);

   void setup() {
     Serial.begin(115200);

     // Connecting to the WiFi network
     WiFi.begin(ssid, password);
     while (WiFi.status() != WL_CONNECTED) {
       delay(250);
       Serial.print(".");
     }
     Serial.println("");

     Serial.println("Connected to WiFi network");

     // Defining web server routes
     server.on("/", HTTP_GET, handleRoot);

     // Start the web server
     server.begin();
   }

   void loop() {
     // Handles requests from the web server
     server.handleClient();
   }

   void handleRoot() {
     // Reads the voltage at A0
     int valueA0 = analogRead(A0);

     // Convert the value to voltage (assuming a reference of 3.3V)
     float voltage = A0value * (3.3 / 1023.0);

     // Construct the HTML response
     String html = "<html><body>";
     html += "<h1>Voltage at A0</h1>";
     html += "<p>Value in A0: " + String(valueA0) + "</p>";
     html += "<p>Voltage: " + String(voltage) + " V</p>";
     html += "</body></html>";

     // Send the response to the client
     server.send(200, "text/html", html);
   } 

Measuring more than 3.3 volts with the NodeMCU

The above example is suitable for measuring up to a maximum of 3.3 volts, because the voltage divider that comes with the NodeMCU is calculated for that.

If we want to measure more than 3.3 volts, we will have to modify the voltage divider (remember that the function of the existing voltage divider in the NodeMCU is to adapt the voltage we want to measure to a range of 0 to 1 volt, which is the maximum we can put into the ESP8266).

Fortunately, modifying it is very simple. Here's how to modify it by adding only one resistor (let's cut to the chase and then I'll tell you why and how to calculate these resistances).

To measure up to 5 voltsThe best thing to do is to use a resistor of 270KΩ (270 kiloohms). With this value the maximum you could measure would be 5.7 volts and the formula for ESPEasy would be %value%*0,0,05566 (5.5/1024 = 0,0556640625).

To measure up to 12 voltsThe best thing to do is to use a resistor of 1MΩ (1 megohm). With this value the maximum you could measure would be 13.2 volts and the formula for ESPEasy would be %value%*0,1289 (13.2/1024 = 0,12890625).

And how to make a voltmeter with a Wemos D1 Mini?

Exactly the same as we have done for the NodeMCU. The only difference is that the pin you have to use is in a different place:

What if I'm brave and want to measure volts with an ESP8266, directly?

If you want to measure volts with an ESP8266 directly, an ESP-12E for example, you will need to fit a suitable voltage divider.

To do this you will have to calculate the necessary resistors to make your own voltage divider, bearing in mind that the maximum voltage you should apply to the ESP8266 is 1 voltas set out in the following section.

Note that you will have to check which pin corresponds to the analogue input, depending on the module you are using (e.g. an ESP12E like the one in the picture).

What if the examples you have given don't work for me? How do I calculate the resistors needed to make my own voltage divider?

To measure more than 3.3 voltswe will have to modifying the voltage dividerwhich we discussed earlier.

Let's first look at the voltage meter that comes with the NodeMCU, looking at that part of the schematic:

Analogue input NodeMCU to ESP8266

The bottom part goes to negative, the top part (where it says ADC EX) goes to the NodeMCU pin marked as A0 (analogue input) and the left part (where it says ADC) goes to the ESP8266 microcontroller.

These two resistors form the voltage divider, and at the central point (where ADC comes out) there is a value proportional to what we put in at the top (ADC EX) but divided according to a formula.

Here is a formula that, if mathematics is your thing, will tell you more than 1000 words and explanations:

V1023 = 1V * (100kΩ + 220kΩ + R) / 100kΩ
Where R is the resistor that you put in series with pin A0.

I recommend that you use a voltage divider calculator like this one.

Below is an example of how it is used to calculate the resistance if we want to measure a maximum of 4.2V.

In case you have any doubts, I leave you a clear example, with the development of the formula, so that it is as easy as possible for you to calculate it yourself:

Interactive voltage divider simulation

With this interactive voltage divider simulator you can see how the output of the voltage divider varies depending on the input voltage and the resistors used.

I encourage you to play with it and to check, before building the circuit, if the values you have selected are valid for your application.

Just click on the "Start simulation" button and change the values you want.

A detail for the "techies": Note that I have represented the ESP8266/ESP32/NodeMCU as a 1GΩ resistor so that the measurement is not affected.

The accuracy of voltage divider resistors

The accuracy of the measurements you obtain will depend very much on the precision of resistors you use.

In quality commercial measuring instruments, resistors with a tolerance of 0.1% and even less are used.

Common, inexpensive and easy to find resistors usually have tolerances of one 5% or 10%This means that if you choose a 270KΩ resistor and it has a 10% tolerance you will not know the exact value of the resistance (unless you measure it) and it could be between 243KΩ and 297KΩ.

This means that the measurement you obtain will also have a relatively large tolerance.

If you need to obtain very accurate voltage measurements, you will need to take this into account.

Another thing you have to take into account is that there are not resistors with all the values and you will have to use standard resistors (the commercially available ones). Fortunately you will be able to adjust the ESPEasy formula easily and at any time. to correct it.

Calibration

Ideally calibrate the meter using a voltage source of known value.a to check the accuracy of the measurement, but what if you do not have a voltage source of known value?

Surprise: You do have one! The NodeMCU (and the Wemos D1 Mini and other similar boards) includes a very accurate 3.3V voltage regulator on board.You can use one of the 3.3V pins to measure it and calibrate the meter until the reading is exactly 3.3V.

Calibration consists of two parts:

Adjustment of the formulaTo correct possible deviations in resistance values and the like.

Adjustment of calibration pointsAllows you to calibrate at two intermediate points in the measurement range to correct linearity errors (for this you will need a reference voltmeter or a multimeter).

But I don't have any resistors, do I have to buy them?

If you don't have a resistor, don't worry, it's not too late. one solution remains

The good thing is that the resistor you need will be within a huge range, so it will be easy to locate a good one in any old or broken device you have lying around. You will simply have to learn how to read its valuewhich is quite easy, and adjust the formula depending on the resistance you have been able to find. You unsolder it from the old device and use it to measure.

Soon I will teach you how to read their value. For now, ask in the chat and I'll help you.

Measuring the battery powering a NodeMCU

This is a widely used utility of this type of application. If you have a battery-powered NodeMCU (or other similar board) you can use this same technique to measure the battery voltage and thus know how much charge is left.

For example, if you are powering it with a Li-Po or Li-Ion battery that can give up to 4.2V, you only have to connect the positive of the battery to the A0 pin through a 100Kohm resistor, as I have indicated before.

With a 100K resistor the maximum you can measure is 4.2V, perfect for measuring a battery of this type using the maximum possible range of the ADC.

Here you can see the calculation of the required resistance made with the voltage divider calculator online.

Remember that the resistor we have to put is 100K (and not 320K) because the NodeMCU already has a 220K resistor installed on the board and we are going to put this one in series.

With this voltage divider when you put 4.2V at the input you will have 1V at the output and as the NodeMCU measures from 0 to 1020 = 0 to 1V, you will have to put a formula to give you the value in volts (instead of a number which is 0=0V and 1023=1V), remember what we have seen before?

The formula will be %value%*0,0041015625 (porque 4,2V/1024=0,0041015625V).

Think about it, when you put 4.2V to the output 1V that will give you a value of 1023. If you multiply 0,0041015625Vx1024= 4.2V Just the voltage you have at the entrance!

You can check the rest of the values, to confirm that the formula is correct, by using a rule of three or by using the formula above.

4 thoughts on “Uso de un ModeMCU como voltímetro”

  1. pretty good, but many numbers are wrong and confusing, like several commas in a number in a formula or talking about voltages over 140v which I think are typing errors.

    Reply
      • I find it regrettable that you have to be told about it and that a year later you still haven't corrected it. It doesn't seem to me that you have explained it well and you still want them to do the work for you, what a nerve you have.

        Reply
  2. I have a doubt the pin A0 of the wemos says max 3.3 v but as I read the Adc works with 1 volt so when I use it as adc I must always be in the range of 1 volt?

    Reply

Leave a comment