First working, tested and calibrated unit

Dependencies:   mbed USBDevice

main.cpp

Committer:
JoeMiller
Date:
2017-03-22
Revision:
0:197cfa57c3c7
Child:
1:0d88cfafe20e

File content as of revision 0:197cfa57c3c7:

/* PULSED DISCHARGE BATTERY CAPACITY MEASUREMENT

Note: The design intent was to calibrate each board rather than designing 
    and assembling precision analog circuits for each shield-board.
      Use compile directive switch "CAL" in this firmware to perform test to 
    obtain calibration coeficients for each board. Place these obtained cal 
    coefficients in the CALIBRATION CONSTANTS section 
    
    See ENG-1492 for more details and results

**** Be sure to set the approriate BOARDNUMBER before compiling ***********

*/


#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


// BOARD SPECIFIC CALIBRATION CONSTANTS
#define BOARDNUMBER 1

#if BOARDNUMBER == 1
#define DAC100MA 35470                                                                                                                                         
#define I_SCALE 0.332386F                                                       
#define V_SCALE 3.314950F                                                       
 
    
#elif BOARDNUMBER == 2
    #define DAC100MA 35950

#elif BOARDNUMBER == 3
    #define DAC100MA 35950

#else 
    #define DAC100MA 35950

#endif



// 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;
    uint16_t DAC_Value = DAC100MA;
    uint32_t count;
    
    DAC_Out.write_u16(0);

    pc.baud(115200);    
    printf("Pulsed Battery Discharger\n\r");
    pc.attach(&OnSerial);
    LED = 0;
    wait(1);
    waiting = 1;

   
//    FILE *fp = fopen("/sd/sdtest.txt", "w");
//    if(fp == NULL) {
//        error("Could not open file for write\n");
//    }

#if 1  // 0 = Calibration Mode, 1= Discharge test mode  

    FILE *fp = fopen("/sd/BatteryLog.txt", "w");
    if(fp == NULL) {
        error("Could not open 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_SCALE;
        V = VBin.read()* V_SCALE;
        
        fprintf(fp,"%1.3f,%1.2f,%d\n",I,V,++count);
        //printf("%1.3f,%1.2f,%d\n\r",I,V,count);


        // 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
    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("OK\n\r");
    wait(0.5);
    V = VBin.read();

    printf("Setting Current to 100mA\n\r");
    printf("Use +, -, *, / to adjust, q to end\n\r");
    
    DAC_Value = 35550;
    DAC_Out.write_u16(DAC_Value);
    
    waiting = 1;
    do {
        while(waiting){wait(0.01);}
        printf("=%c",serial_inchar);
        switch (serial_inchar) {
            case '+':
                DAC_Value += 10;
                break;
            case '-':
                DAC_Value -= 10;
                break;
            case '*':
                DAC_Value += 100;
                break;
            case '/':
                DAC_Value -= 100;
                break;        
        }
        DAC_Out.write_u16(DAC_Value);
        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("Cut/paste this calibration into the calibration section...\n\r\n\r");
    printf("#define DAC100MA %d\n\r",DAC_Value);
    printf("#define I_SCALE %fF\n\r",0.1/I);
    printf("#define V_SCALE %fF\n\r",3.2/V);
    printf("\n\r\n\r");
    
    
    // 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",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);
    
#endif  
 
}