Nov 30, 2018, 08:34 PM
Registered User

# BattIR vs other Battery IR measuring meters

By now, a few of the RCGroup readers may have read the December issue of the AMA Model Aviation magazine, and have noted the rather large difference in IR measurements between the BattIR meter and the other top of the line meters.

As a refresher, the BattIR meter software measures the voltage on each cell of the battery under two different test currents. For a 6S LiPo, those two test currents run about 4.5 Amps and 16 Amps. The voltage on each cell is read by a MicroChip microcontroller that has 2^12 or 1/4096 resolution.

The BattIR meter reads the voltage on each cell 10 times, and takes an average of those readings. The various test voltages and test currents for each cell are displayed on the BattIR meter during the testing process.

The BattIR meter switches on the low current, pauses for two seconds for the battery voltage to stabilize, then quickly measures the voltage on each cell, and stores the values to an internal table. It repeats that test under the high current, and again stores the voltage values.

Next, the BattIR meter uses this formula to calculate the IR of each cell. This test routine has been described as a "Two Tier" test, in that two different test currents are involved.

Cell IR = (V_lowAmps - V_hiAmps) / ( I_HiAmps-I_LowAmps)

This formula is accurate to the point that it can predict with reasonable accuracy the batteries output voltage under actual running conditions where the battery current may be 50-100 Amps or so.

The other meters use a semiconductor (MosFet) for the test current load for the battery. This has an advantage of very low cost. Its disadvantage is that it can not handle those currents and power dissipation for more than a few milliseconds.

Vollrathd did a lot of manual testing of these batteries several years ago, finding that a very brief load test on a battery can result in voltage differences when doing the same load test over a period of several seconds. This effect can be significant when measuring voltage differences of a few dozen millivolts during a test process.

Apparently, the other meters use a different method of calculating the Battery IR values. That would involve the following formula:

I changed the software on the BattIR meter to reflect the testing under no load/load condition and got these results on a 6S 4500 Mah LiPo battery pack. The battery pack open circuit voltage is 3.783 Volts DC.

BattIR meter test result = 5.37 MilliOms on the 6S LiPo.

So, which is correct? IMHO, both work well when comparing one battery against another battery. But, if you want raw test result accuracy, the "Two Tier" test method does have some advantages.

Now, as far as the suggested maximum current limit goes, the Giles meter does its max current limit based on its calculated cells IR value.

That formula basically is maximum cell heating watts = 6 Watts per Amp Hour of the cell. So a 4.5 Amp Hour battery can handle 27 Watts internal heat on each cell with reasonable reliability.

But, the BattIR meter also uses the same 6 Watts per Amp Hour limit on the battery pack. And, the BattIR meters will show a realistic cell internal IR value, that happens to be nearly double that of the Giles meter.

Bottom line, to have the BattIR meter match the maximum current limit of the Giles meter, you'd have to use around 11 Watts per Amp Hour for the calculation.

One item of interest, the wider range of the Cell IR values on the BattIR meter, compared to the other meters in the MA column.

I've checked my four 6S 4500 mah Lipo packs with the BattIR meter. All of them had closely matched IR values, per the typical result below.

Cell #1 - 5.69 milliOhms
Cell #2 - 5.69 milliOhms
Cell #3 - 5.78 milliOhms
Cell #4 - 5.87 milliOhms
Cell #5 - 5.87 milliOhms
Cell #6 - 5.78 milliOhms

Interesting stuff.
Last edited by vollrathd; Dec 01, 2018 at 04:03 PM.
Dec 01, 2018, 08:39 PM
Registered User

# LiPo Temperature Tests

This subject has been covered many times in RCGroups, and elsewhere. The IR values of these LiPo battery packs vary all over the map with temperature changes.

I just ran two tests on one of my 6S 4500 Mah Gens Ace LiPo packs. At 65F, the BattIR meter shows 5.69 milliOhms. When the same battery pack was warmed up to 97F, the BattIR meter showed that the battery IR value dropped to 2.76 MilliOhms. That's a very significant change.
Dec 02, 2018, 10:30 AM
Registered User

# BattIR meter and A123/Life tests

FYI
The open circuit voltage on these A123 and Life receiver batteries ranges from 3.6 VDC down to around 3.4 VDC after charging.

As such, the BattIR meters "Two Tier" test process provides reliable IR values for these critical receiver battery applications.

So far in my club, the BattIR meter has kicked out four Life receiver battery packs due to a bad cell. This meter directly displays the cell IR values along with the voltage on each cell at around both one Amp and 4.5 Amp loads.
Last edited by vollrathd; Jan 22, 2019 at 03:44 PM.
Dec 02, 2018, 12:00 PM
Registered User

Vollrathd has been working with those Arduino Nanos on other projects. Just crossed my mind that a BattIR software upgrade could be used to spit out all the calculations for a Lipo battery test through the Batter's PicChip programming connector.

Then, plug in an Arduino Nano to that programming connector with its own Sketch to read the BattIR test results.

Now, the Arduino have a built in serial communication system that allows sending the info to your PC. And, EBay has those Arduino Manos for a few dollars.

Add that to my list of winter projects!

Got a good start on the BattIR programming to send the data to the Arduino. That Saleae Logic 16 data analyzer really helps in setting this sort of serial data strings up.
Last edited by vollrathd; Dec 02, 2018 at 11:39 PM.
Dec 22, 2018, 10:28 AM
Registered User

# BattIR meter communication update

I've been working on a communication update for the BattIR meter.

This software update for the existing meter allows sending all battery test results through the existing PicChip 5 pin programming connections to an Arduino Nano to your PC. From that, It's a quick copy and paste to an Excel spreadsheet.

Right now, I've got the downlink from the BattIR meter to the Arduino to the PC working. What's left is organizing the results to fit into the spreadsheet. Or Word file.

More to come.
Dec 22, 2018, 09:30 PM
Registered User

# Progress Update

