/* Lithium battery tester Tests how the internal resistance of a small 3.6 V lithium battery varies over time when loaded. Written by Per Magnusson, http://www.axotron.se v 0.2 2015-07-06 This program is public domain. */ static const float loadCur = 5.0e-3; // Target load current static const unsigned int switchPeriod = 1000; // On/off time static const byte doPulse = 0; // Whether to pulse the current static const float Rtop = 1817; // Top resistor of divider, ohms static const float Rbot = 8170; // Bottom resistor of divider, ohms static const float Gdiv = 1/(Rtop+Rbot); // Voltage divider conductance static const float Rs = 32.8; // Current sense resistor, ohms static const float Rb = 995; // Base resistor, ohms static const float Vref = 3.28; // ADC reference voltage, volts static const int ADCbits = 12; static const int DACbits = 12; static const float voltPerADC = Vref/((1< detectLimit) { // A battery was connected testBat = true; // Proceed to test it } } else if(state == sWaitBat) { // We are waiting for a battery to be disconnected if(batteryVoltage < detectLimit) { // A battery was disconnected Serial.println("\nWaiting for a battery to be connected..."); delay(1000); // Delay to not react on glitches while the battery is being disconnected state = sWaitNoBat; } } if(!testBat) { // Not in a situation that a battery should be tested return; } // Test the battery Serial.println("Battery connected, waiting for connection to stabilize."); delay(1000); // Wait for the connection to stabilize readBattery(); if(batteryVoltage < detectLimit) { // The battery is gone, it was just a glitch state = sWaitNoBat; Serial.println("Battery removed, aborting."); Serial.println("Waiting for a battery to be connected..."); return; } digitalWrite(ledPin, HIGH); // turn LED on Serial.println("Testing battery."); voltNoLoad = batteryVoltage; curNoLoad = voltNoLoad*Gdiv; // "No load" current Serial.println(""); Serial.print("Unloaded voltage: "); Serial.print(voltNoLoad); Serial.print(" V (current = "); Serial.print(curNoLoad*1000); Serial.println(" mA)"); dacVal = 0.66*DACperVolt; // Base drive starting value, 0.66 V, low current analogWrite(dacPin, dacVal); // Drive the base of the transistor readBattery(); // Loop to adjust DAC current for(int ii=0; ii= (1< switchPeriod)) { onOffState = 1-onOffState; lastSwitchTime = elapsedTime; } if(onOffState) { analogWrite(dacPin, dacVal); // Drive the base of the transistor } else { analogWrite(dacPin, 0); // Turn off the base drive of the transistor } readBattery(); if(batteryVoltage < detectLimit) { // The voltage is too low (maybe the battery was removed), exit from loop Serial.print("Warning: Below minimum battery voltage ("); Serial.print(batteryVoltage); Serial.println(" V), exiting"); break; } if((batteryCurrent - curNoLoad) > 0) { res = (voltNoLoad - batteryVoltage)/(batteryCurrent - curNoLoad); // Calculate internal resistance } else { res = 0; // Avoid dividing by zero } // Print result Serial.print(elapsedTime); Serial.print("\t"); Serial.print(batteryVoltage, 4); Serial.print("\t"); Serial.print(batteryCurrent*1000); Serial.print("\t"); Serial.print(res); Serial.print("\t"); Serial.println(dacVal); if(onOffState) { // Make a small adjustment to stay close to the target current if(batteryCurrent < loadCur) { dacVal++; } else { dacVal--; } } } // Cleanup after loop analogWrite(dacPin, 0); // Stop the battery current drain digitalWrite(ledPin, LOW); // turn LED off state = sWaitBat; Serial.println("Done"); }