As written for first EVE battery test
Dependencies: SDFileSystem mbed
main.cpp
- Committer:
- JoeMiller
- Date:
- 2017-09-20
- Revision:
- 5:f5ac3e216653
- Parent:
- 4:0d79ec30dd60
File content as of revision 5:f5ac3e216653:
/* PULSED DISCHARGE BATTERY CAPACITY MEASUREMENT Version 2 Note: The design intent was to calibrate each board rather than designing and assembling precision analog circuits for each shield-board. 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 calibration mode if the calibration file does not exist and when complete will write the calibration file to the SD card. No longer need to compile twice (once for cal, a 2nd for discharge test). Calibration ASSUMES the MOSFET gain temperature compensation process included in this code is only good for temperatures near room temperatures. Keep this hardware away from extreme temperature changes - The battery (DUT) can go into temp chamber See ENG-1492 for more details and results */ #include "mbed.h" #include "SDFileSystem.h" Serial pc(SERIAL_TX, SERIAL_RX); AnalogOut DAC_Out(PA_4); // Connected to Gate of MOSFET AnalogIn VRin(PA_0); // for Current Measurement AnalogIn VBin(PA_1); // To measure battery Voltage DigitalOut LED(D4); // Activity indicator SDFileSystem sd(D11, D12, D13, D10, "sd"); // the pinout on the mbed Cool Components workshop board // Parameters #define PULSEWIDTH 0.099f #define INTERVAL 0.599f #define SLEWRATE 100 //10 is good for active testing, 100 for debugging #define VBATTERY_MIN (3.00f) #define TERMINATION_CURRENT (0.067f) #define HYST (0.0001f) // temp comp hysteresis #define GAIN 10000 // temp comp gain char serial_inchar,waiting; void OnSerial(void) // serial port interrupt used in calibration mode { serial_inchar = pc.getc(); waiting = 0; printf("%c:%d",serial_inchar,serial_inchar); } int main() { float I,V,I_Target; int DAC_Value = 35950; uint32_t count; float i_Cal,v_Cal; uint8_t CalibrationMode = 0; sd.disk_initialize(); DAC_Out.write_u16(0); pc.baud(115200); pc.attach(&OnSerial); LED = 0; waiting = 1; printf("Pulsed Battery Discharger\n\r"); // GET Calibration Coefficients and Constants from SD card printf("Reading Calibration Coefficients\n\r"); FILE *fc = fopen("/sd/calibrationCoefficients.txt", "r"); if(fc == NULL) { // try one more time wait(1.0); printf("\n\rTying to read SD a second time..\n\r"); fclose(fc); wait(1.0); FILE *fc = fopen("/sd/calibrationCoefficients.txt", "r"); if(fc == NULL) { waiting = 1; printf("\n\rFile does not exist. Enter Calibration Mode(Y/N)?\n\r"); while (waiting == 1) { wait(0.05); } if (serial_inchar == 'y' || serial_inchar == 'Y') { CalibrationMode = 1; } } } if (CalibrationMode == 0) { wait(1.0); fscanf(fc,"DAC100MA %d\n", &DAC_Value); fscanf(fc,"I_SCALE %f\n", &i_Cal); fscanf(fc,"V_SCALE %f\n", &v_Cal); printf("Dac Cal: %d, i_Cal: %f, v_Cal: %f\n\r",DAC_Value,i_Cal,v_Cal); if(DAC_Value == 0 || i_Cal == 0 || v_Cal == 0) { error("calibration file content error (2nd try)\n"); } } fclose(fc); printf("Using DAC_Value of:%d\n\r",DAC_Value); // Normal Battery Discharge Loop if (CalibrationMode == 0) { FILE *fp = fopen("/sd/BatteryLog.txt", "a"); if(fp == NULL) { error("Could not open Log file for write\n"); } fprintf(fp, "I,V,count\n"); printf("\n\rBattery Discharge Mode\n\r"); I_Target = 0.100; do { LED = 0; DAC_Out.write_u16(0); wait(INTERVAL); LED = 1; DAC_Out.write_u16(DAC_Value); wait(PULSEWIDTH); I = VRin.read()* i_Cal; V = VBin.read()* v_Cal; fprintf(fp,"%1.3f,%1.2f,%d\n",I,V,++count); //printf("%1.3f,%1.2f,%d\n\r",I,V,count); // MOSFET Gain temperature compensation if (I < (I_Target - HYST)) { DAC_Value += (I_Target - I)*GAIN; } else if ( I > (I_Target + HYST)) { DAC_Value -= (I - I_Target)*GAIN; } // If battery Voltage goes below BATTERY_MIN then reduce current if (V < VBATTERY_MIN) { if (I_Target > ( TERMINATION_CURRENT - (2.0*HYST))) { I_Target -= 0.001; } } } while (I > TERMINATION_CURRENT && waiting); fclose(fp); DAC_Out.write_u16(0); printf("Done!\n\r"); LED = 0; } else { //Perform Board Calibration uint8_t doPulse; printf("Creating Calibration Coefficients file on SD card\n\r"); FILE *fc = fopen("/sd/calibrationCoefficients.txt", "w"); if(fc == NULL) { error("cannot create calibration file on SD card\n\r"); } while (1) { printf("\n\rCalibration Mode\n\r"); waiting = 1; while (pc.readable()) { // flush buffer serial_inchar = pc.getc(); } printf("Set Vin to 3.20V then [press any key]\n\r"); while(waiting == 1){ wait(0.05); } printf("\n\rOK\n\r"); wait(0.5); V = VBin.read(); printf("Set Vin > 3.20V and < 3.60V\n\r"); printf("Press keys to adjust Current exactly to 100mA\n\r"); printf("Use +, -, *, / to adjust, q to end\n\r"); waiting = 1; do { DAC_Out.write_u16(0); while(waiting){wait(0.01);} printf("=%c",serial_inchar); switch (serial_inchar) { case '+': DAC_Value += 10; doPulse = 1; break; case '-': DAC_Value -= 10; doPulse = 1; break; case '*': DAC_Value += 100; doPulse = 1; break; case '/': DAC_Value -= 100; doPulse = 1; break; case 'q': case ' ': doPulse = 1; break; default: doPulse = 0; } if(doPulse) { DAC_Out.write_u16(DAC_Value); wait(PULSEWIDTH * 2); } doPulse = 0; waiting = 1; } while (serial_inchar != 'q'); I = VRin.read(); DAC_Out.write_u16(0); printf("\n\rVIN VALUE: %f\n\rDACVALUE: %d\n\r,I in:%f\n\r",V,DAC_Value,I); printf("Writting calibration values into SD card file \"SD\\calibrationCoefficients.txt\"...\n\r\n\r"); printf("DAC100MA %d\n\r",DAC_Value); printf("I_SCALE %f\n\r",0.1/I); printf("V_SCALE %f\n\r",3.2/V); printf("\n\r\n\r"); fprintf(fc,"DAC100MA %d\n",DAC_Value); fprintf(fc,"I_SCALE %f\n",0.1/I); fprintf(fc,"V_SCALE %f\n",3.2/V); fclose(fc); // Validation test float test_I_SCALE = 0.1/I; float test_V_SCALE = 3.2/V; while(serial_inchar == 'q') { DAC_Out.write_u16(DAC_Value); wait(INTERVAL+PULSEWIDTH); I = VRin.read()* test_I_SCALE; V = VBin.read()* test_V_SCALE; printf("%1.4f,%1.2f,%d\n\r\n\r",I,V,DAC_Value); // temperature compensation if (I < (0.100 - HYST)) { DAC_Value += (0.1 - I)*GAIN; } else if ( I > (0.100 + HYST)) { DAC_Value -= (I - 0.1)*GAIN;; } } DAC_Out.write_u16(0); } // while (1) } // else (calibration mode) }