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:
maxv008
Date:
Sat Jan 28 14:41:19 2017 +0000
Revision:
6:b567fcb604aa
Parent:
5:793afeef45dc
Child:
7:d00f4433cea9
Added Library to acquire cell voltages and balance cells, still need to implement storing them for CAN use.

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