Has base BMU code but sends dummy temperature and voltage readings to test CAN

Dependencies:   CUER_CAN DS1820 LTC2943 LTC6804 mbed

Fork of BMS_BMUCore_Max by CUER

Committer:
msharma97
Date:
Sat Feb 11 16:09:20 2017 +0000
Revision:
9:82ba050a7e13
Parent:
7:d00f4433cea9
Child:
10:1079f8e52d65
nah mate

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lcockerton62 0:0a5f554d2a16 1 #include "mbed.h"
lcockerton62 0:0a5f554d2a16 2 #include "CANParserBMU.h"
lcockerton62 0:0a5f554d2a16 3 #include "Data_Types_BMU.h"
lcockerton62 0:0a5f554d2a16 4 #include "CAN_Data.h"
lcockerton62 0:0a5f554d2a16 5 #include "CAN_IDs.h"
lcockerton62 1:51477fe4851b 6 #include "EEPROM_I2C.h"
lcockerton62 1:51477fe4851b 7 #include "Temperature.h"
DasSidG 4:9050c5d6925e 8 #include "LTC2943_Read.h"
maxv008 7:d00f4433cea9 9 #include "State_Of_Charge.h"
maxv008 7:d00f4433cea9 10 #include "SPI_I2C_Parser.h"
lcockerton62 0:0a5f554d2a16 11
msharma97 9:82ba050a7e13 12
msharma97 9:82ba050a7e13 13
lcockerton62 0:0a5f554d2a16 14 using namespace CAN_IDs;
lcockerton62 0:0a5f554d2a16 15
lcockerton62 0:0a5f554d2a16 16 // Function definitions
lcockerton62 1:51477fe4851b 17 void transmit_data(BMU_data measurements,uint32_t status);
lcockerton62 1:51477fe4851b 18 void read_temperature_sensors(BMU_data &measurements);
lcockerton62 0:0a5f554d2a16 19 void update_SOC();
lcockerton62 0:0a5f554d2a16 20 void init();
lcockerton62 1:51477fe4851b 21 void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address);
lcockerton62 1:51477fe4851b 22 uint16_t read_EEPROM_startup(BMU_data &measurements);
lcockerton62 1:51477fe4851b 23 uint32_t check_measurements(BMU_data &measurements);
lcockerton62 1:51477fe4851b 24 void take_measurements(BMU_data &measurements);
lcockerton62 0:0a5f554d2a16 25
lcockerton62 0:0a5f554d2a16 26 CAN can(CAN_READ_PIN, CAN_WRITE_PIN); //Create a CAN object to handle CAN comms
DasSidG 4:9050c5d6925e 27 uint16_t eeprom_start_address; //the initial address where we store/read SoC values
lcockerton62 0:0a5f554d2a16 28
lcockerton62 1:51477fe4851b 29 Timeout loop_delay;
lcockerton62 1:51477fe4851b 30 bool delay_finished = false;
lcockerton62 2:94716229ecc3 31
lcockerton62 2:94716229ecc3 32 void loop_delay_callback(void)
lcockerton62 2:94716229ecc3 33 {
lcockerton62 1:51477fe4851b 34 delay_finished = true;
lcockerton62 1:51477fe4851b 35 }
lcockerton62 1:51477fe4851b 36
lcockerton62 0:0a5f554d2a16 37 int main()
lcockerton62 0:0a5f554d2a16 38 {
lcockerton62 1:51477fe4851b 39 BMU_data measurements;
lcockerton62 1:51477fe4851b 40 uint16_t current_EEPROM_address;
lcockerton62 1:51477fe4851b 41 uint32_t status;
lcockerton62 0:0a5f554d2a16 42 int c = 0;
lcockerton62 0:0a5f554d2a16 43 init();
DasSidG 4:9050c5d6925e 44 current_EEPROM_address = read_EEPROM_startup(measurements); // Read from the eeprom at startup to fill in the values of SoC
DasSidG 4:9050c5d6925e 45 ltc2943.accumulatedCharge(measurements.percentage_SOC); // Initialise the LTC2943 with the current state of charge
DasSidG 4:9050c5d6925e 46
lcockerton62 1:51477fe4851b 47 while (true) {
lcockerton62 2:94716229ecc3 48
lcockerton62 1:51477fe4851b 49 // Take measurements from the sensors
lcockerton62 1:51477fe4851b 50 take_measurements(measurements);
lcockerton62 0:0a5f554d2a16 51 // Dont want to read the temperature sensors during each iteration of the loop
lcockerton62 1:51477fe4851b 52 if (c == 0) {
lcockerton62 1:51477fe4851b 53 read_temperature_sensors(measurements);
lcockerton62 1:51477fe4851b 54 } else if(c >= 4) {
lcockerton62 0:0a5f554d2a16 55 c = -1;
lcockerton62 0:0a5f554d2a16 56 }
lcockerton62 0:0a5f554d2a16 57 c++;
lcockerton62 0:0a5f554d2a16 58
lcockerton62 1:51477fe4851b 59 // Check data for errors
lcockerton62 1:51477fe4851b 60 status = check_measurements(measurements);
lcockerton62 1:51477fe4851b 61
lcockerton62 0:0a5f554d2a16 62 // Update the SOC
lcockerton62 0:0a5f554d2a16 63 update_SOC();
lcockerton62 0:0a5f554d2a16 64
lcockerton62 1:51477fe4851b 65 //Store data in the eeprom
lcockerton62 1:51477fe4851b 66 write_SOC_EEPROM(measurements, current_EEPROM_address);
lcockerton62 0:0a5f554d2a16 67
lcockerton62 5:793afeef45dc 68 // CAN bus
lcockerton62 1:51477fe4851b 69 transmit_data(measurements,status);
lcockerton62 0:0a5f554d2a16 70
lcockerton62 0:0a5f554d2a16 71 // Conserve power - enter a low powered mode
lcockerton62 2:94716229ecc3 72 delay_finished = false;
lcockerton62 1:51477fe4851b 73 loop_delay.attach(loop_delay_callback, LOOP_DELAY_S);
lcockerton62 1:51477fe4851b 74 while (!delay_finished) sleep();
lcockerton62 0:0a5f554d2a16 75 }
lcockerton62 0:0a5f554d2a16 76 }
lcockerton62 0:0a5f554d2a16 77
lcockerton62 1:51477fe4851b 78 void transmit_data(BMU_data measurements, uint32_t status)
lcockerton62 0:0a5f554d2a16 79 {
msharma97 9:82ba050a7e13 80 CANMessage msg;
lcockerton62 0:0a5f554d2a16 81 /*
lcockerton62 0:0a5f554d2a16 82 Place all of the collected data onto the CAN bus
lcockerton62 0:0a5f554d2a16 83 */
lcockerton62 5:793afeef45dc 84 // Send cell voltages
msharma97 9:82ba050a7e13 85 //voltages sent in sets of 4 + one cmy data set
msharma97 9:82ba050a7e13 86 int repeating_unit_length = NO_READINGS_PER_CMU /4 + 1;
lcockerton62 1:51477fe4851b 87 for(int i= 0; i < NO_CMUS; i++) {
msharma97 9:82ba050a7e13 88 //createVoltageTelemetry(i + 2 , measurements.cell_voltages[i].first_cell_voltages);
msharma97 9:82ba050a7e13 89 //createVoltageTelemetry(i + 3, measurements.cell_voltages[i].last_cell_voltages);
msharma97 9:82ba050a7e13 90 //input id is offset, data structure is info, voltage, voltage, ......
msharma97 9:82ba050a7e13 91 //
msharma97 9:82ba050a7e13 92 msg = createVoltageTelemetry(repeating_unit_length*i+2, measures.cell_voltages[i].voltages);
msharma97 9:82ba050a7e13 93 can.write(msg);
msharma97 9:82ba050a7e13 94 //+4 - 4 cell voltages sent per measurement
msharma97 9:82ba050a7e13 95 msg = createVoltageTelemetry(repeating_unit_length*i+3, measures.cell_voltages[i].voltages + 4);
msharma97 9:82ba050a7e13 96 can.write(msg);
msharma97 9:82ba050a7e13 97 msg = createVoltageTelemetry(repeating_unit_length*i+4, measures.cell_voltages[i].voltages + 8);
msharma97 9:82ba050a7e13 98 can.write(msg);
msharma97 9:82ba050a7e13 99
msharma97 9:82ba050a7e13 100
lcockerton62 1:51477fe4851b 101 }
lcockerton62 1:51477fe4851b 102
lcockerton62 1:51477fe4851b 103 // Create SOC CAN message
lcockerton62 1:51477fe4851b 104 createPackSOC(measurements.SOC, measurements.percentage_SOC);
lcockerton62 0:0a5f554d2a16 105
lcockerton62 1:51477fe4851b 106 // Min/max cell voltages
lcockerton62 1:51477fe4851b 107 createCellVoltageMAXMIN(measurements.max_cell_voltage, measurements.min_cell_voltage);
lcockerton62 2:94716229ecc3 108
lcockerton62 1:51477fe4851b 109 // Min/Max cell temperature
lcockerton62 1:51477fe4851b 110 createCellTemperatureMAXMIN(measurements.min_cell_temp,measurements.max_cell_temp);
lcockerton62 2:94716229ecc3 111
lcockerton62 2:94716229ecc3 112 // Battery voltage and current
lcockerton62 5:793afeef45dc 113 // @TODO add the voltage
lcockerton62 1:51477fe4851b 114 createBatteryVI(measurements.battery_voltage,measurements.battery_current);
lcockerton62 2:94716229ecc3 115
lcockerton62 1:51477fe4851b 116 //Extended battery pack status
lcockerton62 1:51477fe4851b 117 createExtendedBatteryPackStatus(status);
lcockerton62 2:94716229ecc3 118
lcockerton62 0:0a5f554d2a16 119 }
lcockerton62 0:0a5f554d2a16 120
lcockerton62 1:51477fe4851b 121 uint16_t read_EEPROM_startup(BMU_data &measurements)
lcockerton62 0:0a5f554d2a16 122 {
lcockerton62 1:51477fe4851b 123 /* The first page of the EEPROM, specifically the first 2 addresses store a
lcockerton62 1:51477fe4851b 124 pointer of the first memory location of measurement data. The EEPROM only has a finite number of
lcockerton62 1:51477fe4851b 125 read/write cycles which is why we aren't writing to the same location throughout
lcockerton62 1:51477fe4851b 126 */
lcockerton62 5:793afeef45dc 127
lcockerton62 1:51477fe4851b 128 uint16_t start_address;
lcockerton62 1:51477fe4851b 129 char start_address_array[2];
lcockerton62 1:51477fe4851b 130 char SOC_out[8]; // 4 bytes for the 2 floats one is SOC and the other % charge
lcockerton62 1:51477fe4851b 131 float *fp1,*fp2; // temporary storage for float conversion
lcockerton62 1:51477fe4851b 132
lcockerton62 1:51477fe4851b 133 // Get a pointer to the start address for the data stored in the eeprom
lcockerton62 1:51477fe4851b 134 i2c_page_read(0x0000,2,start_address_array);
lcockerton62 1:51477fe4851b 135
lcockerton62 1:51477fe4851b 136 // Read the data from this address
lcockerton62 1:51477fe4851b 137 start_address = (start_address_array[1]<< 8) | start_address_array[0]; // mbed little endian follow this convention
lcockerton62 1:51477fe4851b 138 i2c_page_read(start_address, 8,SOC_out);
lcockerton62 0:0a5f554d2a16 139
lcockerton62 1:51477fe4851b 140 // Convert the SOC_out values back into floats
lcockerton62 1:51477fe4851b 141 fp1 = (float*)(&SOC_out[0]);
lcockerton62 1:51477fe4851b 142 fp2 = (float*)(&SOC_out[4]);
lcockerton62 1:51477fe4851b 143 measurements.SOC = *fp1;
lcockerton62 1:51477fe4851b 144 measurements.percentage_SOC = *fp2;
lcockerton62 1:51477fe4851b 145
lcockerton62 1:51477fe4851b 146 // Select the next address to write to
lcockerton62 1:51477fe4851b 147 start_address += 0x0040;
lcockerton62 1:51477fe4851b 148 if(start_address > MAX_WRITE_ADDRESS) {
lcockerton62 5:793afeef45dc 149 start_address = START_WRITE_ADDRESS; // Loop to the start of the eeprom
lcockerton62 1:51477fe4851b 150 }
lcockerton62 1:51477fe4851b 151
lcockerton62 5:793afeef45dc 152 /*@TODO need to include a CRC check for the address pointer for the scenario
lcockerton62 5:793afeef45dc 153 when power is removed and we are writing to the eeprom*/
lcockerton62 1:51477fe4851b 154 // write the new address to location 0x0000
lcockerton62 1:51477fe4851b 155 start_address_array[0] = start_address | 0x00FF;
lcockerton62 1:51477fe4851b 156 start_address_array[1] = start_address >> 8;
lcockerton62 1:51477fe4851b 157 i2c_page_write(0x0000, 2, start_address_array);
lcockerton62 1:51477fe4851b 158
lcockerton62 1:51477fe4851b 159 return start_address;
lcockerton62 0:0a5f554d2a16 160 }
lcockerton62 0:0a5f554d2a16 161
lcockerton62 1:51477fe4851b 162 void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address)
lcockerton62 0:0a5f554d2a16 163 {
lcockerton62 1:51477fe4851b 164 char data_out[8];
lcockerton62 1:51477fe4851b 165 float *fp1,*fp2;
lcockerton62 1:51477fe4851b 166
lcockerton62 1:51477fe4851b 167 fp1 = (float*)(&measurements.SOC);
lcockerton62 1:51477fe4851b 168 fp2 = (float*)(&measurements.percentage_SOC);
lcockerton62 0:0a5f554d2a16 169
lcockerton62 1:51477fe4851b 170 for(int i = 0; i < 4; i++ ) {
lcockerton62 1:51477fe4851b 171 data_out[i] = *fp1;
lcockerton62 1:51477fe4851b 172 fp1++;
lcockerton62 1:51477fe4851b 173 }
lcockerton62 1:51477fe4851b 174 for(int j = 4; j < 7; j++ ) {
lcockerton62 1:51477fe4851b 175 data_out[j] = *fp2;
lcockerton62 1:51477fe4851b 176 fp2++;
lcockerton62 1:51477fe4851b 177 }
lcockerton62 1:51477fe4851b 178 i2c_page_write(start_address, 8,data_out);
lcockerton62 0:0a5f554d2a16 179 }
lcockerton62 0:0a5f554d2a16 180
lcockerton62 1:51477fe4851b 181 void read_temperature_sensors(BMU_data &measurements)
lcockerton62 0:0a5f554d2a16 182 {
lcockerton62 1:51477fe4851b 183 float min_temperature;
lcockerton62 1:51477fe4851b 184 float max_temperature;
lcockerton62 1:51477fe4851b 185
lcockerton62 1:51477fe4851b 186 probe[0]->convert_temperature(DS1820::all_devices);
lcockerton62 1:51477fe4851b 187 min_temperature = probe[0]->temperature('C');
lcockerton62 1:51477fe4851b 188 max_temperature = min_temperature; // Initially set the max and min temperature equal
lcockerton62 1:51477fe4851b 189 for (int i=1; i<devices_found; i++) {
lcockerton62 2:94716229ecc3 190
lcockerton62 1:51477fe4851b 191 measurements.temperature_measurements[i].ID = i;
lcockerton62 1:51477fe4851b 192 measurements.temperature_measurements[i].measurement = probe[i] ->temperature('C');
lcockerton62 2:94716229ecc3 193
lcockerton62 1:51477fe4851b 194 if(measurements.temperature_measurements[i].measurement > max_temperature) {
lcockerton62 1:51477fe4851b 195 max_temperature = measurements.temperature_measurements[i].measurement;
lcockerton62 2:94716229ecc3 196 } else if (measurements.temperature_measurements[i].measurement < min_temperature) {
lcockerton62 1:51477fe4851b 197 min_temperature = measurements.temperature_measurements[i].measurement;
lcockerton62 1:51477fe4851b 198 }
lcockerton62 1:51477fe4851b 199 }
lcockerton62 1:51477fe4851b 200 measurements.max_cell_temp.temperature = max_temperature;
lcockerton62 1:51477fe4851b 201 measurements.min_cell_temp.temperature = min_temperature;
lcockerton62 0:0a5f554d2a16 202 }
lcockerton62 0:0a5f554d2a16 203
lcockerton62 0:0a5f554d2a16 204 void update_SOC()
lcockerton62 0:0a5f554d2a16 205 {
lcockerton62 1:51477fe4851b 206 // Update the SOC value
lcockerton62 0:0a5f554d2a16 207 }
lcockerton62 0:0a5f554d2a16 208
lcockerton62 0:0a5f554d2a16 209
lcockerton62 1:51477fe4851b 210 uint32_t check_measurements(BMU_data &measurements)
lcockerton62 1:51477fe4851b 211 {
lcockerton62 1:51477fe4851b 212 uint32_t status;
lcockerton62 2:94716229ecc3 213
lcockerton62 2:94716229ecc3 214 if(measurements.max_cell_voltage.voltage > MAX_CELL_VOLTAGE) {
lcockerton62 2:94716229ecc3 215 status = status | CELL_OVER_VOLTAGE;
lcockerton62 2:94716229ecc3 216 } else if (measurements.min_cell_voltage.voltage < MIN_CELL_VOLTAGE) {
lcockerton62 1:51477fe4851b 217 status = status | CELL_UNDER_VOLTAGE;
lcockerton62 2:94716229ecc3 218 } else if (measurements.max_cell_temp.temperature > MAX_CELL_TEMPERATURE) {
lcockerton62 1:51477fe4851b 219 status = status | CELL_OVER_TEMPERATURE;
lcockerton62 1:51477fe4851b 220 }
lcockerton62 2:94716229ecc3 221
lcockerton62 1:51477fe4851b 222 /*
lcockerton62 1:51477fe4851b 223 @TODO also include errors for:
lcockerton62 1:51477fe4851b 224 *untrusted measurement
lcockerton62 1:51477fe4851b 225 *CMU timeout
lcockerton62 1:51477fe4851b 226 *SOC not valid
lcockerton62 1:51477fe4851b 227 */
lcockerton62 1:51477fe4851b 228 return status;
lcockerton62 1:51477fe4851b 229 }
lcockerton62 1:51477fe4851b 230
lcockerton62 1:51477fe4851b 231 void take_measurements(BMU_data &measurements)
lcockerton62 1:51477fe4851b 232 {
maxv008 6:b567fcb604aa 233 uint16_t cellvoltages[NO_CMUS][12];
maxv008 6:b567fcb604aa 234 //TODO Use LTC6804_acquireVoltage to fill this array, and then properly format
maxv008 6:b567fcb604aa 235 //it to be sent over CAN
maxv008 6:b567fcb604aa 236
maxv008 7:d00f4433cea9 237 LTC6804_acquireVoltage(cellvoltages);
maxv008 7:d00f4433cea9 238
maxv008 7:d00f4433cea9 239
lcockerton62 2:94716229ecc3 240 // Here collect all measured data from the sensors
lcockerton62 1:51477fe4851b 241 /*
lcockerton62 5:793afeef45dc 242 * TODO Cell voltages
lcockerton62 1:51477fe4851b 243 */
DasSidG 4:9050c5d6925e 244
DasSidG 4:9050c5d6925e 245 //Current, SoC
DasSidG 4:9050c5d6925e 246 measurements.battery_current = (uint32_t) ltc2943.current()*1000; //*1000 to converet to mA
DasSidG 4:9050c5d6925e 247 measurements.percentage_SOC = ltc2943.accumulatedCharge();
DasSidG 4:9050c5d6925e 248 measurements.SOC = (measurements.percentage_SOC /100) * BATTERY_CAPACITY;
DasSidG 4:9050c5d6925e 249
msharma97 9:82ba050a7e13 250 for(int i=0; i<NO_CMUS; i++){
msharma97 9:82ba050a7e13 251 for(int j=0; j<12; j++){
msharma97 9:82ba050a7e13 252 measurements.cell_voltages[i][j] = cellvoltages[i][j] / 10;
msharma97 9:82ba050a7e13 253 }
msharma97 9:82ba050a7e13 254 }
msharma97 9:82ba050a7e13 255
msharma97 9:82ba050a7e13 256
lcockerton62 1:51477fe4851b 257 }
lcockerton62 1:51477fe4851b 258
lcockerton62 0:0a5f554d2a16 259 void init()
lcockerton62 0:0a5f554d2a16 260 {
lcockerton62 1:51477fe4851b 261 temperature_init(); // Initialise the temperature sensors
DasSidG 4:9050c5d6925e 262 LTC2943_initialise(); //Initialises the fixed parameters of the LTC2943
lcockerton62 0:0a5f554d2a16 263 }
lcockerton62 0:0a5f554d2a16 264