Here is progress so far. The link between the BattIR meter to the PC USB port via the Arduino Nano is working. Attached are two photos of the BattIR meter along with the screen dump to the PC via the free "Termite 3.4" USB software. Note the slight difference in voltage reading, due to the battery recovering slightly after the IR test.

Next is how to label the various printouts from the BattIR meter to the PC USB terminal. Thoughts so far is to simply program the BattIR meter to send a number to the Arduino and on to the PC showing that same test number to the PC screen. And, that number would be incremented each time a test is conducted. The number would be saved to the BattIR meter's MicroChip EERom, and would range from zero to several thousand?

Photos of the two readings are attached.

### Images

Dec 23, 2018, 01:44 AM
Registered User

# Sample Test Result Screen Dump of BattIR meter

Here is what a copy/paste of the screen dump on a 10 year old 5S2P A123 pack along with a 6S1P 4500 mah LiPo looks like.

Code:
```Test Report #  6
Cell#1  Cell#2  Cell#3  Cell#4  Cell#5  Cell#6  Cell#7
3.340   3.340   3.340   3.340   3.270
Low Amp Voltage
3.315   3.315   3.314   3.315   3.218
Medium Amp Voltage
3.279   3.278   3.277   3.280   3.146
High Amp Voltage
3.254   3.253   3.253   3.255   3.096
Cell IR Values
07.63   07.76   07.63   07.51   15.27

Test Report #  7
Cell#1  Cell#2  Cell#3  Cell#4  Cell#5  Cell#6  Cell#7
3.766   3.761   3.758   3.768   3.767   3.755
Low Amp Voltage
3.737   3.730   3.727   3.735   3.734   3.723
Medium Amp Voltage
3.696   3.687   3.683   3.690   3.689   3.678
High Amp Voltage
3.668   3.657   3.653   3.659   3.658   3.647
Cell IR Values
06.33   06.70   06.79   06.97   06.97   06.97

Test Report #  8 (By holding the switch down, only the these two results are shown.)
Cell#1  Cell#2  Cell#3  Cell#4  Cell#5  Cell#6  Cell#7
3.765   3.759   3.756   3.766   3.765   3.753
Cell IR Values
06.23   06.42   06.33   06.79   06.69   06.69```
Last edited by vollrathd; Jan 08, 2019 at 08:18 PM.
 Dec 23, 2018, 03:30 PM Registered User I really like the idea of having all that info laid out like that to give a big picture view. I used to keep a logbook with all sorts of data for each of my packs written down. Something like this would be much nicer. I’ve gotten lazy and don’t track everything like I used to, but still do initial data and then periodic updates to watch them.
Dec 23, 2018, 11:03 PM
Registered User

# BattIR Serial Port Program

Here is the BattIR C program with the addition of the interconnection to an Arduino Nano, which connects to the IBM PC. This file along with the Arduino Nano, and Hex codes will be posted to the GitHub site later on.

