A public repository for BMS algorithms for a NUCLEO BOARD.

Dependencies:   mbed

Hi Everyone!

Welcome to this repository from Howey's Research Group at the University of Oxford.

The code published here incorporates BMS algorithms for diagnosis functions such as SOC, SOH and Power estimation on a Kokam 53Ah Li-ion battery. This code was designed to work with a NUCLEO F401-RE board and to be tested with a dSPACE HIL Simulator. A short guide on how the set up works is available at https://bitbucket.org/ff95/bms .

The code is made up of three key parts. "Headers" and "Source" folders and the "main.cpp" file. As the code was generated by converting a Simulink model ( available on the BitBucket page), the headers and source code files generated by the conversion are in the corresponding "Headers" and "Source" folders. The "main.cpp" file sets up the ADC, the USB data transmission and starts the estimation (once a character "y" has been received by the computer it is connected to). It also transmits the data from the estimation via USB. Explanation on how to set up the communication with the board is available at BitBucket webpage, from where a MATLAB file can be downloaded which allows real time communication.

For any questions you can contact the author at federicomariaferrari@gmail.com .

The Simulink and Matlab files, together with a short guide, are all available at: https://bitbucket.org/ff95/bms.

Thanks for trying this out!

Federico

main.cpp

Committer:
fmferrari
Date:
2017-07-13
Revision:
23:447ef1071e49
Parent:
22:caf41c9bb9d0

File content as of revision 23:447ef1071e49:



#include "mbed.h"
#include "EKF.h"
#include <vector>



Timer OutputTimer;
Timer MacroTime;
Ticker TimerforIteration;
Ticker TimerforSampling;

Serial TRANSMIT(SERIAL_TX, SERIAL_RX);

AnalogIn VoltageSensor(PA_0);
AnalogIn CurrentSensor(PA_1);
AnalogIn TemperatureSensor(PA_4);
DigitalOut DATATRANSMISSION(LED1);
InterruptIn OnOrOff(USER_BUTTON);

float VoltageMeas = 0;
float CurrentMeas = 0;
float TemperatureMeas=0;

float Result_V = 0;
float  Result_I = 0;
float  Result_T = 0;

float  MinStepRes = 0;
float SocOutput = 0.0f;
float R0Output=0.0f;
float Q0Output=0.0f;
float  mVoltRange  = 3300; // This is the supplay voltage of ADC (or MCU)
float  ADCres = 65536; // This is the ADC resolution oxFFFF
int Count=0;

float MaxCurrentAmp=250;
float MaxTemperature=80;
float MaxdSpaceOut=6;
float CircuitGain=0.545;

bool ButtonPressed=0.0f;
bool StateEKF=1.0f;
char RunMed=0;
const int nIterations=200;

float StoreVoltage[nIterations];
float StoreCurrent[nIterations];
float StoreTemperature[nIterations];

float MeanVoltage;
float MeanCurrent;
float MeanTemperature;

double StoreTime=0;
double StorePrevTime=0;
float TimerLimit=600;
double TimerTimeStep=0;
double MacroPrevTime=0;

//Get Mean Function
float GetMean(float Array[])
{
    float Sum=0;
    float mean=0;

    for ( int iter=0; iter<nIterations; iter++ ) {
        Sum=Sum+Array[iter];
    }

    mean=Sum/nIterations;

    return mean;
}



//SAMPLING function
void SAMPLE()
{
    for ( int iter=0; iter<nIterations; iter++ ) {

        // SAMPLE THE ADCs
        VoltageMeas = VoltageSensor.read_u16();
        CurrentMeas = CurrentSensor.read_u16();
        TemperatureMeas=TemperatureSensor.read_u16();

        //CALCULATE THE RESOLUTION OF EACH BIT
        MinStepRes = (mVoltRange / ADCres);

        // CONVERT MEASURED VALUES TO ACTUAL SCALED VALUES
        Result_V = ((MinStepRes * VoltageMeas))/1000;
        Result_I = ((MinStepRes * CurrentMeas))/1000;
        Result_T = ((MinStepRes * TemperatureMeas))/1000;


        // INPUT THE DATA TO THE EKF_STEP

       
         StoreVoltage[iter]=Result_V*1.8272;
         StoreCurrent[iter]=(Result_I*1.8225-MaxdSpaceOut/2)*(2*MaxCurrentAmp/MaxdSpaceOut);
         StoreTemperature[iter]=Result_T*1.8245*(MaxTemperature/MaxdSpaceOut);
    }

 
   
     MeanVoltage=GetMean(StoreVoltage)/1.0005;
    MeanCurrent=GetMean(StoreCurrent)/1.003;
    MeanTemperature=GetMean(StoreTemperature)/1.0008;
   
}




//USE THE FUNCTION WITH A TIMER TO STEP AT KNOWN TIME LENGTHS
void ITERATE()
{


    if (MacroTime.read()>TimerLimit) {
        MacroTime.reset();
        TimerTimeStep=EKF_U.TimeStep;
        MacroPrevTime=0;
    } else {

        TimerTimeStep=MacroTime.read()-MacroPrevTime;
        MacroPrevTime=MacroTime.read();
    }

    //THIS IS THE OVERALL CLOCK
    StoreTime=StoreTime+TimerTimeStep;


    //TimerforSampling.attach(&SAMPLE, 0.001);
    SAMPLE();
    EKF_U.Voltage=MeanVoltage;
    EKF_U.Current=MeanCurrent;
    EKF_U.TemperatureIn=MeanTemperature;

    EKF_U.TimeStep=StoreTime-EKF_U.MacroTime;
    EKF_U.MacroTime=StoreTime;

    // STEP THE EKF MODEL
    EKF_step();

    //FLASH THE LIGHT
    DATATRANSMISSION=1;

    //TRANSMIT DATA
    TRANSMIT.printf("%f \n", EKF_Y.SOC);
    TRANSMIT.printf("%f \n", EKF_Y.Q0);
    TRANSMIT.printf("%f \n", EKF_Y.R0);

    TRANSMIT.printf("%f \n", EKF_Y.PowerDisch);
    TRANSMIT.printf("%f \n", EKF_Y.PowerCh);

    TRANSMIT.printf(" %f \n",EKF_U.Voltage);
    TRANSMIT.printf("%f \n", EKF_U.Current);
    TRANSMIT.printf("%f \n", EKF_U.TemperatureIn);

    TRANSMIT.printf(" %f \n", EKF_U.MacroTime);
    TRANSMIT.printf(" %f \n", EKF_U.TimeStep);

    TRANSMIT.printf("%f \n", EKF_Y.DegradationIndex);
}


//MAIN SCRIPT
int main()
{
    while(1) {


        char RunMBED=TRANSMIT.getc();

        EKF_initialize();
        OutputTimer.reset();
        MacroTime.reset();

        while (RunMBED=='y') {

            TimerforIteration.attach(&ITERATE,0.2);
            //START TIMER AND LED
            MacroTime.start();
            OutputTimer.start();
            DATATRANSMISSION=0;
            RunMBED=TRANSMIT.getc();

        }
    }

}