Skip to content

Krakkus.com

Electronics

Menu
  • Home
  • Posts
  • About
  • Author
  • YouTube
Menu

How to scale any voltage into the analogRead range of your microcontroller

Posted on November 25, 2022

You want to measure a voltage? But it’s outside the range of your microcontroller’s 0 to 3.3v or 5v? We can achieve this with resistors.

There are three distinct problems, each with its own solution.

Table of Contents

  • The positive voltage is above 3.3v or 5v
  • The voltage is below ground/negative
  • Both voltages are out of range
  • Arduino code
  • Network generator
  • Resistor simulator

The positive voltage is above 3.3v or 5v

If we apply double our maximum voltage over two identical resistors in series, we expect to measure half our voltage at the midpoint. It is this midpoint we are going to measure.

Simple resistor divider, voltage at midpoint is half the voltage at the top
Simulation of the voltages in a resistor network, all the voltages are evenly scaled

The voltage at the top can be calculated by multiplying the analog-read-voltage by 2. In this example I will assume a 5V microcontroller.

If we add another identical resistor, we add another 5V to the maximum voltage we can read, we can extend this as many times as we like.

With three identical resistors, we can now measure three times the maximum voltage of our microcontroller

We do only intend to measure after the first resistor, and then multiply the measured voltage by three to get the correct voltage. This means we can group the other resistors together by adding them up.

Final solution, measure three times the voltage on your analogRead pin

The voltage is below ground/negative

If we want to measure below ground, we have to set this resistor network upside down. This example assumes a 3.3V microcontroller.

Reading a negative voltage can be done with an up-side-down resistor network

Instead of connecting the bottom end to the ground, we now connect the top to the maximum of our controller. And it is now after the top resistor where we read our voltage.

Once again, we simplify the network to only use two resistors by adding them up.

Final solution for reading a negative voltage on a microcontroller

Calculating the actual voltage is not that complicated. First we multiply the voltage on the analog input by three and then add the lowest voltage we can read on the network, which is -6.6V. On the positive network we did not do this because that value was 0V.

So if we read +3.3V the actual value = (3.3 x 3) – 6.6 = +3.3V.

And if we read 0V the actual value = (0 x 3) – 6.6 = – 6.6V.

Both voltages are out of range

When the input can be below ground as well as above the controller’s maximum, we can’t tie one end of the network to ground or max-voltage. We need to tie it in the middle, using another resistor divider. This example assumes a 5V controller.

Using a three way resistor divider network, we can measure positive and negative voltages

The standing resistors on the left are equal, and without any voltage to measure would produce +2.5V at the middle for the analog pin to read.

The to-measure-voltage applied to the right will then pull that voltage up or down through the third resistor.

Then, how to calculate that third resistor? And how to translate the value read at the analog pin back to the real world value? I could not figure this out in a simple way, so I wrote a tool for it.

You find this tool further down this page.

Arduino code

It doesn’t matter how many resistors your divider has, the voltage at the measuring point always has a linear relation to the actual voltage you are trying to measure.

Therefore, all you need to do is measure two sets of voltages and store them in the map() function. It will then ‘translate’ your new reading into the new actual voltage using these data points.

const int analogPin = A0; // define analog input pin
const float voltageMax = 5.0; // maximum voltage the Arduino can read

void setup() {
  Serial.begin(9600); // initialize serial communication
}

void loop() {
  int analogValue = analogRead(analogPin); // read analog value on pin A0
  float voltageValue = (analogValue / 1023.0) * voltageMax; // convert analog value to voltage

  /*
  To setup the map function we need to sample two voltages and record 
  both the actual and midpoint voltage.
  Example: 1K - 1K resistor divider.
  Sample 1: Measure 0V, midPoint is 0V 
  Sample 2: Measure 10V, midPoint is 5V
  float actualVoltage = map(midPointVoltage, sampleMP1, sampleMP2, sampleActual1, sampleActual2);
  */
  float actualVoltage = map(voltageValue, 0, 5, 0, 10);
  
  Serial.print("Analog Value: ");
  Serial.println(analogValue);

  Serial.print("Voltage Value: ");
  Serial.print(voltageValue);
  Serial.println("V");

  Serial.print("Actual Voltage: ");
  Serial.print(actualVoltage);
  Serial.println("V");

  delay(1000); // wait for 1 second
}

Network generator

Designing a three-way-resistor-divider is not as easy as a regular one. So I wrote a script for that.

Just enter the resistors you have, or dump a list of common values in the box. Then add the maximum voltages you expect to measure and hit the compute button. After a few seconds, it will give you the results.

Resistor Calculator

Network generator







Resistor simulator

A friend of mine is making an educational tool; a resistor simulator. You can use it to try out different resistor dividers and see what the voltages at the midpoints become.

Download page

3 thoughts on “How to scale any voltage into the analogRead range of your microcontroller”

  1. Jafal says:
    March 8, 2023 at 8:39 pm

    Thanks 🙏🙏 Alot for your fast response

    Reply
  2. Jafal says:
    March 8, 2023 at 12:55 pm

    Hi

    Can you provide full Arduino sketch if you please

    Reply
    1. krakkus says:
      March 8, 2023 at 3:44 pm

      Hello,

      I added some code near the end that should do the job and compiles fine, but I don’t have an Arduino at work so I will test it later.

      Code does work.

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Other Posts

  • Hacking a DC to DC converter

    Hacking a DC to DC converter

    Introduction This is a follow-up of a proof of concept I made two months ago. I used an Arduino based DAC (8 bit 8 resistor) and an op-amp to create a signal...
  • How to add dead time to PWM

    How to add dead time to PWM

    There are situations where you absolutely want to avoid signals overlapping one another. This is when you get introduced to the term dead-time. I will give you an example of a circuit...
  • Ten ways to drive a MOSFET, with examples

    Ten ways to drive a MOSFET, with examples

    These are a couple of circuits that can drive a MOSFET. Each of them has their own pros and cons, so whether or not they are useful is highly dependent of what...
  • How to make an op-amp output PWM with duty-cycle control?

    How to make an op-amp output PWM with duty-cycle control?

    We can use a generic op-amp like the LM4562NA. We build an oscillator from the first op-amp in the IC. This produces a triangle-wave. We feed this wave into the second op-amp....
  • How does an op-amp work?

    How does an op-amp work?

    Op-amp is short for operational-amplifier. You can use it as a comparator, buffer a signal, or amplify a signal. These are some op-amps I have; they are the LM358 and the LM4562....

Tools

  • DAC generator
  • Ohms law calculator
  • Inductor calculator
  • Where to get MOSFETs?
©2023 Krakkus.com | Design: Newspaperly WordPress Theme