Code:
```/*
BATTERY IR METER TEST UNIT RELAY SYSTEM VERSION IV
AMA Magazine
This version includes a precision 0.2% 5 Volt DC reference
This version includes links to an Arduino Nano for telemetry to PC

Version 12-23-2018
Following are digital commands for the Arduino Nano that are sent to the serial
port
200      Send Text Cell#1  Cell#2  Cell#3  Cell#4  Cell#5  Cell#6  Cell#7
201      Carriage return
202      Send three spaces
203      Send decimal period
204      Send Text Volts No Load
205      Send Text Volts Low Amps
206      Send Text Volts Mid Amps
207      Send Text Volts High Amps
208      Send Text IR Values
209      Send Text Test Report #

*******************************************************************************
The "C" program in the mikroC format follows:
*******************************************************************************
*/

// Set up PicChip for LCD function per instruction in mikroC manual
sbit LCD_RS at RB3_bit;
sbit LCD_EN at RB2_bit;
sbit LCD_d4 at RC4_bit;
sbit LCD_d5 at RC5_bit;
sbit LCD_d6 at RC6_bit;
sbit LCD_d7 at RC7_bit;

sbit LCD_RS_Direction at TRISB3_bit;
sbit LCD_EN_Direction at TRISB2_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
//set up definitions
unsigned char lcd_loc ;
float Test_Amps,Batt_IR,Test_LoAmp,Test_HiAmp;
unsigned long CellCnt,BattNL,BattV5ohm,BattV2ohm,BattV14ohm,Batt_Mah,calc;

unsigned char  NUMA, NUMAbit,nano_shift;
unsigned long ch,Cell_1,Cell_2;
unsigned char Mah_1000, Mah_100;                        //Batt Mah numbers
unsigned long tlong   ;
unsigned char counts,LCD1,LCD2 ;
unsigned int ArrayV [8] ;
unsigned int Array14ohm [8];
unsigned int Array2ohm [8];
unsigned int Array5ohm [8];
unsigned long int ArrayIR [8];
//   Look Up tables
unsigned char LCDRow[] = {1,2,3,4,1,2,3,4}       ;              //LCD Rows
unsigned char LCDCol[] = {4,4,4,4,15,15,15,15}   ;           //LCD Columns
unsigned char LCDIRCol[] = {6,6,6,6,17,17,17,17}   ;         //LCD Columns
unsigned char LCDIRColIR[] = {4,4,4,4,15,15,15,15} ;       //IRLCD Columns
// these are the channel assignments to turn on proper relay for each cell
//changed port A from RA3 to RA2
unsigned char porta_bat[] ={0x04,0x20,0x40,0x00,0x00,0x00,0x00};
unsigned char portc_bat[] ={0x00,0x00,0x00,0x01,0x02,0x04,0x08};
#define switch portb.rb1
#define pressed 1
//watch which resistor goes to which cpu port!
#define R2ohm PORTb.rb5
#define R5ohm PORTb.rb4
#define on 1
#define off 0
#define nanodata PORTb.rb7                          //port to Arduino Nano
#define nanoclock PORTb.rb6                         //port to Arduino Nano
#define nanostrobe PORTb.rb0
#define nano_1delay 100     //delays for Arduino and serial port functions
#define nano_2delay 400
#define nano_3delay 10000
//*****************************************************************************
//** Routine takes one byte data in NUMA (0-255) and nanoclock and nanodata ***
//** This needs to be cleaned up with a "For 0-8" routine *********************
//*****************************************************************************
void Data_Send(void)
{
nanostrobe = on;                                 //LOGIC ANALYZER TRIGGER
nano_1delay;
nanostrobe = off;

nanoclock= on;                                       //START CLOCK SIGNAL
delay_us(nano_3delay)  ;
nanoclock = off;
delay_us(nano_1delay);
nano_shift = 0b10000000;
nanoclock= on;                               //START CLOCK SIGNAL    bit7

NUMAbit = NUMA & 0b10000000;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock= on;                                //START CLOCK SIGNAL    bit6
NUMAbit = NUMA & 0b01000000;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock= on;                               //START CLOCK SIGNAL     bit5
NUMAbit = NUMA & 0b00100000;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock= on;                                //START CLOCK SIGNAL    bit4
NUMAbit = NUMA & 0b00010000;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock= on;                                //START CLOCK SIGNAL     bit3
NUMAbit = NUMA & 0b00001000;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock= on;                                 //START CLOCK SIGNAL    bit2
NUMAbit = NUMA & 0b00000100;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock= on;                                //START CLOCK SIGNAL     bit1
NUMAbit = NUMA & 0b00000010;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock= on;                                  //START CLOCK SIGNAL    bit0
NUMAbit = NUMA & 0b00000001;
if(NUMAbit==0)nanodata = off;
else nanodata = on;
delay_us(nano_1delay);
nanoclock = off;
nanodata = off;
delay_us(nano_1delay);

nanoclock = off;
delay_us(nano_3delay);
}
void Ard_Volt(void)             //this routine sends NUMA 1.234 to Arduino
{
NUMA = tlong /1000;
Data_Send();
NUMA = 203;                                                 //send period
Data_Send();
NUMA = (tlong/100)%10;
Data_Send();                                                  //3rd digit
NUMA =(tlong/10)%10;                                          //2nd digit
Data_Send();
NUMA = (tlong /1)%10 ;                                        //1st digit
Data_Send();
}
void Ard_Mohm(void)              //this routine sends NUMA 123.45 to Arduino
{
NUMA = tlong /10000;
Data_Send();
NUMA = (tlong/1000)%10;
Data_Send();                                                  //3rd digit
NUMA =(tlong/100)%10;                                         //2nd digit
Data_Send();
NUMA = 203;                                                 //send period
Data_Send();
NUMA = (tlong /10)%10 ;                                       //1st digit
Data_Send();
NUMA = (tlong /1)%10 ;                                        //1st digit
Data_Send();
}
//*****************************************************************************
//***this routine sends the IR array to the Arduino serial printer ************
//*****************************************************************************
void data_IR(void)                      //  need five digits change 200 code
{
for (counts=0; counts<(CellCnt);counts++)
{
tlong = ArrayIR[counts] ;                                   //show volts
NUMA= tlong /10000   ;
//      Data_Send ();                                      //don't show 999.99

NUMA = (tlong/1000)%10  ;
Data_Send ();
NUMA=(tlong/100)%10  ;
Data_Send ();

NUMA = 203;
Data_Send();                                                  // decimal
NUMA = (tlong /10)%10  ;
Data_Send ();
NUMA = (tlong /1)%10  ;
Data_Send ();
NUMA = 202;                                                 //send space
Data_Send();
}
}

void data_ArrayV(void)                  //This routine sends ArrayV to Arduino
{
for (counts=0; counts<(CellCnt);counts++)
{
tlong = ArrayV[counts] ;                                 //show volts
NUMA= tlong /1000   ;
Data_Send ();
NUMA = 203;                                              //send period
Data_Send();                                                // decimal
NUMA = (tlong/100)%10  ;
Data_Send ();
NUMA=(tlong/10)%10  ;
Data_Send ();
NUMA = (tlong /1)%10  ;
Data_Send ();
NUMA = 202;                                               //send space
Data_Send();
}
}

//*****************************************************************************
//***********Analog Digital Function.  Input, CPU, Output ArrayV **************
//*****************************************************************************
{
ArrayV[0] = 0x00;
ArrayV[1] = 0x00;
ArrayV[2] = 0x00;
ArrayV[3] = 0x00;
ArrayV[4] = 0x00;
ArrayV[5] = 0x00;
ArrayV[6] = 0x00;
ArrayV[7] = 0x00;
CellCnt = 0;
for(counts=0;counts<7;counts++)
{
porta = (porta_bat[CellCnt]);
delay_us(20);
portc = (portc_bat[Cellcnt]);
delay_ms(40)      ;                                //wait for warm up
for (counter=0; counter<10; counter++)            //Read voltage 10x times
{
}
mi_volt = (milli_readavg*0.1254);       //calibrate voltage range here
if (mi_volt <100)                                     //If zero volts, skip
{
ArrayV[CellCnt] = 0x00;                             //enter zero count
}
else
{
ArrayV[CellCnt] = mi_volt;                 //Store cell volts to array
CellCnt=CellCnt+1 ;
}
}
//if first cell is zero volts, clear display to all zeros
if (ArrayV[0]<200)                             //Test first Array for zero
{
ArrayV[1] = 0x00;                          //If zero, clear full Array
ArrayV[2] = 0x00;
ArrayV[3] = 0x00;
ArrayV[4] = 0x00;
ArrayV[5] = 0x00;
ArrayV[6] = 0x00;
}
else
{}
portb = 0x00;                               //turn off power resistors
delay_ms(2);                                         //2 ms mikroC bug
porta = 0x00;                                    //turn everything off
delay_ms(2);
portc = 0x00;
}
//****************************************************************************
//***LCD Function Input ArrayV  Output to LCD Display. ***********************
//****************************************************************************
void LCDFunction(void)
{
{
for (counts=0; counts<(CellCnt);counts++)
{
tlong = ArrayV [counts] ;                                 //show volts
ch = tlong /1000;
LCD_CHR(LCDRow[counts],LCDCol[counts],0x30+ch);            //4th digit
LCD_CHR_CP ('.');                                           // decimal
ch = (tlong/100)%10;
LCD_CHR_CP(0x30+ch);                                       //3rd digit
ch=(tlong/10)%10;                                          //2nd digit
LCD_CHR_CP(0x30+ch);
ch = (tlong /1)%10 ;                                       //1st digit
LCD_CHR_CP (0x30+ch);
}
delay_ms(50);
}
}
void Switch_push (void)  //This routine flashes push, and waits til sw is on
{
do
{
Lcd_out(1,10,"P");                             //display vertical "Push"
Lcd_out(2,10,"u");
Lcd_out(3,10,"s");
Lcd_out(4,10,"h");
delay_ms(100);
Lcd_out(1,10," ");                                    //flash on and off
Lcd_out(2,10," ");
Lcd_out(3,10," ");
Lcd_out(4,10," ");
delay_ms(100);
}
while(switch==0)       ;
delay_ms(100);
}
void Switch_release (void) //This routine flashes rls, and waits til sw is 0
{
do
{
Lcd_out(1,10,"R");                             //display vertical "Push"
Lcd_out(2,10,"l");
Lcd_out(3,10,"s");
Lcd_out(4,10," ");
delay_ms(100);
Lcd_out(1,10," ");                                    //flash on and off
Lcd_out(2,10," ");
Lcd_out(3,10," ");
Lcd_out(4,10," ");
delay_ms(100);
}
while(switch==1)     ;
}
//*****************************************************************************
//*****Battery Voltage Function with tlong input, LCD1,2 screen location*******
//*****************************************************************************
void Display_Data(void)
{
ch = tlong /10000;
LCD_CHR(LCD1,LCD2,0x30+ch);//4th digit
ch = (tlong/1000)%10;
LCD_CHR_CP(0x30+ch);                                        //3rd digit
LCD_CHR_CP ('.');                                            // decimal
ch=(tlong/100)%10;                                          //2nd digit
LCD_CHR_CP(0x30+ch);
ch = (tlong /10)%10 ;                                       //1st digit
LCD_CHR_CP (0x30+ch);                       //don't show to many digits
}
void Display_reset (void)
{
Lcd_Out(1,1,"#1");
Lcd_Out(2,1,"#2");
Lcd_Out(3,1,"#3");
Lcd_Out(4,1,"#4");
Lcd_Out(1,9,"V  #5");
Lcd_Out(2,9,"V  #6");
Lcd_Out(3,9,"V  #7");
Lcd_Out(4,9,"V  #7");
Lcd_Out(1,20,"V");
Lcd_Out(2,20,"V");
Lcd_Out(3,20,"V");
Lcd_Out(4,9,"V Bat");
Lcd_Out(4,20,"V");
}
//*****************************************************************************
//***********This is the main program ****************************t************
//*****************************************************************************
void main()
{
//Configure A/D converter
ANCON0 = 0X01 ;                           //configures channel 0 as A/D
ANCON1 = 0X00;                                //configure port B as all
ADCON1 = 0b00010000;                            // digital default A/D!
lcd_loc = 0x00 ;
// Configure I/O ports
trisb = 0b00000010  ;                   //make port b, bits 0, 1 inputs
trisc = 0b00000000;
porta = 0;
portb = 0;                                             //turn off loads
portc = 0;
Lcd_init();
Lcd_cmd(_LCD_CLEAR);
Lcd_cmd(_LCD_CURSOR_OFF);

//get 9 Volt battery value
tlong = tlong*10000;
tlong = tlong/2640;
LCD1 = 3;
LCD2 = 14;
Lcd_Out(1,1,"Battery IR Meter    ");             //show info on display
Lcd_Out(2,1,"9 Volt Batt < 6.7VDC");     //check for low 9 volt battery
Lcd_Out(3,1,"9 Volt Batt       V ");
Lcd_Out(4,1,"SW On Pwr Up set Mah");
Display_Data();
delay_ms(2000);
//set off low battery warning if below 6.70 Volts DC
if (tlong<6700)
{
low_batt:
Lcd_cmd(_LCD_CLEAR);                          //lock in low batt, don't
delay_ms(200);                                    //allow use of BattIR
Lcd_Out (4,1,"Change 9 VDC Battery");
delay_ms(200);
goto low_batt ;
}
else
{
}
//*********Program End Return Point *******************************************
reinit:
Lcd_init();
Lcd_cmd(_LCD_CLEAR);
Lcd_cmd(_LCD_CURSOR_OFF);
porta = 0;                //shut everything off
portb = 0;               //turn off loads
portc = 0;
//set up battery mah value for maximum current calculation
if (switch == 0)                               //do the switch routines
goto   Get_EEprom;
Mah_1000 = 0;                                             //Clear files
Mah_100  = 0;
Lcd_Out(1,1,"Battery IR Meter    ");             //show info on display
Lcd_Out(2,1,"Push Switch         ");
Lcd_Out(3,1,"Do 1000 Mah Batt    ");
Lcd_Out(4,1,"Batt Mah Cap        ");
LCD_CHR(4,15,0x30+Mah_1000);
LCD_CHR(4,16,0x30+Mah_100);
LCD_CHR(4,17,0x30);
LCD_CHR(4,18,0x30);
//This routine sets up the test batteries milliampere hour rating
delay_ms(400);
Lcd_Out(2,1,"Hold/Release Switch ");
if (Mah_1000>0x09)                            //if above 9, set to zero
Mah_1000 = 0;
LCD_CHR(4,15,0x30+Mah_1000);
delay_ms(400);
if(switch == 1)
{
Mah_1000 = Mah_1000+1;
}
//do 100 mah                                                //adjust 100's Mah
{
delay_ms(500);
Lcd_Out(3,1,"Do 100 Mah Batt        ");
Switch_pusha:
Lcd_Out(2,1,"Push Switch         ");
if (switch == 0)
goto   Switch_pusha;
Lcd_Out(2,1,"Hold/Release Switch ");

//      Lcd_Out(2,1,"Hold to 100's mah   ");                                                //if above 9, set to zero
if (Mah_100>0x09)
Mah_100 = 0;
LCD_CHR(4,16,0x30+Mah_100);
delay_ms(400);
if(switch == 1)
{
Mah_100 = Mah_100+1;
}
}
{
//Turn off test currents,
R2ohm = off;
delay_ms (10);
R5ohm = off;                                  //turn off power resistors
porta=0;
portb=0;
portc=0;
//Save mah values to eeprom
eeprom_write(0,mah_1000);
eeprom_write(01,mah_100);
delay_ms(100);
//Retrieve mah values from EEProm on normal start up here
Get_EEPRom:
//and verify existing mah settings
Lcd_Out(1,1,"Battery IR Meter    ");             //show info on display
Lcd_Out(2,1,"Check Test Settings ");
Lcd_Out(3,1,"Batt Cap      00 Mah");
Lcd_Out(4,1,"       Wait         ");
//***********************************************************************

Batt_Mah = (Mah_1000*10)+Mah_100;
LCD_CHR(3,13,0x30+Mah_1000);
LCD_CHR(3,14,0x30+Mah_100);
delay_ms (2500);                               //wait for battery reading
}
//this routine reads the individual cell voltages and displays them in a loop
{
restart:
Lcd_cmd(_LCD_CLEAR);
//individual LCD data inputs
do
{
Display_reset();                       //set up display for volts readouts
portb = 0b00000000;                        //no load battery measurement
delay_ms(30);                           //  wait for relays to stabilize
RestartA:
if (ArrayV[0]<500)                                  //Test first Array Volts
{                                               //test no battery connected
Lcd_cmd(_LCD_CLEAR);
Lcd_Out(3,1,"No Battery Connected");           //Clear Display to blanks
delay_ms(400);
Lcd_Out(3,1,"                    ");           //Clear Display to blanks
delay_ms(200);                                               //stay here
goto RestartA;
}
{
Display_reset();
//do program
//*********** Setup display for constants, do not change readouts
BattNL = ArrayV[0];                     //save battery no load for later
LCDFunction();                                 //display 7 channel volts

/////////////////////////////////////////////////////////////////
//      data_string();
tlong = ArrayV[0]+ArrayV[1]+ArrayV[2]
+ArrayV[3]+ArrayV[4]+ArrayV[5]+ArrayV[6];        //add up all cell volts
LCD1 = 4;
LCD2 = 15;
Display_data();                                  //print LiPo batt volts
delay_ms(1);
}
//Test for switch pushed for doing load tests   //hold here till button pushed
Lcd_out(1,10,"P");                             //display vertical "Push"
Lcd_out(2,10,"u");
Lcd_out(3,10,"s");
Lcd_out(4,10,"h");
delay_ms(400);
Lcd_out(1,10,"S");                                    //flash on and off
Lcd_out(2,10,"W");
Lcd_out(3,10," ");
Lcd_out(4,10," ");
delay_ms(200);
Lcd_out(1,10," ");                             //display vertical "Push"
Lcd_out(2,10," ");
Lcd_out(3,10," ");
Lcd_out(4,10," ");
delay_ms(200);

//   test if switch is pushed, if not, loop back to continuous voltage reads
}
while (switch == 0);

//*****************************************************************************
//******  send no load array to Arduino Nano *********************t************
//*****************************************************************************
NUMA = 209;                                       //send "Test Report #"
Data_Send();
NUMA = 201;
Data_Send();
delay_ms(100);
NUMA = 204;                                    //send "No Load Voltages"
Data_Send();
delay_ms(100);
NUMA = 201;                                                    //send CR
Data_Send();
delay_ms(100);
NUMA = 200;            //         send header file  Cell#1  Cell#2 . . .
Data_Send();
delay_ms(100);
data_ArrayV() ;              //routine reads ArrayV and sends to Arduino
NUMA = 201;                                                   //send CR
Data_Send();
}
Lcd_out(4,1,"For Fast Hold Switch");          //show how to fast forward
delay_ms(1000);
//Routine applies 5 Ohm load, reads all cell voltages and stores to Array5ohm
Lcd_cmd(_LCD_CLEAR);
Lcd_Out(1,1,"Test in Progress    ");
delay_ms(5);
Lcd_Out(2,1,"5 Ohm Load is ON    ");
R5ohm = 1 ;
delay_ms(700);                          //on time for 5 ohms - 2 seconds
portb = 0x00;                                          //turn off 5 ohms
Lcd_Out(2,1,"5 Ohm Load is OFF   ");
//*********** Record Volts for Low Current Test Amps *************************
Array5ohm[0] = ArrayV[0];                               //transfer array
Array5ohm[1] = ArrayV[1];
Array5ohm[2] = ArrayV[2];
Array5ohm[3] = ArrayV[3];
Array5ohm[4] = ArrayV[4];
Array5ohm[5] = ArrayV[5];
Array5ohm[6] = ArrayV[6];
Array5ohm[7] = ArrayV[7];
BattV5ohm = Array5ohm[0]+Array5ohm[1]+Array5ohm[2] //add up all voltages
+Array5ohm[3]+Array5ohm[4]+Array5ohm[5]+Array5ohm[6];
Lcd_Out(3,1,"2 Ohm Load is ON    ");
delay_ms(10);
R2ohm = 1;
delay_ms(200);                          //on time for 5 ohms - 2 seconds
portb = 0x00;                                          //turn off 5 ohms
Lcd_Out(3,1,"2 Ohm Load is OFF   ");
//*********** Record Volts for Low Current Test Amps *************************
Array2ohm[0] = ArrayV[0];                               //transfer array
Array2ohm[1] = ArrayV[1];
Array2ohm[2] = ArrayV[2];
Array2ohm[3] = ArrayV[3];
Array2ohm[4] = ArrayV[4];
Array2ohm[5] = ArrayV[5];
Array2ohm[6] = ArrayV[6];
Array2ohm[7] = ArrayV[7];
BattV2ohm = Array2ohm[0]+Array2ohm[1]+Array2ohm[2] //add up all voltages
+Array2ohm[3]+Array2ohm[4]+Array2ohm[5]+Array2ohm[6];
//Routine applies 1.428 Ohm Load, reads all cell voltages stores to Array2ohm
Lcd_Out(4,1,"1.4  Ohm Load is ON ");
delay_ms(5);
portb = 0b00110000;                      //turn on 5 and 2 ohm resistors
delay_ms(200);                        //on time for 5 ohms - 1.0 seconds
portb = 0x00;                                          //turn off 5 ohms
//*****************Record Volts For High Current Test Amps *******************
Array14ohm[0] = ArrayV[0];              //copy to Array14ohm for IR calc
Array14ohm[1] = ArrayV[1];
Array14ohm[2] = ArrayV[2];
Array14ohm[3] = ArrayV[3];
Array14ohm[4] = ArrayV[4];
Array14ohm[5] = ArrayV[5];
Array14ohm[6] = ArrayV[6];
Array14ohm[7] = ArrayV[7];
BattV14ohm = Array14ohm[0]+Array14ohm[1]+Array14ohm[2]
+Array14ohm[3]+Array14ohm[4]+Array14ohm[5]+Array14ohm[6];
delay_ms(100);
//*****************************************************************************
//*****if no voltage sag, give warning about connecting red/black wires********
//*****************************************************************************
if(Array5ohm[0]-Array14ohm[0]<5)             //check for less than 5 mv sag
{
Lcd_cmd(_LCD_CLEAR);
Lcd_out(3,1,"BattIR meter        ");
Lcd_out(2,1,"Red and Black Wire  ");
Lcd_out(4,1,"                    ");
delay_ms(5000);
goto restart;
}
{
goto show_result;
}
{
Lcd_cmd(_LCD_CLEAR);
Lcd_out(3,1,"BattIR meter        ");
Lcd_out(2,1,"Red and Black Wire  ");
Lcd_out(4,1,"                    ");
delay_ms(5000);
goto restart;
}
{
goto show_result;
}
//*****************************************************************************
//if switch is closed at this time, skip all readings and go to IR readouts ***
//*****************************************************************************
show_result:
if(switch==1)
goto do_IR;
//else, show results volts and amps at 5, 2 and 1.4 Ohms
Lcd_cmd(_LCD_CLEAR);
Lcd_out(1,1,"Results             ");
Lcd_out(2,1,"LoAmps      V      A");
Lcd_out(3,1,"MdAmps      V      A");
Lcd_out(4,1,"HiAmps      V      A");
//do pack voltage at low Amps and Hi Amps
tlong = BattV5ohm;                                  //show low amp Volts
ch = tlong/10000;
LCD1 = 2;                                  // LCD1&2 are print locations
LCD2 = 8;
Display_data();
tlong = BattV2ohm;                                 //show high amp volts
ch = tlong/10000;
LCD1=3;
LCD2=8;
Display_data();
tlong = BattV14ohm;                                //show high amp volts
ch = tlong/10000;
LCD1=4;
LCD2=8;
Display_data();

tlong=battV5ohm/5;                           //show low amp test current
ch = tlong/10000;
LCD1 = 2;
LCD2 = 15;
Display_data();

tlong=battV2ohm/2;                           //show low amp test current
ch = tlong/10000;
LCD1 = 3;
LCD2 = 15;
Display_data();

tlong=battV14ohm/1.428   ;                  //show high amp test current
ch = tlong/10000;
LCD1 = 4;
LCD2 = 15;
Display_data();                                 //hold for key push here
delay_ms(100);
do
{
LCD_Out(1,9,"Push Switch");
delay_ms(100);
LCD_Out (1,9,"           ");
delay_ms(100);
}
while (switch == 0);
Lcd_Out(1,1,"#1      V  #5      V");
Lcd_Out(2,1,"#2      V  #6      V");
Lcd_Out(3,1,"#3      V  #7      V");
Lcd_Out(4,1,"#4      V VoltLowAmp");

ArrayV[0] = Array5ohm[0];               //copy to Array14ohm for IR calc
ArrayV[1] = Array5ohm[1];
ArrayV[2] = Array5ohm[2];
ArrayV[3] = Array5ohm[3];
ArrayV[4] = Array5ohm[4];
ArrayV[5] = Array5ohm[5];
ArrayV[6] = Array5ohm[6];
ArrayV[7] = Array5ohm[7];
LCDFunction();
//send low current array info to Arduino
NUMA = 205;                                      //send "Low Amp Volts"
Data_Send();
delay_ms(100);
delay_ms(100);
NUMA = 201;                                                   //send CR
Data_Send();
delay_ms(100);
data_ArrayV() ;
NUMA = 201;                                                   //send CR
Data_Send();

Switch_release();
Switch_push ();
//show results at 2 ohms
Lcd_Out(1,1,"#1      V  #5      V");
Lcd_Out(2,1,"#2      V  #6      V");
Lcd_Out(3,1,"#3      V  #7      V");
Lcd_Out(4,1,"#4      V VoltMidAmp");

ArrayV[0] = Array2ohm[0];               //copy to Array14ohm for IR calc
ArrayV[1] = Array2ohm[1];
ArrayV[2] = Array2ohm[2];
ArrayV[3] = Array2ohm[3];
ArrayV[4] = Array2ohm[4];
ArrayV[5] = Array2ohm[5];
ArrayV[6] = Array2ohm[6];
ArrayV[7] = Array2ohm[7];
LCDFunction();                          //display results to LCD display
//send medium current array info to Arduino
NUMA = 206;                                //send "Medium Amp Voltages"
Data_Send();
NUMA = 201;                                                   //send CR
Data_Send();
delay_ms(100);
data_ArrayV() ;
NUMA = 201;                                                   //send CR
Data_Send();

Switch_release();
Switch_push();
delay_ms(200);
Lcd_Out(1,1,"#1      V  #5      V");
Lcd_Out(2,1,"#2      V  #6      V");
Lcd_Out(3,1,"#3      V  #7      V");
Lcd_Out(4,1,"#4      V VoltsHiAmp");
ArrayV[0]=  Array14ohm[0]  ;            //copy to Array14ohm for IR calc
ArrayV[1]=  Array14ohm[1]  ;
ArrayV[2]=  Array14ohm[2]  ;
ArrayV[3]=  Array14ohm[3]  ;
ArrayV[4]=  Array14ohm[4]  ;
ArrayV[5]=  Array14ohm[5]   ;
ArrayV[6]=  Array14ohm[6]  ;
ArrayV[7]=  Array14ohm[7]  ;
LCDFunction();
//send high current array info to Arduino
NUMA = 207;                                    //send "No Load Voltages"
Data_Send();
delay_ms(100);
NUMA = 201;                                                    //send CR
Data_Send();
delay_ms(100);
data_arrayV() ;
NUMA = 201;                                                    //send CR
Data_Send();
Switch_release();
Switch_push();

Do_ir:

// data_string();
//do IR tests
Lcd_Out(1,1,"1ir        5ir      ");
Lcd_Out(2,1,"2ir        6ir      ");
Lcd_Out(3,1,"3ir        7ir      ");
Lcd_Out(4,1,"4ir       Milli-Ohms");
//calculate IR where IR = (Vlow-Vhi)/(AmpsHi-AmpsLo)
ArrayIR [0] = 0;                     //clear array for less than 7 cells
ArrayIR [1] = 0;
ArrayIR [2] = 0;
ArrayIR [3] = 0;
ArrayIR [4] = 0;
ArrayIR [5] = 0;
ArrayIR [6] = 0;
ArrayIR [7] = 0;
Tot_IR      = 0;                                  //clear total IR value
//do calculations
for (counts=0; counts<(CellCnt);counts++)
{
Test_Amps = (BattV5ohm/5)-(BattV14ohm/1.428);
tlong  = (Array5ohm[counts]-Array14ohm[counts]) ;
tlong = tlong*100000;                     //adjust ranges on calculation
tlong = tlong/Test_Amps;
ArrayIR [counts] = tlong;
Tot_IR = Tot_IR + tlong;                             //add up total IR's
ch = tlong/10000 ;                                              //9xx.xx
LCD_CHR(LCDRow[counts],LCDIRColIR[counts],0x30+ch);          //4th digit
ch =  (tlong/1000)%10;
LCD_CHR_CP(0X30+ch);
ch = (tlong/100)%10;
LCD_CHR_CP(0x30+ch);                                         //3rd digit
LCD_CHR_CP ('.');                                             // decimal
ch=(tlong/10)%10;
LCD_CHR_CP(0x30+ch);                                         //2nd digit
ch = (tlong /1)%10 ;
LCD_CHR_CP (0x30+ch);                                        //1st digit
}
//send IR array info to Arduino
NUMA = 208;                                           //send "IR Values"
Data_Send();
delay_ms(100);
NUMA = 201;                                                    //send CR
Data_Send();
delay_ms(100);

data_IR() ;                                   //send IR array to Arduino
NUMA = 201;                                                    //send CR
Data_Send();
NUMA = 201;                                                    //send CR
Data_Send();

delay_ms(100);
Switch_release();
Lcd_Out(4,11,"T-IR ");
tlong = Tot_IR;

ch = tlong /10000;                                   //adjust full range
LCD_CHR(4,16,0x30+ch);                                       //4th digit
ch = (tlong/1000)%10;
LCD_CHR_CP(0x30+ch);                                         //3rd digit

ch=(tlong/100)%10;                                           //2nd digit
LCD_CHR_CP(0x30+ch);
LCD_CHR_CP ('.');                                            // decimal
ch = (tlong /10)%10 ;
LCD_CHR_CP (0x30+ch);                                        //1st digit
Switch_push();
delay_ms(100);
Lcd_Out(1,1,"Max Current is     A");
Lcd_Out(2,1,"Reference RCGroups  ");
Lcd_Out(3,1,"Forsyth,Julian,Giles");
Lcd_Out(4,1,"                    ");
//this routine finds the maximum IR value in the IR Array
for (counts = 0; counts < 7; counts ++)
{
if (ArrayIR[0]<ArrayIR[counts])
ArrayIR[0] = ArrayIR[counts]    ;
}
Max_IR = ArrayIR[0];                             //calculate IR for cell
Calc = 60000*Batt_mah;
tlong = sqrt (calc/Max_IR)    ;              //do square root on results
ch = tlong /100;
LCD_CHR(1,16,0x30+ch); //4th digit
ch = (tlong/10)%10;
LCD_CHR_CP(0x30+ch);                                         //3rd digit
ch=(tlong/1)%10;                                             //2nd digit
LCD_CHR_CP(0x30+ch);
//1st digit
delay_ms(100);
do
{    Lcd_out(4,1,"    Push Switch     ");
delay_ms(100);
Lcd_out(4,1,"                    ");
delay_ms(100);
}
while(switch==0)   ;
do
{
Lcd_out(4,1,"   Release Switch   ");
delay_ms(100);
Lcd_out(4,1,"                    ");
delay_ms(100);
}
while(switch==1)         ;
goto restart;
}

//end of program```
Dec 23, 2018, 11:09 PM
Registered User

