# Reading battery voltage in project

Found this schematic and code below for reading voltage from a 7.4v LiPo and cannot get my head around exactly what is happening with the mapping. The input to the A7 is the centre tap of a 10K with a 1K to ground.
From what I can gather, the voltage into the A7 pin will be around 0.75V which I believe should give an Ad_In of around 153 given 5v as the reference. The V_Cal value is set to 1166 and again, as far as I can make out, that should give a value of approx. 174. What I cannot understand how this ends up at 760 for Ad_Cnv or 7.6v on the display.

``````void do_battvolts()
{
Ad_Cnv = map(Ad_In, 0, 1023, 0, V_Cal);          //convert to actual voltage reading
display.setCursor(50,56);
display.setTextSize(1);
display.print("Batt V = ");
display.print(Ad_Cnv/100,2);                               //show two decimal result
display.setTextSize(2);
}
``````

To clarify, you are trying to understand how the voltage divider drops your voltage from 7.4 to 0.74?

When the 7.4 volt fully charged LiPo has delivered power for some time the voltage drops. When it drops below 7 volts I'm not sure the controller feels happy.

To clarify, how does this, which I believe gives a number of approx. 174, give an output of the battery voltage here.......

Never mind the detail on battery levels falling etc. as that is not a problem as it stands.

The voltage divider gives 0.75v at the A7 input. When mapped to (assuming 5v regulated) a number between 0-1023 of 153.
This is then mapped to a calculated value between 0 and 1166 but how does this come about. As I see it it should be either 1166 as the 0.75v represents near to full battery voltage which doesn't make sense or there is some other calculation/conversion I am missing. Answer should be somewhere around 760 mark for the "print" of (Ad_Cnv/100,2) to show approx 7.66v on the display.
Note that actual precise voltage levels not important at this instance as I can recalibrate and also the battery voltage ranges from 7.4v nominal to 8.4v fully charged.

The answer is in the code that you didn't post.
See if Aref is set to INTERNAL (~1.1volt) in setup().
Leo..

That would be it......... never seen that used before, live and learn.
1st line in setup.
Makes sense now...cheers.

