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

Committer:
fmferrari
Date:
Thu Jul 13 10:50:13 2017 +0000
Revision:
23:447ef1071e49
Parent:
22:caf41c9bb9d0
A working version of the code needed to run an mbed micro controller.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fmferrari 14:4b5df635f248 1
fmferrari 0:1e567a5a99c3 2
fmferrari 0:1e567a5a99c3 3 #include "mbed.h"
fmferrari 6:cb71171a7108 4 #include "EKF.h"
fmferrari 15:b39f568faa27 5 #include <vector>
fmferrari 0:1e567a5a99c3 6
fmferrari 12:bf3e3b87224e 7
fmferrari 0:1e567a5a99c3 8
fmferrari 13:831eab218c33 9 Timer OutputTimer;
fmferrari 13:831eab218c33 10 Timer MacroTime;
fmferrari 14:4b5df635f248 11 Ticker TimerforIteration;
fmferrari 15:b39f568faa27 12 Ticker TimerforSampling;
fmferrari 14:4b5df635f248 13
fmferrari 12:bf3e3b87224e 14 Serial TRANSMIT(SERIAL_TX, SERIAL_RX);
fmferrari 13:831eab218c33 15
fmferrari 12:bf3e3b87224e 16 AnalogIn VoltageSensor(PA_0);
fmferrari 12:bf3e3b87224e 17 AnalogIn CurrentSensor(PA_1);
fmferrari 14:4b5df635f248 18 AnalogIn TemperatureSensor(PA_4);
fmferrari 12:bf3e3b87224e 19 DigitalOut DATATRANSMISSION(LED1);
fmferrari 14:4b5df635f248 20 InterruptIn OnOrOff(USER_BUTTON);
fmferrari 14:4b5df635f248 21
fmferrari 12:bf3e3b87224e 22 float VoltageMeas = 0;
fmferrari 12:bf3e3b87224e 23 float CurrentMeas = 0;
fmferrari 14:4b5df635f248 24 float TemperatureMeas=0;
fmferrari 14:4b5df635f248 25
fmferrari 12:bf3e3b87224e 26 float Result_V = 0;
fmferrari 12:bf3e3b87224e 27 float Result_I = 0;
fmferrari 14:4b5df635f248 28 float Result_T = 0;
fmferrari 14:4b5df635f248 29
fmferrari 12:bf3e3b87224e 30 float MinStepRes = 0;
fmferrari 12:bf3e3b87224e 31 float SocOutput = 0.0f;
fmferrari 12:bf3e3b87224e 32 float R0Output=0.0f;
fmferrari 13:831eab218c33 33 float Q0Output=0.0f;
fmferrari 14:4b5df635f248 34 float mVoltRange = 3300; // This is the supplay voltage of ADC (or MCU)
fmferrari 14:4b5df635f248 35 float ADCres = 65536; // This is the ADC resolution oxFFFF
fmferrari 14:4b5df635f248 36 int Count=0;
fmferrari 14:4b5df635f248 37
fmferrari 21:534cd02b6bc4 38 float MaxCurrentAmp=250;
fmferrari 14:4b5df635f248 39 float MaxTemperature=80;
fmferrari 14:4b5df635f248 40 float MaxdSpaceOut=6;
fmferrari 15:b39f568faa27 41 float CircuitGain=0.545;
fmferrari 14:4b5df635f248 42
fmferrari 14:4b5df635f248 43 bool ButtonPressed=0.0f;
fmferrari 14:4b5df635f248 44 bool StateEKF=1.0f;
fmferrari 17:9b1f3bf6da0f 45 char RunMed=0;
fmferrari 20:efb192150248 46 const int nIterations=200;
fmferrari 15:b39f568faa27 47
fmferrari 15:b39f568faa27 48 float StoreVoltage[nIterations];
fmferrari 15:b39f568faa27 49 float StoreCurrent[nIterations];
fmferrari 15:b39f568faa27 50 float StoreTemperature[nIterations];
fmferrari 15:b39f568faa27 51
fmferrari 15:b39f568faa27 52 float MeanVoltage;
fmferrari 15:b39f568faa27 53 float MeanCurrent;
fmferrari 15:b39f568faa27 54 float MeanTemperature;
fmferrari 15:b39f568faa27 55
fmferrari 21:534cd02b6bc4 56 double StoreTime=0;
fmferrari 21:534cd02b6bc4 57 double StorePrevTime=0;
fmferrari 21:534cd02b6bc4 58 float TimerLimit=600;
fmferrari 21:534cd02b6bc4 59 double TimerTimeStep=0;
fmferrari 21:534cd02b6bc4 60 double MacroPrevTime=0;
fmferrari 15:b39f568faa27 61
fmferrari 21:534cd02b6bc4 62 //Get Mean Function
fmferrari 21:534cd02b6bc4 63 float GetMean(float Array[])
fmferrari 21:534cd02b6bc4 64 {
fmferrari 21:534cd02b6bc4 65 float Sum=0;
fmferrari 21:534cd02b6bc4 66 float mean=0;
fmferrari 21:534cd02b6bc4 67
fmferrari 21:534cd02b6bc4 68 for ( int iter=0; iter<nIterations; iter++ ) {
fmferrari 21:534cd02b6bc4 69 Sum=Sum+Array[iter];
fmferrari 21:534cd02b6bc4 70 }
fmferrari 21:534cd02b6bc4 71
fmferrari 21:534cd02b6bc4 72 mean=Sum/nIterations;
fmferrari 21:534cd02b6bc4 73
fmferrari 21:534cd02b6bc4 74 return mean;
fmferrari 21:534cd02b6bc4 75 }
fmferrari 15:b39f568faa27 76
fmferrari 15:b39f568faa27 77
fmferrari 17:9b1f3bf6da0f 78
fmferrari 21:534cd02b6bc4 79 //SAMPLING function
fmferrari 15:b39f568faa27 80 void SAMPLE()
fmferrari 15:b39f568faa27 81 {
fmferrari 15:b39f568faa27 82 for ( int iter=0; iter<nIterations; iter++ ) {
fmferrari 15:b39f568faa27 83
fmferrari 15:b39f568faa27 84 // SAMPLE THE ADCs
fmferrari 15:b39f568faa27 85 VoltageMeas = VoltageSensor.read_u16();
fmferrari 15:b39f568faa27 86 CurrentMeas = CurrentSensor.read_u16();
fmferrari 15:b39f568faa27 87 TemperatureMeas=TemperatureSensor.read_u16();
fmferrari 15:b39f568faa27 88
fmferrari 15:b39f568faa27 89 //CALCULATE THE RESOLUTION OF EACH BIT
fmferrari 15:b39f568faa27 90 MinStepRes = (mVoltRange / ADCres);
fmferrari 15:b39f568faa27 91
fmferrari 15:b39f568faa27 92 // CONVERT MEASURED VALUES TO ACTUAL SCALED VALUES
fmferrari 15:b39f568faa27 93 Result_V = ((MinStepRes * VoltageMeas))/1000;
fmferrari 15:b39f568faa27 94 Result_I = ((MinStepRes * CurrentMeas))/1000;
fmferrari 15:b39f568faa27 95 Result_T = ((MinStepRes * TemperatureMeas))/1000;
fmferrari 15:b39f568faa27 96
fmferrari 15:b39f568faa27 97
fmferrari 15:b39f568faa27 98 // INPUT THE DATA TO THE EKF_STEP
fmferrari 15:b39f568faa27 99
fmferrari 23:447ef1071e49 100
fmferrari 22:caf41c9bb9d0 101 StoreVoltage[iter]=Result_V*1.8272;
fmferrari 22:caf41c9bb9d0 102 StoreCurrent[iter]=(Result_I*1.8225-MaxdSpaceOut/2)*(2*MaxCurrentAmp/MaxdSpaceOut);
fmferrari 22:caf41c9bb9d0 103 StoreTemperature[iter]=Result_T*1.8245*(MaxTemperature/MaxdSpaceOut);
fmferrari 15:b39f568faa27 104 }
fmferrari 21:534cd02b6bc4 105
fmferrari 23:447ef1071e49 106
fmferrari 22:caf41c9bb9d0 107
fmferrari 22:caf41c9bb9d0 108 MeanVoltage=GetMean(StoreVoltage)/1.0005;
fmferrari 22:caf41c9bb9d0 109 MeanCurrent=GetMean(StoreCurrent)/1.003;
fmferrari 22:caf41c9bb9d0 110 MeanTemperature=GetMean(StoreTemperature)/1.0008;
fmferrari 22:caf41c9bb9d0 111
fmferrari 15:b39f568faa27 112 }
fmferrari 15:b39f568faa27 113
fmferrari 15:b39f568faa27 114
fmferrari 15:b39f568faa27 115
fmferrari 12:bf3e3b87224e 116
fmferrari 14:4b5df635f248 117 //USE THE FUNCTION WITH A TIMER TO STEP AT KNOWN TIME LENGTHS
fmferrari 14:4b5df635f248 118 void ITERATE()
fmferrari 14:4b5df635f248 119 {
fmferrari 21:534cd02b6bc4 120
fmferrari 21:534cd02b6bc4 121
fmferrari 21:534cd02b6bc4 122 if (MacroTime.read()>TimerLimit) {
fmferrari 21:534cd02b6bc4 123 MacroTime.reset();
fmferrari 21:534cd02b6bc4 124 TimerTimeStep=EKF_U.TimeStep;
fmferrari 21:534cd02b6bc4 125 MacroPrevTime=0;
fmferrari 21:534cd02b6bc4 126 } else {
fmferrari 21:534cd02b6bc4 127
fmferrari 21:534cd02b6bc4 128 TimerTimeStep=MacroTime.read()-MacroPrevTime;
fmferrari 21:534cd02b6bc4 129 MacroPrevTime=MacroTime.read();
fmferrari 21:534cd02b6bc4 130 }
fmferrari 21:534cd02b6bc4 131
fmferrari 21:534cd02b6bc4 132 //THIS IS THE OVERALL CLOCK
fmferrari 21:534cd02b6bc4 133 StoreTime=StoreTime+TimerTimeStep;
fmferrari 21:534cd02b6bc4 134
fmferrari 21:534cd02b6bc4 135
fmferrari 15:b39f568faa27 136 //TimerforSampling.attach(&SAMPLE, 0.001);
fmferrari 15:b39f568faa27 137 SAMPLE();
fmferrari 15:b39f568faa27 138 EKF_U.Voltage=MeanVoltage;
fmferrari 15:b39f568faa27 139 EKF_U.Current=MeanCurrent;
fmferrari 15:b39f568faa27 140 EKF_U.TemperatureIn=MeanTemperature;
fmferrari 14:4b5df635f248 141
fmferrari 21:534cd02b6bc4 142 EKF_U.TimeStep=StoreTime-EKF_U.MacroTime;
fmferrari 21:534cd02b6bc4 143 EKF_U.MacroTime=StoreTime;
fmferrari 14:4b5df635f248 144
fmferrari 14:4b5df635f248 145 // STEP THE EKF MODEL
fmferrari 14:4b5df635f248 146 EKF_step();
fmferrari 14:4b5df635f248 147
fmferrari 14:4b5df635f248 148 //FLASH THE LIGHT
fmferrari 14:4b5df635f248 149 DATATRANSMISSION=1;
fmferrari 14:4b5df635f248 150
fmferrari 14:4b5df635f248 151 //TRANSMIT DATA
fmferrari 14:4b5df635f248 152 TRANSMIT.printf("%f \n", EKF_Y.SOC);
fmferrari 14:4b5df635f248 153 TRANSMIT.printf("%f \n", EKF_Y.Q0);
fmferrari 21:534cd02b6bc4 154 TRANSMIT.printf("%f \n", EKF_Y.R0);
fmferrari 21:534cd02b6bc4 155
fmferrari 18:4a769322eb39 156 TRANSMIT.printf("%f \n", EKF_Y.PowerDisch);
fmferrari 18:4a769322eb39 157 TRANSMIT.printf("%f \n", EKF_Y.PowerCh);
fmferrari 21:534cd02b6bc4 158
fmferrari 14:4b5df635f248 159 TRANSMIT.printf(" %f \n",EKF_U.Voltage);
fmferrari 14:4b5df635f248 160 TRANSMIT.printf("%f \n", EKF_U.Current);
fmferrari 14:4b5df635f248 161 TRANSMIT.printf("%f \n", EKF_U.TemperatureIn);
fmferrari 14:4b5df635f248 162
fmferrari 21:534cd02b6bc4 163 TRANSMIT.printf(" %f \n", EKF_U.MacroTime);
fmferrari 21:534cd02b6bc4 164 TRANSMIT.printf(" %f \n", EKF_U.TimeStep);
fmferrari 21:534cd02b6bc4 165
fmferrari 21:534cd02b6bc4 166 TRANSMIT.printf("%f \n", EKF_Y.DegradationIndex);
fmferrari 14:4b5df635f248 167 }
fmferrari 12:bf3e3b87224e 168
fmferrari 12:bf3e3b87224e 169
fmferrari 17:9b1f3bf6da0f 170 //MAIN SCRIPT
fmferrari 13:831eab218c33 171 int main()
fmferrari 13:831eab218c33 172 {
fmferrari 0:1e567a5a99c3 173 while(1) {
fmferrari 15:b39f568faa27 174
fmferrari 13:831eab218c33 175
fmferrari 21:534cd02b6bc4 176 char RunMBED=TRANSMIT.getc();
fmferrari 18:4a769322eb39 177
fmferrari 21:534cd02b6bc4 178 EKF_initialize();
fmferrari 21:534cd02b6bc4 179 OutputTimer.reset();
fmferrari 21:534cd02b6bc4 180 MacroTime.reset();
fmferrari 21:534cd02b6bc4 181
fmferrari 21:534cd02b6bc4 182 while (RunMBED=='y') {
fmferrari 21:534cd02b6bc4 183
fmferrari 18:4a769322eb39 184 TimerforIteration.attach(&ITERATE,0.2);
fmferrari 14:4b5df635f248 185 //START TIMER AND LED
fmferrari 14:4b5df635f248 186 MacroTime.start();
fmferrari 14:4b5df635f248 187 OutputTimer.start();
fmferrari 14:4b5df635f248 188 DATATRANSMISSION=0;
fmferrari 17:9b1f3bf6da0f 189 RunMBED=TRANSMIT.getc();
fmferrari 21:534cd02b6bc4 190
fmferrari 13:831eab218c33 191 }
fmferrari 10:c4f0c3a5223f 192 }
fmferrari 10:c4f0c3a5223f 193
fmferrari 13:831eab218c33 194 }