A public repository for BMS algorithms for a NUCLEO BOARD.
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(); } } }