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@5:dad47e5b9586, 2016-12-07 (annotated)
- Committer:
- fmferrari
- Date:
- Wed Dec 07 20:27:27 2016 +0000
- Revision:
- 5:dad47e5b9586
- Parent:
- 4:dc0c58eedabb
- Child:
- 6:cb71171a7108
Not working try 1;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
fmferrari | 0:1e567a5a99c3 | 1 | /** |
fmferrari | 0:1e567a5a99c3 | 2 | * @author Damien Frost |
fmferrari | 0:1e567a5a99c3 | 3 | * |
fmferrari | 0:1e567a5a99c3 | 4 | * @section LICENSE |
fmferrari | 0:1e567a5a99c3 | 5 | * |
fmferrari | 0:1e567a5a99c3 | 6 | * Copyright (c) 2016 Damien Frost |
fmferrari | 0:1e567a5a99c3 | 7 | * |
fmferrari | 0:1e567a5a99c3 | 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
fmferrari | 0:1e567a5a99c3 | 9 | * of this software and associated documentation files (the "Software"), to deal |
fmferrari | 0:1e567a5a99c3 | 10 | * in the Software without restriction, including without limitation the rights |
fmferrari | 0:1e567a5a99c3 | 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
fmferrari | 0:1e567a5a99c3 | 12 | * copies of the Software, and to permit persons to whom the Software is |
fmferrari | 0:1e567a5a99c3 | 13 | * furnished to do so, subject to the following conditions: |
fmferrari | 0:1e567a5a99c3 | 14 | * |
fmferrari | 0:1e567a5a99c3 | 15 | * The above copyright notice and this permission notice shall be included in |
fmferrari | 0:1e567a5a99c3 | 16 | * all copies or substantial portions of the Software. |
fmferrari | 0:1e567a5a99c3 | 17 | * |
fmferrari | 0:1e567a5a99c3 | 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
fmferrari | 0:1e567a5a99c3 | 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
fmferrari | 0:1e567a5a99c3 | 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
fmferrari | 0:1e567a5a99c3 | 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
fmferrari | 0:1e567a5a99c3 | 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
fmferrari | 0:1e567a5a99c3 | 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
fmferrari | 0:1e567a5a99c3 | 24 | * THE SOFTWARE. |
fmferrari | 0:1e567a5a99c3 | 25 | * |
fmferrari | 0:1e567a5a99c3 | 26 | * @file "main.cpp" |
fmferrari | 0:1e567a5a99c3 | 27 | * |
fmferrari | 0:1e567a5a99c3 | 28 | * @section DESCRIPTION |
fmferrari | 0:1e567a5a99c3 | 29 | * Simple Internet of Things main program. The device sends data every 3 |
fmferrari | 0:1e567a5a99c3 | 30 | * seconds, and can receive data from a server. |
fmferrari | 0:1e567a5a99c3 | 31 | * |
fmferrari | 0:1e567a5a99c3 | 32 | */ |
fmferrari | 0:1e567a5a99c3 | 33 | |
fmferrari | 0:1e567a5a99c3 | 34 | #include "mbed.h" |
fmferrari | 0:1e567a5a99c3 | 35 | #include "globals.h" |
fmferrari | 0:1e567a5a99c3 | 36 | #include "WiflyInterface.h" |
fmferrari | 0:1e567a5a99c3 | 37 | #include "Commands.h" |
fmferrari | 0:1e567a5a99c3 | 38 | #include "Websocket.h" |
fmferrari | 0:1e567a5a99c3 | 39 | #include "ADC.h" |
fmferrari | 0:1e567a5a99c3 | 40 | #include "pwm.h" |
fmferrari | 5:dad47e5b9586 | 41 | #include "mbed_model.h" |
fmferrari | 0:1e567a5a99c3 | 42 | |
fmferrari | 0:1e567a5a99c3 | 43 | //#define DEBUG |
fmferrari | 0:1e567a5a99c3 | 44 | #define INFOMESSAGES |
fmferrari | 0:1e567a5a99c3 | 45 | #define WARNMESSAGES |
fmferrari | 0:1e567a5a99c3 | 46 | #define ERRMESSAGES |
fmferrari | 0:1e567a5a99c3 | 47 | #define FUNCNAME "IoT" |
fmferrari | 0:1e567a5a99c3 | 48 | #include "messages.h" |
fmferrari | 0:1e567a5a99c3 | 49 | |
fmferrari | 0:1e567a5a99c3 | 50 | |
fmferrari | 0:1e567a5a99c3 | 51 | |
fmferrari | 3:2360864c12e2 | 52 | |
fmferrari | 0:1e567a5a99c3 | 53 | // Main Loop! |
fmferrari | 0:1e567a5a99c3 | 54 | int main() { |
fmferrari | 0:1e567a5a99c3 | 55 | unsigned int wifi_cmd = NO_WIFI_CMD; |
fmferrari | 0:1e567a5a99c3 | 56 | float wifi_data = 0.0f; |
fmferrari | 0:1e567a5a99c3 | 57 | unsigned int ADCRaw; |
fmferrari | 0:1e567a5a99c3 | 58 | char msg[128]; |
fmferrari | 0:1e567a5a99c3 | 59 | |
fmferrari | 0:1e567a5a99c3 | 60 | // Set the IoT ID: |
fmferrari | 0:1e567a5a99c3 | 61 | IoT_ID = 5; |
fmferrari | 0:1e567a5a99c3 | 62 | |
fmferrari | 0:1e567a5a99c3 | 63 | // Set the Auto reconnect flag: |
fmferrari | 0:1e567a5a99c3 | 64 | IotStatus.SetFlag(SF_AUTOCONNECT); |
fmferrari | 0:1e567a5a99c3 | 65 | |
fmferrari | 0:1e567a5a99c3 | 66 | // Send a startup message to serial port: |
fmferrari | 0:1e567a5a99c3 | 67 | INFO(""); |
fmferrari | 0:1e567a5a99c3 | 68 | INFO(""); |
fmferrari | 0:1e567a5a99c3 | 69 | INFO("Starting up..."); |
fmferrari | 0:1e567a5a99c3 | 70 | INFO("CPU SystemCoreClock is %d Hz", SystemCoreClock); |
fmferrari | 0:1e567a5a99c3 | 71 | |
fmferrari | 0:1e567a5a99c3 | 72 | // Configure the ADC to sample the internal temperature sensor. You cannot |
fmferrari | 0:1e567a5a99c3 | 73 | // use AnalogIn() unfortunately... |
fmferrari | 0:1e567a5a99c3 | 74 | ConfigureADC(); |
fmferrari | 0:1e567a5a99c3 | 75 | |
fmferrari | 4:dc0c58eedabb | 76 | // Check for the wifi module |
fmferrari | 4:dc0c58eedabb | 77 | WifiPresent.mode(PullDown); |
fmferrari | 4:dc0c58eedabb | 78 | if(WifiPresent == 1){ |
fmferrari | 4:dc0c58eedabb | 79 | IotStatus.SetFlag(SS_WIFIPRESENT); |
fmferrari | 4:dc0c58eedabb | 80 | } |
fmferrari | 4:dc0c58eedabb | 81 | |
fmferrari | 4:dc0c58eedabb | 82 | if(IotStatus.CheckFlag(SS_WIFIPRESENT)){ |
fmferrari | 0:1e567a5a99c3 | 83 | |
fmferrari | 4:dc0c58eedabb | 84 | // Connect to the wifi network. It will basically get stuck here until it |
fmferrari | 4:dc0c58eedabb | 85 | // connects to the network. |
fmferrari | 4:dc0c58eedabb | 86 | SetupNetwork(5000); |
fmferrari | 4:dc0c58eedabb | 87 | |
fmferrari | 4:dc0c58eedabb | 88 | // Configure the baud rate of the wifi shield: |
fmferrari | 4:dc0c58eedabb | 89 | // This will make our wireless transmissions much faster. |
fmferrari | 4:dc0c58eedabb | 90 | ws.setBaud(115200); |
fmferrari | 4:dc0c58eedabb | 91 | wait(0.5f); |
fmferrari | 4:dc0c58eedabb | 92 | } |
fmferrari | 0:1e567a5a99c3 | 93 | |
fmferrari | 0:1e567a5a99c3 | 94 | // Configure the PWM module: |
fmferrari | 0:1e567a5a99c3 | 95 | ConfigurePWM(Duty_us, PwmPeriod_us); |
fmferrari | 0:1e567a5a99c3 | 96 | // Turn on the PWM: |
fmferrari | 0:1e567a5a99c3 | 97 | TurnOnPWM(true); |
fmferrari | 0:1e567a5a99c3 | 98 | |
fmferrari | 0:1e567a5a99c3 | 99 | // Check to see we are connected to the network: |
fmferrari | 0:1e567a5a99c3 | 100 | if(IotStatus.CheckFlag(SF_WIRELESSCONNECTED)){ |
fmferrari | 0:1e567a5a99c3 | 101 | // Try to connect to the WebSocket server: |
fmferrari | 0:1e567a5a99c3 | 102 | sprintf(msg, "ws://%s:%d/ws", SERVER_IP, WS_PORT); |
fmferrari | 0:1e567a5a99c3 | 103 | ws.Initialize(msg); |
fmferrari | 0:1e567a5a99c3 | 104 | INFO("Connecting to Websocket Server on %s...", msg); |
fmferrari | 0:1e567a5a99c3 | 105 | if(ws.connect()){ |
fmferrari | 0:1e567a5a99c3 | 106 | // Set a status flag: |
fmferrari | 0:1e567a5a99c3 | 107 | INFO("Connected."); |
fmferrari | 0:1e567a5a99c3 | 108 | IotStatus.SetFlag(SF_SERVERCONNECTED); |
fmferrari | 0:1e567a5a99c3 | 109 | }else{ |
fmferrari | 0:1e567a5a99c3 | 110 | // We could not connect right now.. |
fmferrari | 0:1e567a5a99c3 | 111 | IotStatus.ClearFlag(SF_SERVERCONNECTED); |
fmferrari | 0:1e567a5a99c3 | 112 | INFO("Could not connect to server, will try again later."); |
fmferrari | 0:1e567a5a99c3 | 113 | ReconnectAttempts++; |
fmferrari | 0:1e567a5a99c3 | 114 | } |
fmferrari | 0:1e567a5a99c3 | 115 | } |
fmferrari | 0:1e567a5a99c3 | 116 | |
fmferrari | 0:1e567a5a99c3 | 117 | // Start the display timer which will send data to the server every |
fmferrari | 0:1e567a5a99c3 | 118 | // 3 seconds. |
fmferrari | 0:1e567a5a99c3 | 119 | DisplayTimer.start(); |
fmferrari | 0:1e567a5a99c3 | 120 | |
fmferrari | 0:1e567a5a99c3 | 121 | // Inifinite main loop: |
fmferrari | 0:1e567a5a99c3 | 122 | while(1) { |
fmferrari | 0:1e567a5a99c3 | 123 | |
fmferrari | 0:1e567a5a99c3 | 124 | // Process the wifi command: |
fmferrari | 0:1e567a5a99c3 | 125 | if(wifi_cmd > NO_WIFI_CMD){ |
fmferrari | 0:1e567a5a99c3 | 126 | // Modify the desired variable: |
fmferrari | 0:1e567a5a99c3 | 127 | ModifyVariable(wifi_cmd, wifi_data); |
fmferrari | 0:1e567a5a99c3 | 128 | // Reset the command: |
fmferrari | 0:1e567a5a99c3 | 129 | wifi_cmd = NO_WIFI_CMD; |
fmferrari | 0:1e567a5a99c3 | 130 | } |
fmferrari | 0:1e567a5a99c3 | 131 | |
fmferrari | 0:1e567a5a99c3 | 132 | // Check for new wifi data: |
fmferrari | 0:1e567a5a99c3 | 133 | if((wifi_cmd == NO_WIFI_CMD)){ |
fmferrari | 0:1e567a5a99c3 | 134 | ReceiveNetworkData(&wifi_cmd, &wifi_data); |
fmferrari | 0:1e567a5a99c3 | 135 | } |
fmferrari | 0:1e567a5a99c3 | 136 | |
fmferrari | 0:1e567a5a99c3 | 137 | // Send the network data every 3 seconds: |
fmferrari | 0:1e567a5a99c3 | 138 | if(DisplayTimer.read()>(3.0f)){ |
fmferrari | 0:1e567a5a99c3 | 139 | // Sample the internal temperature sensor: |
fmferrari | 0:1e567a5a99c3 | 140 | STARTADCCONVERSION; |
fmferrari | 0:1e567a5a99c3 | 141 | // Wait for the conversion to complete: |
fmferrari | 0:1e567a5a99c3 | 142 | while(!ADCCONVERSIONCOMPLETE); |
fmferrari | 0:1e567a5a99c3 | 143 | // Save the raw value from the ADC: |
fmferrari | 0:1e567a5a99c3 | 144 | ADCRaw = ADC1->DR; |
fmferrari | 0:1e567a5a99c3 | 145 | // Calculate the temperature using information from the datasheet: |
fmferrari | 0:1e567a5a99c3 | 146 | TempSensor = ((((float)ADCRaw)/ADC_MAX)*IT_VMAX - IT_V25)/IT_AVG_SLOPE + 25.0f; |
fmferrari | 0:1e567a5a99c3 | 147 | // Output the result: |
fmferrari | 0:1e567a5a99c3 | 148 | DBG("TempSensor = %.5f", TempSensor); |
fmferrari | 0:1e567a5a99c3 | 149 | DBG("ADC1->DR = %d", ADCRaw); |
fmferrari | 0:1e567a5a99c3 | 150 | |
fmferrari | 5:dad47e5b9586 | 151 | // INFO("SOC is, %f", mbed_model_Y.SOC); |
fmferrari | 2:089480a12fa2 | 152 | |
fmferrari | 0:1e567a5a99c3 | 153 | // Send data over network: |
fmferrari | 0:1e567a5a99c3 | 154 | SendNetworkData(); |
fmferrari | 0:1e567a5a99c3 | 155 | |
fmferrari | 0:1e567a5a99c3 | 156 | // Increment a counter: |
fmferrari | 0:1e567a5a99c3 | 157 | SendCounter++; |
fmferrari | 0:1e567a5a99c3 | 158 | |
fmferrari | 0:1e567a5a99c3 | 159 | // Reset the timer: |
fmferrari | 0:1e567a5a99c3 | 160 | DisplayTimer.reset(); |
fmferrari | 0:1e567a5a99c3 | 161 | |
fmferrari | 0:1e567a5a99c3 | 162 | } |
fmferrari | 0:1e567a5a99c3 | 163 | } // while(1) |
fmferrari | 0:1e567a5a99c3 | 164 | } // main() |