# Here is the Arduino Nano Sketch program

The following is the Arduino Sketch program that interfaces between the BattIR meter and the PC USB terminal. The USB reader is the "Termite" software, available for free in the Internet.

Also shown is the interconnection between the Arduino Nano and the BattIR meter. It would have been great if the built in communications for the MicroChip PicChip and the Arduino Nano could have been used. Problem was that would call for a new circuit board for the BattIR meter.

Code:
```//pin 12 is data, 11 is clock
int long counter = 0;
unsigned int Cntr = 0;
unsigned int  cycle = 0;
int rotate = 0;
unsigned int data = 0;
unsigned int test_report = 0;
#include <EEPROM.h>
void setup() {
//  Serial.begin(9600);
Serial.begin(9600);
pinMode(12,INPUT) ;
pinMode (11,INPUT);
pinMode (10,OUTPUT);
pinMode (9, OUTPUT);

}

//this routine centers the program at the bit point
void getbit()
{
do
while (Cntr == HIGH);

do
while (Cntr == LOW);
//     delay(0.5);
}

//this routine gets one byte from BattIR meter and save in "data"
void getbyte()
{
digitalWrite(10,1);
//get start of serial data string
do
counter = pulseIn(11,1);
while (counter<800);
digitalWrite (10,0);
data = 0;            //clear data variable

//get data one bit at a time

getbit();
delayMicroseconds(40);
digitalWrite(9,1);
digitalWrite(9,0);
if (Cntr == HIGH)
bitWrite (data,7,1);

getbit();
delayMicroseconds(40);
if (Cntr == HIGH)
bitWrite (data,6,1);

getbit();
delayMicroseconds(40);
if (Cntr == HIGH)
bitWrite (data,5,1);

getbit();
delayMicroseconds(40);
if (Cntr == HIGH)
bitWrite (data,4,1);

getbit();
delayMicroseconds(40);
if (Cntr == HIGH)
bitWrite (data,3,1);

getbit();
delayMicroseconds(40);
if (Cntr == HIGH)
bitWrite (data,2,1);

getbit();
delayMicroseconds(40);
if (Cntr == HIGH)
bitWrite (data,1,1);

getbit();
delayMicroseconds(40);
if (Cntr == HIGH)
bitWrite (data,0,1);
}
void loop()
{

getbyte();
if (data == 200)
{

Serial.println ("Cell#1  Cell#2  Cell#3  Cell#4  Cell#5  Cell#6  Cell#7");
}

else
if (data == 201) //carriage return
{
Serial.println(" ");
}
else
if (data == 204)
{
}

else
if (data == 205) //Low Amp voltage readings
{
Serial.print("Low Amp Voltage");
}

else
if (data == 206) //Medium amp voltage readings
{
Serial.print("Medium Amp Voltage");
}

else
if (data == 207) //low amp voltage readings
{
Serial.print("High Amp Voltage");
}

else
if (data == 208) //cell IR values
{
Serial.print("Cell IR Values");
}

else
if (data == 203) //carriage return
{
Serial.print(".");
}
else
if (data == 209) //carriage return
{
Serial.print("Test Report #  ");
Serial.print (test_report);
test_report = test_report +1;
EEPROM.write (0,test_report);
}

else
if (data == 202) //print space
{
Serial.print ("   ");  //adjust spacing here to line up on USB reader
}

else
{
Serial.print(data);
}

}```
Last edited by vollrathd; Jan 08, 2019 at 08:16 PM. Reason: Added diode to Arduino Nano interconnection schematic
Dec 25, 2018, 08:33 PM
Registered User

