External reference for current and voltage measurement

Hi everybody,

I’m building a linear power supply and an Arduino Nano to measure and display values as accurate as possible on an Lcd display. The Voltage output is from 0.5 -25V (27V fluctuations!!) while the current measurement is less than 5 Amperes; I use an LM358 (powered from 5 volts) as a current sense amplifier measuring millivolts and a shunt resistor .01 ohms. I’m using a 4.096 voltage reference. My voltage divider is R1= 25K, and R2= 5k ( R1 4 parallel 100k, R2 2 parallel 10k and all are 1%).

I searched videos on precision and accuracy and watched a lot on ADC and references etc. and here’s what I could gather.

I wonder if I can 1. improve the Voltage measurement compared to (Uni-t139C) through software and 2. use a different voltage reference for current measurement, for instance 1.1V, as I am using only the 5 volts input to A1 without a divider. I think things get complicated as I have to make switch to different references to achieve this.

//Edited October 2025

// updated December13 2025 by adding an external 4.096 V-reference 
 

 #include <LiquidCrystal_I2C.h> // Library for LCD

  LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 lines

  #define analogInput0 A0

  #define analogInput1 A1

  float Voltage_in = 0.0;

  float Current_in = 0.0;

  float Temp_V = 0.0;

  float Temp_I = 0.0; 

  #define ref_voltage(EXTERNAL);

  float V_ref = 4.096; 

  float R1 = 33250.0; // connected to sourceand A0 49978

  float R2 = 4996.0;  // connected to A0 and ground

  void setup() 

  {

  lcd.init(); //initialize the lcd

  lcd.backlight(); //open the backlight 

  pinMode(analogInput0, INPUT);

  pinMode(analogInput1, INPUT);

  analogReference(EXTERNAL);

  lcd.setCursor(0,0);

  lcd.print("Power Supply V1");

  lcd.setCursor(0,1);

  lcd.print("0-27V    0-5A");

  delay(2000); 

  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("E:         Volts");

  lcd.setCursor(0,1);

  lcd.print("I:         Amps");

  }

  void loop() 

  {

   // E Volts measurement

   int V_Value = analogRead(analogInput0);

   Temp_V =  (V_Value * V_ref) / 1023.0; 

   Voltage_in = Temp_V / (R2/(R1+R2));

   lcd.setCursor(3,0);

   lcd.print(Voltage_in,3);// digits after the decimal point

   delay(10);

   //Current Amperes measurement

    float I_Value = analogRead(analogInput1);

    float Temp_I = (I_Value * V_ref) / 1023.0; 

    float Current_in = Temp_I;

    lcd.setCursor(3,1);

    lcd.print(Current_in,3);// digits after the decimal point

    delay(10);

}

Nice design. I do not do this often, but when I do, I use the calibrate method with standard temperature-stable parts. Then I use my Fluke voltage source to set the high end, and I check the mid and low points. They usually come out OK.

Unless you build in ranging, with a 25 V full scale you will get about 0.2443 volts per count. Using your reference value, it comes out to about 0.004 volt per count.

This link may help:

1 Like

You can try with the following seup:

Test Codes: (untested)

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  analogReference(DEFAULT);   //5V for V measurement
  float vb = (5.0 / 1023) * analogRead(A0);
  Serial.print("Voltage: "); Serial.print(vb, 1); Serial.println(" V");
  delay(1000);
  //-------------------------------------
  analogReference(INTERNAL);  //1.1V for I measurement
  float vi = (1.1 / 1023) * analogRead(A1) * 1000.0;
  Serial.print("Current: "); Serial.print(vi, 1); Serial.println(" mA");
  delay(1000);
  Serial.println(" == == == == == == == == == == == == == == == == ");
}
1 Like

