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:
lcockerton62
Date:
Fri Dec 30 16:01:59 2016 +0000
Revision:
1:51477fe4851b
Parent:
0:0a5f554d2a16
Child:
2:94716229ecc3
Storing SOC in EEPROM, added temperature sensors code, changed some of the data structures, added to CAN messages, added basic error status

Who changed what in which revision?

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