``````/*
This is a program to use the MCP3424 A/D converter along with a Nano and OLED
to provide a microOhmmeter function.
This unit automatically conducts four ranges on the A/D converter and selects the proper one.
Start date is 04/18/2019
Complete date 04/20/2019
Upgraded to PCB layout, complete rework of sketch program file
Upgraded date is 07/01/2020
Upgraded to measure test current with 0.1 Ohm resistor
Upgraded date is 07/03/2020
Upgraded to read over 2 OHms 08/25/2020
Minor tweeks and a warning note
ref Gainx1, max input voltage is 2.5 VDC for full scale ***
ref Gainx8, max input voltage is 0.25 VDC for full scale **
** ref SRxxB is bit resolution, ranging from 12 to 18 bits  ***
** MCP 3421 has one channel input
** MCP 3422 has two channel inputs
** MCP 3424 has four channel inputs, from CH1 to Ch4
* *************************************************************************
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
DO NOT DO RESISTOR TESTS WITH ONLY THE USB POWER TO THE METER!!
THAT RESISTOR UNDER TEST REVERSES BIASES THE ARDUINO NANO 5 VOLT REGULATOR
AND WILL BLOW THE REGULATOR.  A 6.6 VOLT POWER SUPPLY MUST BE CONNECTED
TO THE METER ANY TIME THE USB PC PORT IS PLUGGED INTO THE ARDUINO NANO
WHEN CONNECTING A TEST RESISTOR TO THE MICRO OHM METER.
*  ***********************************************************************************
*/
#include <Wire.h>
#include <MCP3424.h>
#define OLED_RESET 4
const int V_Cal = 1000;                      //1166 number is used to calibrate voltage
float R_Cal = 1.005; //  R_CAL is the calibration of the meter against a known resistor
#if (SH1106_LCDHEIGHT != 64)
#endif
float value;  //define variable
double R5_Ohm ;
float Vx_Ohm;
float Rx_Ohm;
double range1;
double range2;
double range3;
double range4;
float test_resistor;
float Ad_Cnv = 0;
int Ad_In = 0;
void setup()
{
analogReference(INTERNAL);
Serial.begin(9600);
display.begin(SH1106_SWITCHCAPVCC, 0x3C);// initialize 128/64 with the I2C addr 0x3D

display.setTextSize(3);
display.setTextColor(WHITE);
display.clearDisplay();

display.setCursor(25, 0);
display.print("uOhm");

display.setCursor(20, 30);
display.print("meter");
display.display();
delay(1000);
}
void do_R5ohm()              //measure the voltage on 5 Ohm 1% resistor for calculation
{
adc.creg[CH4].bits = {GAINx8, R16B, CONTINUOUS, CH4, 1 };
R5_Ohm  = R5_Ohm * 10.14;         //R5_Ohm variable contains voltage drop on resistor
}
void do_range1()               //following routines runs variable settings on channel 3
{
adc.creg[CH3].bits = {GAINx8, R18B, CONTINUOUS, CH3, 1 };
range1 = range1 * R_Cal / R5_Ohm;
}
void do_range2()
{
adc.creg[CH3].bits = {GAINx1, R18B, CONTINUOUS, CH3, 1 };
range2 = range2 * R_Cal / R5_Ohm;
}
void do_range3()
{
adc.creg[CH3].bits = {GAINx2, R14B, CONTINUOUS, CH3, 1 };
range3 = range3 * R_Cal / R5_Ohm;
}
void do_range4()
{
adc.creg[CH3].bits = {GAINx1, R12B, CONTINUOUS, CH3, 1 };
range4 = range4 * R_Cal / R5_Ohm;
}
void do_battvolts()
{
Ad_Cnv = map(Ad_In, 0, 1024, 0, V_Cal);          //convert to actual voltage reading
display.setCursor(50, 56);
display.setTextSize(1);
display.print("Batt V = ");
display.print(Ad_Cnv / 100, 2);                            //show two decimal result
display.setTextSize(2);

}
//*************************************************************************************
//main program starts here
void loop()
{
display.setTextSize(2);
display.setTextColor(WHITE);
do_R5ohm();                                        //run voltage on 5 ohm resistor

Serial.println  (R5_Ohm, 5);
if (R5_Ohm < 0.01)           //if A/D result is negative, no test resistor is connected
{
display.clearDisplay();
display.setCursor(0, 20);
display.setTextSize(4);
display.print("OPEN!");
display.display();
}
else                                          //do the entire resistance check program
{
do_range1();
do_range2();
do_range3();
do_range4();
// Serial.print ("R5 ");
// Serial.println (R5_Ohm, DEC);               //send to USB for test_resistor purposes
test_resistor =  max(range1, range2);        //identify the maximum resistance value
test_resistor =  max(test_resistor, range3);
test_resistor =  max(test_resistor, range4);
if (test_resistor > 2.0)                             //if over 2 ohms, show over range
{
display.clearDisplay();                                                //over range
display.setCursor(0, 0);
display.print("Over");
display.setCursor(0, 25);
display.print("Range");
display.display();
}
else
{
//  Serial.print ("  test_resistor=");
//  Serial.println  (test_resistor, DEC);
display.clearDisplay();
display.setCursor(80, 38);
display.print("Ohm");                                              //show ohms value
display.setCursor(0, 38);
display.print(test_resistor, 4);

display.setCursor(80, 19);
display.print("mOhm");
display.setCursor(0, 19);
display.display();
//  Serial.println  (test_resistor, DEC);
if (test_resistor * 1000 > 999)    //show milliohms result for either xxxx.xx, or xxxx
{
display.print(test_resistor * 1000, 0);                       //show milliohms value
display.display();
}
else
{
display.print(test_resistor * 1000, 2);
display.display();
}
if (test_resistor * 1000000 < 999999)             //test for maximum uOhm digit display
{
display.setCursor(80, 0);                              //if under 999999, display it
display.print("uOhm");
display.setCursor(0, 0);
display.print(test_resistor * 1000000, 0);
do_battvolts();
display.display();
}
else
{
display.setCursor(0, 0);
display.print("      ");
display.display();
}
}
}
}``````

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.