# Update

Right now I'm printing out a 3D printer case for this project, using PLA filament. Hopefully the heat generated by the power resistors in this project won't affect the easily melted PLA case. We'll see.

In addition, I ran into intermittent loss of communication between the Arduino Nano and the PC. Took awhile to find out that you can't simply unplug the Arduino USB cable to the PC without first closing the "Termite" communication software. If the Termite software is first closed, then the USB cable is pulled, all is well.

Photos of the BattIR case, the Arduino installation on the PCB will follow in a few hours.
Dec 27, 2018, 01:11 AM
Registered User

# 3D Printed Project Enclosure

This project enclosure was printed on a WanHao i3 Pro Printer using PLA filament. The lid took six hours, the case took 23 hours! The project box lid has an Arduino Nano circuit that allows plugging the BattIR meter into your PC to download test results. I'll run a video on that next day or three.

### Images

Last edited by vollrathd; Dec 27, 2018 at 01:17 AM.
Dec 28, 2018, 10:06 PM
Registered User

# It's Done!

The attached JPG's show the 3D printed enclosure for the BattIR project, along with the Arduino Nano holder. Note the power resistors are mounted on pieces of wood, isolated from the 3D box. The PLA filament is very susceptible to any sort of heat from items like power resistors. This stuff functions like a stick of butter if it gets much more than 130 F. There are ventilation slots in the back of the enclosure.

Note the USB cable in the front of the BattIR meter that allows the user to download all of the test results directly through the USB cable to a USB reader, available free through the internet. The one I've been using is the "Termite" software. All of the test results, either just the open circuit voltage and IR values, or all of the voltage measurements on the three different load tests, plus the IR values can be downloaded, and dumped into Excel, or even MS Word.

### Images

Jan 08, 2019, 12:41 AM
Registered User

# Updated 3D Printed BattIR Meter Case

Attached are a few photos of the updated 3D printed case for the BattIR meter. Note the use of pre-threaded nylon spacers located on the case along with the stand-offs for the front panel aluminum heat sink for the power resistors.

That aluminum panel heat sink was added due to the possibility of the 3D printed PLA filament getting soft at higher temperatures. With that aluminum panel, three quick tests on a 6S LiPo battery pack resulted in perhaps a 10 degree F temperature rise of that aluminum panel.

The Tinkercad 3D files for the BattIR case will be added to the www.github.com site for this project in the next day or two.