Thanks a lot I’ll consider your suggestions for another project. As for this one, I have been inspired by some V references, high resolution measurements and precision videos and also this one: https://youtu.be/JCxF-o6tLgA. I was amazed he got the reading in accordance with his DVM. I have got a large lcd and I would like to get similar results, later when I get the 16 bit ADC. This power supply is probably the 20th I make in my life from Analog meters, ICL7106, 7107, 70135 etc and the similar tiny Chinese displays. The idea is to get a power supply where I use it as powerful voltage and current source with more 4-5 digits without frequent recourse to a DMM to check precision.

Thanks for the suggestions, it looks simple and neat. I’ll try it and consider precision. I wonder if I can still use the EXTERNAL voltage reference 4.096V for the voltage measurements as it is more precise than the DEFAULT.

but the output of the opamp will go to up to 3.5V and will not measure 5A

1 Like

Thanks a lot. Yes, I don’t want it to go beyond 4 Amps. I have a short circuit protection and current limit shutting off when exceeded. Fed up of shorts and smoke, I am happy with 3.5 Amperes only to power a halogen lamp for test purposes.

You can use 4.096V from external source via AREF-pin of the MCU. Do not forget to include analogReference(EXTERNAL) in your sketch.

1 Like

Then it makes no sense to use a 1.1V reference with a 3.5V input.
Why don't you use a rail-to-rail opamp and increase the gain

1 Like

I tried with an OP77G which requires offsetting and dual supply, and burned a few tiny OPA340 while trying. I remember I got more or less math readings I couldn’t figure out(I am a tinkerer with minimum math experience) so I gave those up and used the modest LM358 as it worked well. I have been trying to understand the V-reference relation with the max imput voltage. As I heard 1.1 is the best I used it but got reading only to 8.xx volts then I used a 2.5 reference and I got 16.xx so I figured out I need a 5V reference. So I used the propagated 4.096 and it worked. I had no idea that the voltage to measure would be down to earth if you use 1.1 reference and I only found videos talking about measuring voltages higher than 5V adding a voltage divider without specific reference to the suitable voltage reference.

Yes, and a 5V Zener diode for protection.

As I already mentioned that is not possible with your current circuit.
The output of the opamp will go way beyond the 1.1V reference voltage.
Also you are limited to 3.5A

Here is the correct way to measure the current with high accuracy

You can measure 0 to 4A using the 5V internal reference

2 Likes

aside from resistor value changes, what makes this more correct?

1 Like

For accurate current measurement you need a 4 terminal shunt resistor. Your shunt is 10 milliohms, so a connection resistance of 100 MICROOHMS will give you a 1% error.
Also you need to consider the material of the connections, as if you create a thermocouple that will also throw off your results.

The problem with using resistors of such a low value is that the resistance of the solder joints and circuit board traces can be a similar order of magnitude and hence will create a voltage drop similar in magnitude to the voltage drop across the sense resistor itself. This makes accurately measuring the voltage drop through the precision sense resistor a bit tricky. The most robust solution to this is to separate the high current path from the voltage sense path with a 4 terminal shunt. The high current path may have a few extra milivolts of drop due to the extra miliohms of resistance from the traces and solder joints, but the voltage sense connections will not see this due to the different current path and can therefore much more accurately read the shunt voltage.

1 Like

here's a circuit from TI

image

1 Like

Which "connection" do you mean?

It may be a good idea to calibrate the meter for the effective resistance between the two ADC connections.

1 Like

@jim-p
All components have values in #14 except U1a and U1b.

1 Like

I was waiting for @khaled1970 to ask but for you:
The MCP6002 is available from Digikey in an 8 pin DIP package for only $0.44 (USD)

2 Likes

If it were easy for me I would buy, as I like to have those precision cheap parts. I can only buy from sources like Temu, who don’t have such items. If I were to order from Digikey or Mouser I have to order a big list to compensate for customs, tax in my country and overseas post. This is why I try to make do with whatever I have.

As for your suggested circuit, I added the resistors and the second OP as in the schematic. At the outset I get 0.475 Volts DC no load. When I connect a load (a car halogen lamp) to 12V source, I read 3.632 Volts on the UNI-T and 12V 3.2A on the power supply. I have to only subtract the 475 millivolts in software.