PNI / Mbed 2 deprecated BatteryCapacityTest_Pulsed

Dependencies:   SDFileSystem mbed

Committer:
JoeMiller
Date:
Wed Sep 20 23:18:03 2017 +0000
Revision:
5:f5ac3e216653
Parent:
4:0d79ec30dd60
Version 2 ;     1) can now withstand a power line loss and resume properly when restored.;     2) now uses a calibration file on the SD card for storing coefficients.;         Macro statements are no longer used. ;     3) The program will enter calib

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JoeMiller 4:0d79ec30dd60 1 /* PULSED DISCHARGE BATTERY CAPACITY MEASUREMENT Version 2
JoeMiller 0:197cfa57c3c7 2
JoeMiller 0:197cfa57c3c7 3 Note: The design intent was to calibrate each board rather than designing
JoeMiller 0:197cfa57c3c7 4 and assembling precision analog circuits for each shield-board.
JoeMiller 0:197cfa57c3c7 5
JoeMiller 5:f5ac3e216653 6 Version 2
JoeMiller 5:f5ac3e216653 7 1) can now withstand a power line loss and resume properly when restored.
JoeMiller 5:f5ac3e216653 8 2) now uses a calibration file on the SD card for storing coefficients.
JoeMiller 5:f5ac3e216653 9 Macro statements are no longer used.
JoeMiller 5:f5ac3e216653 10 3) The program will enter calibration mode if the calibration file does not
JoeMiller 5:f5ac3e216653 11 exist and when complete will write the calibration file to the SD card.
JoeMiller 5:f5ac3e216653 12 No longer need to compile twice (once for cal, a 2nd for discharge test).
JoeMiller 4:0d79ec30dd60 13
JoeMiller 4:0d79ec30dd60 14 Calibration ASSUMES the MOSFET gain temperature compensation process included in this
JoeMiller 2:29264f52a28e 15 code is only good for temperatures near room temperatures. Keep this hardware away from
JoeMiller 4:0d79ec30dd60 16 extreme temperature changes - The battery (DUT) can go into temp chamber
JoeMiller 2:29264f52a28e 17
JoeMiller 0:197cfa57c3c7 18 See ENG-1492 for more details and results
JoeMiller 0:197cfa57c3c7 19
JoeMiller 0:197cfa57c3c7 20 */
JoeMiller 0:197cfa57c3c7 21
JoeMiller 0:197cfa57c3c7 22
JoeMiller 0:197cfa57c3c7 23 #include "mbed.h"
JoeMiller 0:197cfa57c3c7 24 #include "SDFileSystem.h"
JoeMiller 0:197cfa57c3c7 25
JoeMiller 0:197cfa57c3c7 26 Serial pc(SERIAL_TX, SERIAL_RX);
JoeMiller 0:197cfa57c3c7 27 AnalogOut DAC_Out(PA_4); // Connected to Gate of MOSFET
JoeMiller 0:197cfa57c3c7 28 AnalogIn VRin(PA_0); // for Current Measurement
JoeMiller 0:197cfa57c3c7 29 AnalogIn VBin(PA_1); // To measure battery Voltage
JoeMiller 0:197cfa57c3c7 30 DigitalOut LED(D4); // Activity indicator
JoeMiller 0:197cfa57c3c7 31 SDFileSystem sd(D11, D12, D13, D10, "sd"); // the pinout on the mbed Cool Components workshop board
JoeMiller 0:197cfa57c3c7 32
JoeMiller 0:197cfa57c3c7 33
JoeMiller 0:197cfa57c3c7 34
JoeMiller 0:197cfa57c3c7 35
JoeMiller 0:197cfa57c3c7 36 // Parameters
JoeMiller 0:197cfa57c3c7 37 #define PULSEWIDTH 0.099f
JoeMiller 0:197cfa57c3c7 38 #define INTERVAL 0.599f
JoeMiller 0:197cfa57c3c7 39 #define SLEWRATE 100 //10 is good for active testing, 100 for debugging
JoeMiller 0:197cfa57c3c7 40 #define VBATTERY_MIN (3.00f)
JoeMiller 0:197cfa57c3c7 41 #define TERMINATION_CURRENT (0.067f)
JoeMiller 0:197cfa57c3c7 42 #define HYST (0.0001f) // temp comp hysteresis
JoeMiller 0:197cfa57c3c7 43 #define GAIN 10000 // temp comp gain
JoeMiller 0:197cfa57c3c7 44 char serial_inchar,waiting;
JoeMiller 0:197cfa57c3c7 45
JoeMiller 0:197cfa57c3c7 46 void OnSerial(void) // serial port interrupt used in calibration mode
JoeMiller 0:197cfa57c3c7 47 {
JoeMiller 0:197cfa57c3c7 48 serial_inchar = pc.getc();
JoeMiller 0:197cfa57c3c7 49 waiting = 0;
JoeMiller 0:197cfa57c3c7 50 printf("%c:%d",serial_inchar,serial_inchar);
JoeMiller 0:197cfa57c3c7 51 }
JoeMiller 0:197cfa57c3c7 52
JoeMiller 0:197cfa57c3c7 53
JoeMiller 0:197cfa57c3c7 54 int main() {
JoeMiller 0:197cfa57c3c7 55 float I,V,I_Target;
JoeMiller 4:0d79ec30dd60 56 int DAC_Value = 35950;
JoeMiller 0:197cfa57c3c7 57 uint32_t count;
JoeMiller 4:0d79ec30dd60 58 float i_Cal,v_Cal;
JoeMiller 4:0d79ec30dd60 59 uint8_t CalibrationMode = 0;
JoeMiller 4:0d79ec30dd60 60
JoeMiller 4:0d79ec30dd60 61 sd.disk_initialize();
JoeMiller 0:197cfa57c3c7 62
JoeMiller 0:197cfa57c3c7 63 DAC_Out.write_u16(0);
JoeMiller 0:197cfa57c3c7 64
JoeMiller 0:197cfa57c3c7 65 pc.baud(115200);
JoeMiller 0:197cfa57c3c7 66 pc.attach(&OnSerial);
JoeMiller 0:197cfa57c3c7 67 LED = 0;
JoeMiller 0:197cfa57c3c7 68 waiting = 1;
JoeMiller 0:197cfa57c3c7 69
JoeMiller 4:0d79ec30dd60 70 printf("Pulsed Battery Discharger\n\r");
JoeMiller 0:197cfa57c3c7 71
JoeMiller 4:0d79ec30dd60 72 // GET Calibration Coefficients and Constants from SD card
JoeMiller 4:0d79ec30dd60 73 printf("Reading Calibration Coefficients\n\r");
JoeMiller 4:0d79ec30dd60 74 FILE *fc = fopen("/sd/calibrationCoefficients.txt", "r");
JoeMiller 4:0d79ec30dd60 75 if(fc == NULL) {
JoeMiller 4:0d79ec30dd60 76 // try one more time
JoeMiller 4:0d79ec30dd60 77 wait(1.0);
JoeMiller 4:0d79ec30dd60 78 printf("\n\rTying to read SD a second time..\n\r");
JoeMiller 4:0d79ec30dd60 79 fclose(fc);
JoeMiller 4:0d79ec30dd60 80 wait(1.0);
JoeMiller 4:0d79ec30dd60 81 FILE *fc = fopen("/sd/calibrationCoefficients.txt", "r");
JoeMiller 4:0d79ec30dd60 82 if(fc == NULL) {
JoeMiller 4:0d79ec30dd60 83 waiting = 1;
JoeMiller 4:0d79ec30dd60 84 printf("\n\rFile does not exist. Enter Calibration Mode(Y/N)?\n\r");
JoeMiller 4:0d79ec30dd60 85 while (waiting == 1) {
JoeMiller 4:0d79ec30dd60 86 wait(0.05);
JoeMiller 4:0d79ec30dd60 87 }
JoeMiller 4:0d79ec30dd60 88 if (serial_inchar == 'y' || serial_inchar == 'Y') {
JoeMiller 4:0d79ec30dd60 89 CalibrationMode = 1;
JoeMiller 4:0d79ec30dd60 90 }
JoeMiller 4:0d79ec30dd60 91 }
JoeMiller 4:0d79ec30dd60 92 }
JoeMiller 4:0d79ec30dd60 93
JoeMiller 4:0d79ec30dd60 94 if (CalibrationMode == 0) {
JoeMiller 4:0d79ec30dd60 95 wait(1.0);
JoeMiller 4:0d79ec30dd60 96 fscanf(fc,"DAC100MA %d\n", &DAC_Value);
JoeMiller 4:0d79ec30dd60 97 fscanf(fc,"I_SCALE %f\n", &i_Cal);
JoeMiller 4:0d79ec30dd60 98 fscanf(fc,"V_SCALE %f\n", &v_Cal);
JoeMiller 4:0d79ec30dd60 99 printf("Dac Cal: %d, i_Cal: %f, v_Cal: %f\n\r",DAC_Value,i_Cal,v_Cal);
JoeMiller 4:0d79ec30dd60 100 if(DAC_Value == 0 || i_Cal == 0 || v_Cal == 0) {
JoeMiller 4:0d79ec30dd60 101 error("calibration file content error (2nd try)\n");
JoeMiller 4:0d79ec30dd60 102 }
JoeMiller 0:197cfa57c3c7 103 }
JoeMiller 0:197cfa57c3c7 104
JoeMiller 4:0d79ec30dd60 105 fclose(fc);
JoeMiller 0:197cfa57c3c7 106
JoeMiller 4:0d79ec30dd60 107 printf("Using DAC_Value of:%d\n\r",DAC_Value);
JoeMiller 4:0d79ec30dd60 108
JoeMiller 4:0d79ec30dd60 109
JoeMiller 4:0d79ec30dd60 110 // Normal Battery Discharge Loop
JoeMiller 4:0d79ec30dd60 111 if (CalibrationMode == 0) {
JoeMiller 4:0d79ec30dd60 112 FILE *fp = fopen("/sd/BatteryLog.txt", "a");
JoeMiller 4:0d79ec30dd60 113 if(fp == NULL) {
JoeMiller 4:0d79ec30dd60 114 error("Could not open Log file for write\n");
JoeMiller 4:0d79ec30dd60 115 }
JoeMiller 4:0d79ec30dd60 116
JoeMiller 4:0d79ec30dd60 117 fprintf(fp, "I,V,count\n");
JoeMiller 4:0d79ec30dd60 118 printf("\n\rBattery Discharge Mode\n\r");
JoeMiller 4:0d79ec30dd60 119 I_Target = 0.100;
JoeMiller 4:0d79ec30dd60 120 do {
JoeMiller 4:0d79ec30dd60 121
JoeMiller 4:0d79ec30dd60 122 LED = 0;
JoeMiller 4:0d79ec30dd60 123 DAC_Out.write_u16(0);
JoeMiller 4:0d79ec30dd60 124 wait(INTERVAL);
JoeMiller 4:0d79ec30dd60 125 LED = 1;
JoeMiller 4:0d79ec30dd60 126 DAC_Out.write_u16(DAC_Value);
JoeMiller 4:0d79ec30dd60 127 wait(PULSEWIDTH);
JoeMiller 4:0d79ec30dd60 128 I = VRin.read()* i_Cal;
JoeMiller 4:0d79ec30dd60 129 V = VBin.read()* v_Cal;
JoeMiller 4:0d79ec30dd60 130
JoeMiller 4:0d79ec30dd60 131 fprintf(fp,"%1.3f,%1.2f,%d\n",I,V,++count);
JoeMiller 4:0d79ec30dd60 132 //printf("%1.3f,%1.2f,%d\n\r",I,V,count);
JoeMiller 4:0d79ec30dd60 133
JoeMiller 4:0d79ec30dd60 134
JoeMiller 4:0d79ec30dd60 135 // MOSFET Gain temperature compensation
JoeMiller 4:0d79ec30dd60 136 if (I < (I_Target - HYST)) {
JoeMiller 4:0d79ec30dd60 137 DAC_Value += (I_Target - I)*GAIN;
JoeMiller 4:0d79ec30dd60 138 }
JoeMiller 4:0d79ec30dd60 139 else if ( I > (I_Target + HYST)) {
JoeMiller 4:0d79ec30dd60 140 DAC_Value -= (I - I_Target)*GAIN;
JoeMiller 4:0d79ec30dd60 141 }
JoeMiller 4:0d79ec30dd60 142
JoeMiller 4:0d79ec30dd60 143
JoeMiller 4:0d79ec30dd60 144 // If battery Voltage goes below BATTERY_MIN then reduce current
JoeMiller 4:0d79ec30dd60 145 if (V < VBATTERY_MIN) {
JoeMiller 4:0d79ec30dd60 146 if (I_Target > ( TERMINATION_CURRENT - (2.0*HYST))) {
JoeMiller 4:0d79ec30dd60 147 I_Target -= 0.001;
JoeMiller 4:0d79ec30dd60 148 }
JoeMiller 4:0d79ec30dd60 149 }
JoeMiller 4:0d79ec30dd60 150
JoeMiller 4:0d79ec30dd60 151 } while (I > TERMINATION_CURRENT && waiting);
JoeMiller 4:0d79ec30dd60 152
JoeMiller 4:0d79ec30dd60 153 fclose(fp);
JoeMiller 0:197cfa57c3c7 154 DAC_Out.write_u16(0);
JoeMiller 4:0d79ec30dd60 155 printf("Done!\n\r");
JoeMiller 4:0d79ec30dd60 156 LED = 0;
JoeMiller 4:0d79ec30dd60 157
JoeMiller 4:0d79ec30dd60 158 }
JoeMiller 0:197cfa57c3c7 159
JoeMiller 0:197cfa57c3c7 160
JoeMiller 0:197cfa57c3c7 161
JoeMiller 4:0d79ec30dd60 162 else {
JoeMiller 4:0d79ec30dd60 163 //Perform Board Calibration
JoeMiller 4:0d79ec30dd60 164 uint8_t doPulse;
JoeMiller 0:197cfa57c3c7 165
JoeMiller 4:0d79ec30dd60 166 printf("Creating Calibration Coefficients file on SD card\n\r");
JoeMiller 4:0d79ec30dd60 167 FILE *fc = fopen("/sd/calibrationCoefficients.txt", "w");
JoeMiller 4:0d79ec30dd60 168 if(fc == NULL) {
JoeMiller 4:0d79ec30dd60 169 error("cannot create calibration file on SD card\n\r");
JoeMiller 0:197cfa57c3c7 170 }
JoeMiller 0:197cfa57c3c7 171
JoeMiller 0:197cfa57c3c7 172
JoeMiller 4:0d79ec30dd60 173 while (1) {
JoeMiller 4:0d79ec30dd60 174 printf("\n\rCalibration Mode\n\r");
JoeMiller 4:0d79ec30dd60 175 waiting = 1;
JoeMiller 4:0d79ec30dd60 176 while (pc.readable()) { // flush buffer
JoeMiller 4:0d79ec30dd60 177 serial_inchar = pc.getc();
JoeMiller 4:0d79ec30dd60 178 }
JoeMiller 4:0d79ec30dd60 179 printf("Set Vin to 3.20V then [press any key]\n\r");
JoeMiller 4:0d79ec30dd60 180 while(waiting == 1){
JoeMiller 4:0d79ec30dd60 181 wait(0.05);
JoeMiller 2:29264f52a28e 182 }
JoeMiller 4:0d79ec30dd60 183 printf("\n\rOK\n\r");
JoeMiller 4:0d79ec30dd60 184 wait(0.5);
JoeMiller 4:0d79ec30dd60 185 V = VBin.read();
JoeMiller 4:0d79ec30dd60 186
JoeMiller 4:0d79ec30dd60 187 printf("Set Vin > 3.20V and < 3.60V\n\r");
JoeMiller 4:0d79ec30dd60 188 printf("Press keys to adjust Current exactly to 100mA\n\r");
JoeMiller 4:0d79ec30dd60 189 printf("Use +, -, *, / to adjust, q to end\n\r");
JoeMiller 4:0d79ec30dd60 190
JoeMiller 4:0d79ec30dd60 191
JoeMiller 4:0d79ec30dd60 192 waiting = 1;
JoeMiller 4:0d79ec30dd60 193 do {
JoeMiller 4:0d79ec30dd60 194 DAC_Out.write_u16(0);
JoeMiller 4:0d79ec30dd60 195 while(waiting){wait(0.01);}
JoeMiller 4:0d79ec30dd60 196 printf("=%c",serial_inchar);
JoeMiller 4:0d79ec30dd60 197 switch (serial_inchar) {
JoeMiller 4:0d79ec30dd60 198 case '+':
JoeMiller 4:0d79ec30dd60 199 DAC_Value += 10;
JoeMiller 4:0d79ec30dd60 200 doPulse = 1;
JoeMiller 4:0d79ec30dd60 201 break;
JoeMiller 4:0d79ec30dd60 202 case '-':
JoeMiller 4:0d79ec30dd60 203 DAC_Value -= 10;
JoeMiller 4:0d79ec30dd60 204 doPulse = 1;
JoeMiller 4:0d79ec30dd60 205 break;
JoeMiller 4:0d79ec30dd60 206 case '*':
JoeMiller 4:0d79ec30dd60 207 DAC_Value += 100;
JoeMiller 4:0d79ec30dd60 208 doPulse = 1;
JoeMiller 4:0d79ec30dd60 209 break;
JoeMiller 4:0d79ec30dd60 210 case '/':
JoeMiller 4:0d79ec30dd60 211 DAC_Value -= 100;
JoeMiller 4:0d79ec30dd60 212 doPulse = 1;
JoeMiller 4:0d79ec30dd60 213 break;
JoeMiller 4:0d79ec30dd60 214 case 'q':
JoeMiller 4:0d79ec30dd60 215 case ' ':
JoeMiller 4:0d79ec30dd60 216 doPulse = 1;
JoeMiller 4:0d79ec30dd60 217 break;
JoeMiller 4:0d79ec30dd60 218
JoeMiller 4:0d79ec30dd60 219 default:
JoeMiller 4:0d79ec30dd60 220 doPulse = 0;
JoeMiller 4:0d79ec30dd60 221 }
JoeMiller 4:0d79ec30dd60 222 if(doPulse) {
JoeMiller 4:0d79ec30dd60 223 DAC_Out.write_u16(DAC_Value);
JoeMiller 4:0d79ec30dd60 224 wait(PULSEWIDTH * 2);
JoeMiller 4:0d79ec30dd60 225 }
JoeMiller 4:0d79ec30dd60 226 doPulse = 0;
JoeMiller 4:0d79ec30dd60 227 waiting = 1;
JoeMiller 4:0d79ec30dd60 228 } while (serial_inchar != 'q');
JoeMiller 4:0d79ec30dd60 229
JoeMiller 4:0d79ec30dd60 230 I = VRin.read();
JoeMiller 2:29264f52a28e 231 DAC_Out.write_u16(0);
JoeMiller 4:0d79ec30dd60 232
JoeMiller 4:0d79ec30dd60 233 printf("\n\rVIN VALUE: %f\n\rDACVALUE: %d\n\r,I in:%f\n\r",V,DAC_Value,I);
JoeMiller 4:0d79ec30dd60 234 printf("Writting calibration values into SD card file \"SD\\calibrationCoefficients.txt\"...\n\r\n\r");
JoeMiller 4:0d79ec30dd60 235 printf("DAC100MA %d\n\r",DAC_Value);
JoeMiller 4:0d79ec30dd60 236 printf("I_SCALE %f\n\r",0.1/I);
JoeMiller 4:0d79ec30dd60 237 printf("V_SCALE %f\n\r",3.2/V);
JoeMiller 4:0d79ec30dd60 238 printf("\n\r\n\r");
JoeMiller 4:0d79ec30dd60 239
JoeMiller 4:0d79ec30dd60 240 fprintf(fc,"DAC100MA %d\n",DAC_Value);
JoeMiller 4:0d79ec30dd60 241 fprintf(fc,"I_SCALE %f\n",0.1/I);
JoeMiller 4:0d79ec30dd60 242 fprintf(fc,"V_SCALE %f\n",3.2/V);
JoeMiller 4:0d79ec30dd60 243 fclose(fc);
JoeMiller 4:0d79ec30dd60 244
JoeMiller 4:0d79ec30dd60 245 // Validation test
JoeMiller 4:0d79ec30dd60 246 float test_I_SCALE = 0.1/I;
JoeMiller 4:0d79ec30dd60 247 float test_V_SCALE = 3.2/V;
JoeMiller 4:0d79ec30dd60 248 while(serial_inchar == 'q') {
JoeMiller 4:0d79ec30dd60 249 DAC_Out.write_u16(DAC_Value);
JoeMiller 4:0d79ec30dd60 250 wait(INTERVAL+PULSEWIDTH);
JoeMiller 4:0d79ec30dd60 251 I = VRin.read()* test_I_SCALE;
JoeMiller 4:0d79ec30dd60 252 V = VBin.read()* test_V_SCALE;
JoeMiller 2:29264f52a28e 253
JoeMiller 4:0d79ec30dd60 254 printf("%1.4f,%1.2f,%d\n\r\n\r",I,V,DAC_Value);
JoeMiller 2:29264f52a28e 255
JoeMiller 4:0d79ec30dd60 256 // temperature compensation
JoeMiller 4:0d79ec30dd60 257 if (I < (0.100 - HYST)) {
JoeMiller 4:0d79ec30dd60 258 DAC_Value += (0.1 - I)*GAIN;
JoeMiller 4:0d79ec30dd60 259 }
JoeMiller 4:0d79ec30dd60 260 else if ( I > (0.100 + HYST)) {
JoeMiller 4:0d79ec30dd60 261 DAC_Value -= (I - 0.1)*GAIN;;
JoeMiller 4:0d79ec30dd60 262 }
JoeMiller 4:0d79ec30dd60 263
JoeMiller 4:0d79ec30dd60 264 }
JoeMiller 4:0d79ec30dd60 265 DAC_Out.write_u16(0);
JoeMiller 4:0d79ec30dd60 266 } // while (1)
JoeMiller 4:0d79ec30dd60 267 } // else (calibration mode)
JoeMiller 4:0d79ec30dd60 268 }