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)
}