Cell voltages fork (SoC)

Dependencies:   CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl

Committer:
DasSidG
Date:
Sat Jul 22 11:41:19 2017 +0000
Revision:
39:34be1b8f46be
Parent:
38:b1f5bfe38d70
Child:
40:0753cbb8bc6a
Replaced 'wait' with a 'sleep' function at the end of the loop. Not sure how much power this saves; needs more investigation.

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 10:1079f8e52d65 9 #include "Cell_Voltage.h"
maxv008 7:d00f4433cea9 10 #include "SPI_I2C_Parser.h"
maxv008 25:1fe8a42f8a6d 11 #include "LTC2943.h"
lcockerton62 0:0a5f554d2a16 12
DasSidG 38:b1f5bfe38d70 13 #define DEBUG 0
msharma97 9:82ba050a7e13 14
lcockerton62 0:0a5f554d2a16 15 using namespace CAN_IDs;
lcockerton62 0:0a5f554d2a16 16
lcockerton62 0:0a5f554d2a16 17 // Function definitions
lcockerton62 1:51477fe4851b 18 void transmit_data(BMU_data measurements,uint32_t status);
lcockerton62 1:51477fe4851b 19 void read_temperature_sensors(BMU_data &measurements);
lcockerton62 0:0a5f554d2a16 20 void update_SOC();
lcockerton62 0:0a5f554d2a16 21 void init();
maxv008 14:e0e88a009f4c 22 void interruptHandler();
maxv008 14:e0e88a009f4c 23 void CANDataSentCallback();
lcockerton62 1:51477fe4851b 24 void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address);
lcockerton62 1:51477fe4851b 25 uint16_t read_EEPROM_startup(BMU_data &measurements);
maxv008 32:5b82679b2e6f 26 void reset_EEPROM(float init_SOC, float init_SOC_Percent);
lcockerton62 1:51477fe4851b 27 uint32_t check_measurements(BMU_data &measurements);
maxv008 23:a1af4439c1fc 28 uint32_t take_measurements(BMU_data &measurements);
maxv008 14:e0e88a009f4c 29 void test_read_CAN_buffer();
DasSidG 12:fa9b1a459e47 30 bool test_read_voltage_CAN(uint16_t readings[], int can_ids[]);
maxv008 10:1079f8e52d65 31 void test_CAN_send();
maxv008 10:1079f8e52d65 32 void test_CAN_read();
maxv008 35:be07fef5db72 33 bool check_EEPROM_PEC(char start_address_array[], char SOC_out[]);
lcockerton62 0:0a5f554d2a16 34
lcockerton62 0:0a5f554d2a16 35 CAN can(CAN_READ_PIN, CAN_WRITE_PIN); //Create a CAN object to handle CAN comms
maxv008 14:e0e88a009f4c 36 CANMessage buffer[CAN_BUFFER_SIZE]; //CAN receive buffer
maxv008 14:e0e88a009f4c 37 bool safe_to_write[CAN_BUFFER_SIZE]; //Semaphore bit indicating that it's safe to write to the software buffer
maxv008 14:e0e88a009f4c 38 bool CAN_data_sent = false;
maxv008 14:e0e88a009f4c 39
maxv008 20:a1a1bfc938da 40 //Global array to store most recently obtained voltage and temp measurement:
maxv008 17:94dd9a0d3870 41 CMU_voltage voltage_readings[NO_CMUS];
maxv008 20:a1a1bfc938da 42 individual_temperature templist[NO_TEMPERATURE_SENSORS];
maxv008 28:f1f882bd1653 43 uint32_t status;
DasSidG 38:b1f5bfe38d70 44 int temperature_counter = TEMPERATURE_MEASUREMENT_FREQ;
DasSidG 38:b1f5bfe38d70 45
maxv008 17:94dd9a0d3870 46
DasSidG 4:9050c5d6925e 47 uint16_t eeprom_start_address; //the initial address where we store/read SoC values
lcockerton62 0:0a5f554d2a16 48
lcockerton62 1:51477fe4851b 49 Timeout loop_delay;
lcockerton62 1:51477fe4851b 50 bool delay_finished = false;
lcockerton62 2:94716229ecc3 51
DasSidG 39:34be1b8f46be 52 void loop_delay_callback(void) {
DasSidG 39:34be1b8f46be 53 delay_finished = true;
DasSidG 39:34be1b8f46be 54 }
DasSidG 39:34be1b8f46be 55
maxv008 28:f1f882bd1653 56 //The following is to initialize reading tests, can be removed when needed
maxv008 28:f1f882bd1653 57 float packSOC;
maxv008 28:f1f882bd1653 58 float packSOCPercentage;
maxv008 28:f1f882bd1653 59 pack_voltage_extremes minVolt;
maxv008 28:f1f882bd1653 60 pack_voltage_extremes maxVolt;
maxv008 28:f1f882bd1653 61 pack_temperature_extremes minTemp;
maxv008 28:f1f882bd1653 62 pack_temperature_extremes maxTemp;
maxv008 31:888b2602aab2 63 float batteryCurrent; uint32_t batteryVoltage;
maxv008 14:e0e88a009f4c 64
lcockerton62 0:0a5f554d2a16 65 int main()
DasSidG 11:cf2db05cfa56 66 {
lcockerton62 1:51477fe4851b 67 BMU_data measurements;
lcockerton62 1:51477fe4851b 68 uint16_t current_EEPROM_address;
DasSidG 12:fa9b1a459e47 69 uint16_t volt_readings[36];
DasSidG 12:fa9b1a459e47 70 int can_ids[9];
maxv008 10:1079f8e52d65 71
lcockerton62 0:0a5f554d2a16 72 init();
maxv008 10:1079f8e52d65 73
maxv008 35:be07fef5db72 74 //current_EEPROM_address = 0x0040; //reset has no way of setting the current address for rest of code.
maxv008 35:be07fef5db72 75 //reset_EEPROM(1,100); //Used to completely initialize EEPROM as if it has never been touched
maxv008 35:be07fef5db72 76 current_EEPROM_address = read_EEPROM_startup(measurements); // Read from the eeprom at startup to fill in the values of SoC
DasSidG 36:1b23c0692f54 77 if (DEBUG) printf("Current EEPROM Address %d \r\n", current_EEPROM_address);
DasSidG 36:1b23c0692f54 78 if (DEBUG) printf("SOC is %f and SOC Percentage is %f \r\n", measurements.SOC, measurements.percentage_SOC);
maxv008 35:be07fef5db72 79 ltc2943.accumulatedCharge(measurements.percentage_SOC); // Initialise the LTC2943 with the current state of charge
DasSidG 4:9050c5d6925e 80
lcockerton62 1:51477fe4851b 81 while (true) {
DasSidG 11:cf2db05cfa56 82
maxv008 35:be07fef5db72 83 Timer t;
maxv008 35:be07fef5db72 84 t.start();
maxv008 35:be07fef5db72 85
maxv008 35:be07fef5db72 86 status = take_measurements(measurements);
maxv008 35:be07fef5db72 87 // Dont want to read the temperature sensors during each iteration of the loop
lcockerton62 0:0a5f554d2a16 88
lcockerton62 1:51477fe4851b 89 //Store data in the eeprom
lcockerton62 1:51477fe4851b 90 write_SOC_EEPROM(measurements, current_EEPROM_address);
maxv008 35:be07fef5db72 91
lcockerton62 5:793afeef45dc 92 // CAN bus
maxv008 14:e0e88a009f4c 93 CAN_data_sent = false;//Currently does nothing, adding this line in more places then using
maxv008 14:e0e88a009f4c 94 //while(!CAN_data_sent); in order to ensure sending completes
maxv008 35:be07fef5db72 95 transmit_data(measurements,status);
maxv008 31:888b2602aab2 96 //test_read_CAN_buffer();
DasSidG 11:cf2db05cfa56 97
DasSidG 39:34be1b8f46be 98
lcockerton62 0:0a5f554d2a16 99 // Conserve power - enter a low powered mode
lcockerton62 2:94716229ecc3 100 delay_finished = false;
lcockerton62 1:51477fe4851b 101 loop_delay.attach(loop_delay_callback, LOOP_DELAY_S);
lcockerton62 1:51477fe4851b 102 while (!delay_finished) sleep();
DasSidG 39:34be1b8f46be 103
DasSidG 39:34be1b8f46be 104 //wait(1);
DasSidG 39:34be1b8f46be 105 if (debug) printf("Loop time is %d \r\n", t.read_ms());
maxv008 10:1079f8e52d65 106 }
lcockerton62 0:0a5f554d2a16 107 }
lcockerton62 0:0a5f554d2a16 108
lcockerton62 1:51477fe4851b 109 void transmit_data(BMU_data measurements, uint32_t status)
lcockerton62 0:0a5f554d2a16 110 {
msharma97 9:82ba050a7e13 111 CANMessage msg;
lcockerton62 0:0a5f554d2a16 112 /*
lcockerton62 0:0a5f554d2a16 113 Place all of the collected data onto the CAN bus
lcockerton62 0:0a5f554d2a16 114 */
lcockerton62 5:793afeef45dc 115 // Send cell voltages
maxv008 13:7b42af989cd1 116 //voltages sent in sets of 4 + one cmu data set
msharma97 9:82ba050a7e13 117 int repeating_unit_length = NO_READINGS_PER_CMU /4 + 1;
maxv008 10:1079f8e52d65 118 for(uint16_t i= 0; i < NO_CMUS; i++) {
msharma97 9:82ba050a7e13 119 //input id is offset, data structure is info, voltage, voltage, ......
maxv008 10:1079f8e52d65 120 //This is a slightly modified version of the Tritium BMS datasheet, to add an extra voltage reading set.
maxv008 10:1079f8e52d65 121 msg = createVoltageTelemetry(repeating_unit_length*i+2, measurements.cell_voltages[i].voltages);
msharma97 9:82ba050a7e13 122 can.write(msg);
DasSidG 36:1b23c0692f54 123 if (DEBUG) printf("Voltage Message id: %d \r\n", msg.id);
maxv008 17:94dd9a0d3870 124 //+4 - 4 cell voltages sent per measurement, simple pointer arithmetic
maxv008 10:1079f8e52d65 125 msg = createVoltageTelemetry(repeating_unit_length*i+3, measurements.cell_voltages[i].voltages + 4);
msharma97 9:82ba050a7e13 126 can.write(msg);
DasSidG 36:1b23c0692f54 127 if (DEBUG) printf("Voltage Message id: %d \r\n", msg.id);
maxv008 10:1079f8e52d65 128 msg = createVoltageTelemetry(repeating_unit_length*i+4, measurements.cell_voltages[i].voltages + 8);
msharma97 9:82ba050a7e13 129 can.write(msg);
DasSidG 36:1b23c0692f54 130 if (DEBUG) printf("Voltage Message id: %d \r\n", msg.id);
lcockerton62 1:51477fe4851b 131 }
maxv008 13:7b42af989cd1 132
maxv008 13:7b42af989cd1 133 //Transmitting all of the individual probes:
DasSidG 38:b1f5bfe38d70 134
DasSidG 38:b1f5bfe38d70 135 if (temperature_counter == TEMPERATURE_MEASUREMENT_FREQ) {
DasSidG 38:b1f5bfe38d70 136 for(uint8_t i = 0; i < devices_found; i++)
DasSidG 38:b1f5bfe38d70 137 {
DasSidG 38:b1f5bfe38d70 138 individual_temperature tempreading = measurements.temperature_measurements[i];
DasSidG 38:b1f5bfe38d70 139 msg = createTemperatureTelemetry(i, &tempreading.ROMID[0], tempreading.measurement);
DasSidG 38:b1f5bfe38d70 140 individual_temperature testOut = decodeTemperatureTelemetry(msg);
DasSidG 38:b1f5bfe38d70 141 if (DEBUG) printf("Temperature reading sent (CAN ID = %d): (%f,%d) \r\n", msg.id, testOut.measurement, testOut.ID);
DasSidG 38:b1f5bfe38d70 142 if(can.write(msg));
DasSidG 38:b1f5bfe38d70 143 else
DasSidG 38:b1f5bfe38d70 144 if (DEBUG) printf("Sending Temperature Failed for some reason \r\n");
DasSidG 38:b1f5bfe38d70 145 }
maxv008 13:7b42af989cd1 146 }
lcockerton62 1:51477fe4851b 147
lcockerton62 1:51477fe4851b 148 // Create SOC CAN message
maxv008 23:a1af4439c1fc 149 msg = createPackSOC(measurements.SOC, measurements.percentage_SOC);
maxv008 23:a1af4439c1fc 150 can.write(msg);
DasSidG 36:1b23c0692f54 151 if (DEBUG) printf("SOC is %f and percentage SOC is %f and id is %d \r\n", measurements.SOC, measurements.percentage_SOC, msg.id);
maxv008 23:a1af4439c1fc 152
lcockerton62 1:51477fe4851b 153 // Min/max cell voltages
maxv008 23:a1af4439c1fc 154 msg = createCellVoltageMAXMIN(measurements.max_cell_voltage, measurements.min_cell_voltage);
maxv008 23:a1af4439c1fc 155 can.write(msg);
maxv008 23:a1af4439c1fc 156
maxv008 23:a1af4439c1fc 157 // Min/Max cell temperatures
maxv008 23:a1af4439c1fc 158 msg = createCellTemperatureMAXMIN(measurements.min_cell_temp, true);
maxv008 23:a1af4439c1fc 159 can.write(msg);
maxv008 23:a1af4439c1fc 160 msg = createCellTemperatureMAXMIN(measurements.max_cell_temp, false);
maxv008 23:a1af4439c1fc 161 can.write(msg);
maxv008 31:888b2602aab2 162 wait(0.1); //WAITS ABSOLUTELY NECESSARY! values may be changed. Limit to how fast msg can be sent
lcockerton62 2:94716229ecc3 163 // Battery voltage and current
maxv008 23:a1af4439c1fc 164 msg = createBatteryVI(measurements.battery_voltage,measurements.battery_current);
maxv008 31:888b2602aab2 165 can.write(msg);
DasSidG 36:1b23c0692f54 166 if (DEBUG) printf("Sent Battery voltage %d and current %f with id %d \r\n",decodeBatteryVoltage(msg),decodeBatteryCurrent(msg),msg.id);
maxv008 23:a1af4439c1fc 167
lcockerton62 1:51477fe4851b 168 //Extended battery pack status
maxv008 23:a1af4439c1fc 169 msg = createExtendedBatteryPackStatus(status);
maxv008 23:a1af4439c1fc 170 can.write(msg);
maxv008 31:888b2602aab2 171
DasSidG 36:1b23c0692f54 172 if (DEBUG) printf("Sent battery pack status with value %d \r\n", status);
DasSidG 36:1b23c0692f54 173
maxv008 31:888b2602aab2 174 msg = createBMSHeartbeat(0, 0);
maxv008 31:888b2602aab2 175 can.write(msg);
lcockerton62 0:0a5f554d2a16 176 }
lcockerton62 0:0a5f554d2a16 177
maxv008 10:1079f8e52d65 178
lcockerton62 1:51477fe4851b 179 uint16_t read_EEPROM_startup(BMU_data &measurements)
lcockerton62 0:0a5f554d2a16 180 {
lcockerton62 1:51477fe4851b 181 /* The first page of the EEPROM, specifically the first 2 addresses store a
lcockerton62 1:51477fe4851b 182 pointer of the first memory location of measurement data. The EEPROM only has a finite number of
lcockerton62 1:51477fe4851b 183 read/write cycles which is why we aren't writing to the same location throughout
lcockerton62 1:51477fe4851b 184 */
lcockerton62 30:d90895e96226 185 uint16_t start_address1;
lcockerton62 30:d90895e96226 186 uint16_t start_address2;
maxv008 35:be07fef5db72 187 char start_address_array1[4];
maxv008 35:be07fef5db72 188 char start_address_array2[4];
lcockerton62 22:2df45c818786 189 char SOC_out[10]; // 4 bytes for the 2 floats one is SOC and the other % charge
lcockerton62 30:d90895e96226 190 bool is_first_read_true = 0;
lcockerton62 30:d90895e96226 191 bool is_second_read_true = 0;
maxv008 35:be07fef5db72 192
maxv008 35:be07fef5db72 193 union float2bytes { float f; char b[sizeof(float)]; };
maxv008 35:be07fef5db72 194 float2bytes SOC_union;
maxv008 35:be07fef5db72 195 float2bytes SOC_Percent_union;
lcockerton62 30:d90895e96226 196
lcockerton62 30:d90895e96226 197 // Get a pointer to the start address for the data stored in the eeprom
maxv008 35:be07fef5db72 198 i2c_page_read(0x0000, 4, start_address_array1);
DasSidG 36:1b23c0692f54 199 if (DEBUG) printf("\r\n\ Start address (%d,%d) \r\n \r\n", start_address_array1[0], start_address_array1[1]);
maxv008 35:be07fef5db72 200 i2c_page_read(0x0004, 4, start_address_array2);
lcockerton62 30:d90895e96226 201
maxv008 35:be07fef5db72 202 is_first_read_true = check_EEPROM_PEC(start_address_array1, SOC_out);
lcockerton62 30:d90895e96226 203
lcockerton62 30:d90895e96226 204 if(is_first_read_true){
maxv008 35:be07fef5db72 205 for ( int i=0; i < sizeof(float); i++ ) {
maxv008 35:be07fef5db72 206 SOC_union.b[i] = SOC_out[i];
maxv008 35:be07fef5db72 207 }
maxv008 35:be07fef5db72 208
maxv008 35:be07fef5db72 209 for ( int i=0; i < sizeof(float); i++ ) {
maxv008 35:be07fef5db72 210 SOC_Percent_union.b[i] = SOC_out[i + sizeof(float)];
maxv008 35:be07fef5db72 211 }
maxv008 35:be07fef5db72 212 measurements.SOC = SOC_union.f;
maxv008 35:be07fef5db72 213 measurements.percentage_SOC = SOC_Percent_union.f;
lcockerton62 30:d90895e96226 214 }
lcockerton62 30:d90895e96226 215 else{
maxv008 35:be07fef5db72 216 is_second_read_true = check_EEPROM_PEC(start_address_array2, SOC_out);
lcockerton62 30:d90895e96226 217
lcockerton62 30:d90895e96226 218 if(is_second_read_true){
maxv008 35:be07fef5db72 219 for ( int i=0; i < sizeof(float); i++ ) {
maxv008 35:be07fef5db72 220 SOC_union.b[i] = SOC_out[i];
maxv008 35:be07fef5db72 221 }
maxv008 35:be07fef5db72 222
maxv008 35:be07fef5db72 223 for ( int i=0; i < sizeof(float); i++ ) {
maxv008 35:be07fef5db72 224 SOC_Percent_union.b[i] = SOC_out[i + sizeof(float)];
maxv008 35:be07fef5db72 225 }
maxv008 35:be07fef5db72 226 measurements.SOC = SOC_union.f;
maxv008 35:be07fef5db72 227 measurements.percentage_SOC = SOC_Percent_union.f;
lcockerton62 30:d90895e96226 228 }
lcockerton62 30:d90895e96226 229 }
lcockerton62 30:d90895e96226 230
lcockerton62 30:d90895e96226 231 if(is_second_read_true || is_first_read_true){
lcockerton62 30:d90895e96226 232 // Select the next address to write to
maxv008 35:be07fef5db72 233 start_address1 = (start_address_array1[1] << 8) | (start_address_array1[0]);
maxv008 35:be07fef5db72 234 start_address2 = (start_address_array2[1] << 8) | (start_address_array2[0]);
maxv008 35:be07fef5db72 235 start_address1 += 0x0040;
maxv008 32:5b82679b2e6f 236 start_address2 += 0x0040; //Also each SOC is taking 0xA space, so 0x15 should be sufficient offset
maxv008 35:be07fef5db72 237 if(start_address2 > MAX_WRITE_ADDRESS) { //Check second start address since it is the larger value.
DasSidG 36:1b23c0692f54 238 if (DEBUG) printf("Resetting start_address \r\n");
lcockerton62 30:d90895e96226 239 start_address1 = START_WRITE_ADDRESS; // Loop to the start of the eeprom
lcockerton62 30:d90895e96226 240 start_address2 = START_WRITE_ADDRESS + SECOND_ADDRESS_OFFSET; // Write this data SECOND_ADDRESS_OFFSET memory locations later than the first set // (this was chosen since only 10 bytes are written to memory
lcockerton62 30:d90895e96226 241 }
maxv008 35:be07fef5db72 242 start_address_array1[0] = start_address1 & 0x00FF;
maxv008 35:be07fef5db72 243 start_address_array1[1] = start_address1 >> 8;
maxv008 35:be07fef5db72 244 start_address_array2[0] = start_address2 & 0x00FF;
maxv008 32:5b82679b2e6f 245 start_address_array2[1] = start_address2 >> 8;
maxv008 35:be07fef5db72 246 //PEC for new address
maxv008 35:be07fef5db72 247 uint16_t pec_address1 = pec15_calc(2, (uint8_t*)start_address_array1);
maxv008 35:be07fef5db72 248 uint16_t pec_address2 = pec15_calc(2, (uint8_t*)start_address_array2);
maxv008 35:be07fef5db72 249 start_address_array1[2] = (char) (pec_address1 >> 8);
maxv008 35:be07fef5db72 250 start_address_array1[3] = (char) (pec_address1);
maxv008 35:be07fef5db72 251 start_address_array2[2] = (char) (pec_address2 >> 8);
maxv008 35:be07fef5db72 252 start_address_array2[3] = (char) (pec_address2);
lcockerton62 30:d90895e96226 253
lcockerton62 30:d90895e96226 254 // Write the new location of the address to memory
maxv008 35:be07fef5db72 255 wait_ms(10);
maxv008 35:be07fef5db72 256 i2c_page_write(0x0000, 4, start_address_array1);
maxv008 33:44b241c7b2c1 257 wait_ms(10);
maxv008 35:be07fef5db72 258 i2c_page_write(0x0004, 4, start_address_array2);
lcockerton62 30:d90895e96226 259
maxv008 35:be07fef5db72 260 write_SOC_EEPROM(measurements, start_address1); //Initializes new memory location to avoid PEC if reset without taking measurements.
lcockerton62 30:d90895e96226 261 return start_address1;
lcockerton62 30:d90895e96226 262 }
lcockerton62 30:d90895e96226 263 else{
DasSidG 36:1b23c0692f54 264 if (DEBUG) printf("PEC error"); //@TODO an error flag should be raised since both values have failed
maxv008 32:5b82679b2e6f 265
lcockerton62 30:d90895e96226 266 }
maxv008 32:5b82679b2e6f 267 return -1; //Will end up as maximum integer, just indicating an error.
maxv008 32:5b82679b2e6f 268 }
maxv008 32:5b82679b2e6f 269
maxv008 32:5b82679b2e6f 270 void reset_EEPROM(float init_SOC, float init_SOC_Percent)
maxv008 32:5b82679b2e6f 271 {
maxv008 32:5b82679b2e6f 272 char start_address_array1[2]; //Purely for testing
DasSidG 34:65fd6a72106f 273 char start_address_array2[2]; //Purely for testing
maxv008 33:44b241c7b2c1 274 char test_float_array[10];
maxv008 32:5b82679b2e6f 275 //Very first addresses to use
maxv008 35:be07fef5db72 276 char first_address[4] = {0x40,0,0,0}; //Address 0x0040, PEC section left blank to start
maxv008 35:be07fef5db72 277 char second_address[4] = {first_address[0] + SECOND_ADDRESS_OFFSET,0,0,0};
maxv008 32:5b82679b2e6f 278 uint16_t address1 = (first_address[1] << 8) | first_address[0];
maxv008 32:5b82679b2e6f 279 uint16_t address2 = (second_address[1] << 8) | second_address[0];
maxv008 35:be07fef5db72 280
maxv008 35:be07fef5db72 281 //PEC stuff for the addresses
maxv008 35:be07fef5db72 282 uint16_t pec_address1 = pec15_calc(2, (uint8_t*)first_address);
maxv008 35:be07fef5db72 283 uint16_t pec_address2 = pec15_calc(2, (uint8_t*)second_address);
maxv008 35:be07fef5db72 284 first_address[2] = (char) (pec_address1 >> 8);
maxv008 35:be07fef5db72 285 first_address[3] = (char) (pec_address1);
maxv008 35:be07fef5db72 286 second_address[2] = (char) (pec_address2 >> 8);
maxv008 35:be07fef5db72 287 second_address[3] = (char) (pec_address2);
maxv008 32:5b82679b2e6f 288
maxv008 35:be07fef5db72 289 i2c_page_write(0x0000, 4, first_address);
maxv008 33:44b241c7b2c1 290 wait_ms(10);
maxv008 35:be07fef5db72 291 i2c_page_write(0x0004, 4, second_address); //This initializes addresses
maxv008 32:5b82679b2e6f 292 //Next segment is for putting initial SOC in:
maxv008 33:44b241c7b2c1 293 wait_ms(10);
maxv008 32:5b82679b2e6f 294
maxv008 32:5b82679b2e6f 295 char data_out[10];
maxv008 32:5b82679b2e6f 296 uint16_t data_pec;
DasSidG 34:65fd6a72106f 297
DasSidG 34:65fd6a72106f 298 union float2bytes { float f; char b[sizeof(float)]; };
DasSidG 34:65fd6a72106f 299
DasSidG 34:65fd6a72106f 300 float2bytes init_SOC_union;
DasSidG 34:65fd6a72106f 301 float2bytes init_SOC_Percent_union;
DasSidG 34:65fd6a72106f 302
DasSidG 34:65fd6a72106f 303 init_SOC_union.f = init_SOC;
DasSidG 34:65fd6a72106f 304 for ( int i=0; i < sizeof(float); i++ ) {
DasSidG 34:65fd6a72106f 305 data_out[i] = init_SOC_union.b[i];
DasSidG 34:65fd6a72106f 306 }
DasSidG 34:65fd6a72106f 307
DasSidG 34:65fd6a72106f 308 init_SOC_Percent_union.f = init_SOC_Percent;
DasSidG 34:65fd6a72106f 309 for ( int i=0; i < sizeof(float); i++ ) {
DasSidG 34:65fd6a72106f 310 data_out[i+sizeof(float)] = init_SOC_Percent_union.b[i];
DasSidG 34:65fd6a72106f 311 }
maxv008 32:5b82679b2e6f 312
maxv008 32:5b82679b2e6f 313 data_pec = pec15_calc(8, ((uint8_t*)data_out)); // Calculate the pec and then write it to memory
maxv008 32:5b82679b2e6f 314 data_out[8] = (char)(data_pec >> 8);
maxv008 32:5b82679b2e6f 315 data_out[9] = (char)(data_pec);
DasSidG 34:65fd6a72106f 316
maxv008 32:5b82679b2e6f 317 i2c_page_write(address1, 10,data_out);
maxv008 33:44b241c7b2c1 318 wait_ms(10);
maxv008 32:5b82679b2e6f 319 i2c_page_write(address2, 10,data_out);
DasSidG 34:65fd6a72106f 320 wait_ms(10);
maxv008 35:be07fef5db72 321 i2c_page_read(0x0000,4,start_address_array1);
DasSidG 34:65fd6a72106f 322 wait_ms(10);
maxv008 35:be07fef5db72 323 i2c_page_read(0x0004,4,start_address_array2);
DasSidG 36:1b23c0692f54 324 if (DEBUG) printf("Start address 1 is (%x,%x) \r\n \r\n", start_address_array1[0], start_address_array1[1]);
DasSidG 36:1b23c0692f54 325 if (DEBUG) printf("Start address 2 is (%x,%x) \r\n \r\n", start_address_array2[0], start_address_array2[1]);
maxv008 33:44b241c7b2c1 326 wait_ms(10);
DasSidG 34:65fd6a72106f 327 i2c_page_read(address1,10,test_float_array);
maxv008 35:be07fef5db72 328 /*for (int i = 0; i < 10; ++i) {
DasSidG 34:65fd6a72106f 329 printf("test_float array %d is %d \r\n", i, test_float_array[i]);
maxv008 35:be07fef5db72 330 }*/
DasSidG 34:65fd6a72106f 331
DasSidG 34:65fd6a72106f 332 float2bytes rec_init_SOC_union;
DasSidG 34:65fd6a72106f 333 float2bytes rec_init_SOC_Percentage_union;
DasSidG 34:65fd6a72106f 334
DasSidG 34:65fd6a72106f 335
DasSidG 34:65fd6a72106f 336 for ( int i=0; i < sizeof(float); i++ ) {
DasSidG 34:65fd6a72106f 337 rec_init_SOC_union.b[i] = test_float_array[i];
DasSidG 34:65fd6a72106f 338 }
DasSidG 34:65fd6a72106f 339 float rec_init_SOC = rec_init_SOC_union.f;
DasSidG 34:65fd6a72106f 340
DasSidG 34:65fd6a72106f 341 for ( int i=0; i < sizeof(float); i++ ) {
DasSidG 34:65fd6a72106f 342 rec_init_SOC_Percentage_union.b[i] = test_float_array[i+4];
DasSidG 34:65fd6a72106f 343 }
DasSidG 34:65fd6a72106f 344 float rec_init_SOC_Percentage = rec_init_SOC_Percentage_union.f;
DasSidG 34:65fd6a72106f 345
DasSidG 36:1b23c0692f54 346 if (DEBUG) printf("init SOC %f \r\n \r\n", rec_init_SOC);
DasSidG 36:1b23c0692f54 347 if (DEBUG) printf("percentage SOC %f \r\n \r\n", rec_init_SOC_Percentage);
lcockerton62 30:d90895e96226 348 }
lcockerton62 30:d90895e96226 349
maxv008 35:be07fef5db72 350 bool check_EEPROM_PEC(char start_address_array[], char SOC_out[]){
lcockerton62 30:d90895e96226 351 // Helper method to check the PEC, returns 0 if the pec is wrong and 1 if the pec is correct
maxv008 35:be07fef5db72 352 uint16_t adr_recieved_pec;
maxv008 35:be07fef5db72 353 uint16_t adr_data_pec;
lcockerton62 22:2df45c818786 354 uint16_t received_pec;
lcockerton62 22:2df45c818786 355 uint16_t data_pec;
lcockerton62 30:d90895e96226 356
maxv008 35:be07fef5db72 357 //Check the PEC of the address itself
maxv008 35:be07fef5db72 358 adr_recieved_pec = (uint16_t)(start_address_array[2] << 8) + (uint16_t)start_address_array[3];
maxv008 35:be07fef5db72 359 adr_data_pec = pec15_calc(2, (uint8_t*)start_address_array);
maxv008 35:be07fef5db72 360 if(adr_recieved_pec != adr_data_pec){
DasSidG 36:1b23c0692f54 361 if (DEBUG) printf("PEC Error in address \r\n");
maxv008 35:be07fef5db72 362 return 0; //If they are equal, continue on to checking the data
maxv008 35:be07fef5db72 363 }
maxv008 35:be07fef5db72 364
lcockerton62 1:51477fe4851b 365 // Read the data from this address
maxv008 35:be07fef5db72 366 uint16_t start_address = (start_address_array[1]<< 8) | start_address_array[0]; // mbed little endian follow this convention
lcockerton62 22:2df45c818786 367 i2c_page_read(start_address, 10,SOC_out); // Reading will aquire 2 floats and a PEC for the data
lcockerton62 0:0a5f554d2a16 368
lcockerton62 22:2df45c818786 369 // Convert the SOC_out values back into floats and deal with the pec
lcockerton62 22:2df45c818786 370 received_pec = (uint16_t)(SOC_out[8]<<8) + (uint16_t)SOC_out[9];
lcockerton62 22:2df45c818786 371 data_pec = pec15_calc(8, (uint8_t*)SOC_out);
lcockerton62 22:2df45c818786 372 if(received_pec != data_pec) {
lcockerton62 30:d90895e96226 373 return 0;
lcockerton62 22:2df45c818786 374 }
lcockerton62 30:d90895e96226 375 else
lcockerton62 30:d90895e96226 376 return 1;
lcockerton62 0:0a5f554d2a16 377 }
lcockerton62 0:0a5f554d2a16 378
maxv008 35:be07fef5db72 379 //Note, this function does not check PEC of address, assumes correctness!
lcockerton62 1:51477fe4851b 380 void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address)
lcockerton62 0:0a5f554d2a16 381 {
lcockerton62 22:2df45c818786 382 char data_out[10];
maxv008 35:be07fef5db72 383 //float *fp1,*fp2;
lcockerton62 22:2df45c818786 384 uint16_t data_pec;
maxv008 35:be07fef5db72 385 union float2bytes { float f; char b[sizeof(float)]; };
maxv008 35:be07fef5db72 386 float2bytes SOC_union;
maxv008 35:be07fef5db72 387 float2bytes SOC_Percent_union;
lcockerton62 0:0a5f554d2a16 388
maxv008 35:be07fef5db72 389
maxv008 35:be07fef5db72 390 SOC_union.f = measurements.SOC;
maxv008 35:be07fef5db72 391 for ( int i=0; i < sizeof(float); i++ ) {
maxv008 35:be07fef5db72 392 data_out[i] = SOC_union.b[i];
lcockerton62 1:51477fe4851b 393 }
maxv008 35:be07fef5db72 394
maxv008 35:be07fef5db72 395 SOC_Percent_union.f = measurements.percentage_SOC;
maxv008 35:be07fef5db72 396 for ( int i=0; i < sizeof(float); i++ ) {
maxv008 35:be07fef5db72 397 data_out[i+sizeof(float)] = SOC_Percent_union.b[i];
lcockerton62 1:51477fe4851b 398 }
maxv008 35:be07fef5db72 399
lcockerton62 22:2df45c818786 400 data_pec = pec15_calc(8, ((uint8_t*)data_out)); // Calculate the pec and then write it to memory
lcockerton62 22:2df45c818786 401 data_out[8] = (char)(data_pec >> 8);
lcockerton62 22:2df45c818786 402 data_out[9] = (char)(data_pec);
maxv008 35:be07fef5db72 403 wait_ms(10); //Just in case function calling it doesnt put a wait before hand
lcockerton62 30:d90895e96226 404 i2c_page_write(start_address, 10,data_out);
maxv008 35:be07fef5db72 405 wait_ms(10);
lcockerton62 30:d90895e96226 406 i2c_page_write((start_address+SECOND_ADDRESS_OFFSET), 10,data_out); // Write the data to the backup memory location, SECOND_ADDRESS_OFFSET memory locations later
lcockerton62 0:0a5f554d2a16 407 }
lcockerton62 0:0a5f554d2a16 408
lcockerton62 1:51477fe4851b 409 void read_temperature_sensors(BMU_data &measurements)
lcockerton62 0:0a5f554d2a16 410 {
lcockerton62 1:51477fe4851b 411 float min_temperature;
maxv008 23:a1af4439c1fc 412 char min_id[8];
lcockerton62 1:51477fe4851b 413 float max_temperature;
maxv008 23:a1af4439c1fc 414 char max_id[8];
DasSidG 21:d461d58e70fc 415 isotherm_12V_pin = 1;
lcockerton62 1:51477fe4851b 416 probe[0]->convert_temperature(DS1820::all_devices);
DasSidG 21:d461d58e70fc 417
lcockerton62 1:51477fe4851b 418 min_temperature = probe[0]->temperature('C');
maxv008 23:a1af4439c1fc 419 std::memcpy(min_id, probe[0]->ROM, sizeof(char)*8); //invalid shallow copy: min_id = probe[0]->ROM;
lcockerton62 1:51477fe4851b 420 max_temperature = min_temperature; // Initially set the max and min temperature equal
maxv008 23:a1af4439c1fc 421 std::memcpy(max_id, probe[0]->ROM, sizeof(char)*8);
DasSidG 16:b2ef68c9a4fd 422 for (int i=0; i<devices_found; i++) {
maxv008 14:e0e88a009f4c 423 for(int j = 0; j < 7; j++)
maxv008 14:e0e88a009f4c 424 measurements.temperature_measurements[i].ROMID[j] = probe[i]->ROM[j];
lcockerton62 1:51477fe4851b 425 measurements.temperature_measurements[i].measurement = probe[i] ->temperature('C');
maxv008 14:e0e88a009f4c 426
lcockerton62 1:51477fe4851b 427 if(measurements.temperature_measurements[i].measurement > max_temperature) {
lcockerton62 1:51477fe4851b 428 max_temperature = measurements.temperature_measurements[i].measurement;
maxv008 23:a1af4439c1fc 429 std::memcpy(max_id, measurements.temperature_measurements[i].ROMID, sizeof(char)*8);
lcockerton62 2:94716229ecc3 430 } else if (measurements.temperature_measurements[i].measurement < min_temperature) {
lcockerton62 1:51477fe4851b 431 min_temperature = measurements.temperature_measurements[i].measurement;
maxv008 23:a1af4439c1fc 432 std::memcpy(min_id, measurements.temperature_measurements[i].ROMID, sizeof(char)*8);
lcockerton62 1:51477fe4851b 433 }
DasSidG 12:fa9b1a459e47 434
maxv008 18:521ffdd724f3 435 //printf("Device %d temperature is %3.3f degrees Celcius.\r\n",i+1 ,probe[i]->temperature('C'));
lcockerton62 1:51477fe4851b 436 }
DasSidG 21:d461d58e70fc 437 isotherm_12V_pin = 0;
maxv008 13:7b42af989cd1 438 //There is also a CMU # component of this struct, currently unfilled, perhaps not needed at all.
lcockerton62 1:51477fe4851b 439 measurements.max_cell_temp.temperature = max_temperature;
maxv008 23:a1af4439c1fc 440 std::memcpy(measurements.max_cell_temp.ROMID, max_id, sizeof(char)*8);
lcockerton62 1:51477fe4851b 441 measurements.min_cell_temp.temperature = min_temperature;
maxv008 28:f1f882bd1653 442 std::memcpy(measurements.min_cell_temp.ROMID, min_id, sizeof(char)*8);
maxv008 28:f1f882bd1653 443 delete max_id;
maxv008 28:f1f882bd1653 444 delete min_id;
lcockerton62 0:0a5f554d2a16 445 }
lcockerton62 0:0a5f554d2a16 446
lcockerton62 0:0a5f554d2a16 447 void update_SOC()
lcockerton62 0:0a5f554d2a16 448 {
lcockerton62 1:51477fe4851b 449 // Update the SOC value
maxv008 25:1fe8a42f8a6d 450 ltc2943.readAll();
lcockerton62 0:0a5f554d2a16 451 }
lcockerton62 0:0a5f554d2a16 452
lcockerton62 0:0a5f554d2a16 453
lcockerton62 1:51477fe4851b 454 uint32_t check_measurements(BMU_data &measurements)
lcockerton62 1:51477fe4851b 455 {
lcockerton62 1:51477fe4851b 456 uint32_t status;
lcockerton62 2:94716229ecc3 457
lcockerton62 2:94716229ecc3 458 if(measurements.max_cell_voltage.voltage > MAX_CELL_VOLTAGE) {
lcockerton62 2:94716229ecc3 459 status = status | CELL_OVER_VOLTAGE;
lcockerton62 2:94716229ecc3 460 } else if (measurements.min_cell_voltage.voltage < MIN_CELL_VOLTAGE) {
lcockerton62 1:51477fe4851b 461 status = status | CELL_UNDER_VOLTAGE;
lcockerton62 2:94716229ecc3 462 } else if (measurements.max_cell_temp.temperature > MAX_CELL_TEMPERATURE) {
lcockerton62 1:51477fe4851b 463 status = status | CELL_OVER_TEMPERATURE;
lcockerton62 1:51477fe4851b 464 }
lcockerton62 2:94716229ecc3 465
lcockerton62 1:51477fe4851b 466 /*
lcockerton62 1:51477fe4851b 467 @TODO also include errors for:
lcockerton62 1:51477fe4851b 468 *untrusted measurement
lcockerton62 1:51477fe4851b 469 *CMU timeout
lcockerton62 1:51477fe4851b 470 *SOC not valid
lcockerton62 1:51477fe4851b 471 */
lcockerton62 1:51477fe4851b 472 return status;
lcockerton62 1:51477fe4851b 473 }
lcockerton62 1:51477fe4851b 474
maxv008 23:a1af4439c1fc 475 //Returns the status variable
maxv008 23:a1af4439c1fc 476 uint32_t take_measurements(BMU_data &measurements)
lcockerton62 1:51477fe4851b 477 {
maxv008 6:b567fcb604aa 478 uint16_t cellvoltages[NO_CMUS][12];
DasSidG 16:b2ef68c9a4fd 479 //Use LTC6804_acquireVoltage to fill this array, and then properly format
maxv008 6:b567fcb604aa 480 //it to be sent over CAN
maxv008 6:b567fcb604aa 481
DasSidG 16:b2ef68c9a4fd 482 LTC6804_acquireVoltage(cellvoltages);
maxv008 23:a1af4439c1fc 483 pack_voltage_extremes min_voltage;
DasSidG 37:fae62a2773a1 484 pack_voltage_extremes max_voltage;
maxv008 23:a1af4439c1fc 485 min_voltage.voltage = 65535; //largest 16 bit unsigned int
maxv008 23:a1af4439c1fc 486 max_voltage.voltage = 0;
maxv008 23:a1af4439c1fc 487
DasSidG 37:fae62a2773a1 488 bool last_CMU = false;
maxv008 23:a1af4439c1fc 489 //Sets voltage readings as well as max/min voltage values.
maxv008 10:1079f8e52d65 490 for(int i=0; i<NO_CMUS; i++){
DasSidG 37:fae62a2773a1 491 if (i == (NO_CMUS - 1)) last_CMU = true;
maxv008 17:94dd9a0d3870 492 for(int j=0; j < NO_READINGS_PER_CMU; j++){
DasSidG 16:b2ef68c9a4fd 493 measurements.cell_voltages[i].voltages[j] = cellvoltages[i][j]/ 10; //To get units of mV
maxv008 17:94dd9a0d3870 494 measurements.cell_voltages[i].CMU_number = i;
DasSidG 37:fae62a2773a1 495
DasSidG 37:fae62a2773a1 496 if(!(last_CMU && j >(NO_READINGS_PER_CMU - (NUM_MISSING_CELLS + 1))))
DasSidG 37:fae62a2773a1 497 //the condition above is to account for the missing cells (not a complete set of 12) on the top CMU
maxv008 23:a1af4439c1fc 498 {
DasSidG 37:fae62a2773a1 499 if(measurements.cell_voltages[i].voltages[j] < min_voltage.voltage)
DasSidG 37:fae62a2773a1 500 {
DasSidG 37:fae62a2773a1 501 min_voltage.voltage = measurements.cell_voltages[i].voltages[j];
DasSidG 37:fae62a2773a1 502 min_voltage.CMU_number = i;
DasSidG 37:fae62a2773a1 503 min_voltage.cell_number = j;
DasSidG 37:fae62a2773a1 504 }
DasSidG 37:fae62a2773a1 505 else if(measurements.cell_voltages[i].voltages[j] > max_voltage.voltage)
DasSidG 37:fae62a2773a1 506 {
DasSidG 37:fae62a2773a1 507 max_voltage.voltage = measurements.cell_voltages[i].voltages[j];
DasSidG 37:fae62a2773a1 508 max_voltage.CMU_number = i;
DasSidG 37:fae62a2773a1 509 max_voltage.cell_number = j;
DasSidG 37:fae62a2773a1 510 }
DasSidG 37:fae62a2773a1 511 }
maxv008 10:1079f8e52d65 512 }
maxv008 23:a1af4439c1fc 513 }
maxv008 23:a1af4439c1fc 514 measurements.max_cell_voltage = max_voltage;
DasSidG 36:1b23c0692f54 515 if (DEBUG) printf("Max Voltage is %d \r\n", max_voltage.voltage);
maxv008 23:a1af4439c1fc 516 measurements.min_cell_voltage = min_voltage;
DasSidG 36:1b23c0692f54 517 if (DEBUG) printf("Min Voltage is %d \r\n", min_voltage.voltage);
DasSidG 4:9050c5d6925e 518
DasSidG 38:b1f5bfe38d70 519 //Code to take all temperature measurements and add it to measurements struct.
DasSidG 38:b1f5bfe38d70 520 //Don't need to take temperature measurements every loop though
DasSidG 38:b1f5bfe38d70 521
DasSidG 38:b1f5bfe38d70 522 if (temperature_counter ==TEMPERATURE_MEASUREMENT_FREQ) {
DasSidG 38:b1f5bfe38d70 523 read_temperature_sensors(measurements);
DasSidG 38:b1f5bfe38d70 524 temperature_counter = 0;
DasSidG 38:b1f5bfe38d70 525 }
DasSidG 38:b1f5bfe38d70 526 temperature_counter++;
DasSidG 38:b1f5bfe38d70 527
maxv008 23:a1af4439c1fc 528 // Update the SOC and take relevant measurements
maxv008 23:a1af4439c1fc 529 update_SOC();
maxv008 31:888b2602aab2 530 measurements.battery_voltage = 0;
maxv008 31:888b2602aab2 531 for(int i = 0; i < NO_CMUS; i++)
maxv008 31:888b2602aab2 532 {
maxv008 31:888b2602aab2 533 for(int j = 0; j < NO_READINGS_PER_CMU; j++)
maxv008 31:888b2602aab2 534 {
maxv008 31:888b2602aab2 535 measurements.battery_voltage += measurements.cell_voltages[i].voltages[j];
maxv008 31:888b2602aab2 536 }
maxv008 31:888b2602aab2 537 }
maxv008 31:888b2602aab2 538 measurements.battery_current =ltc2943.current() * 1000; //*1000 to convert to mA
DasSidG 4:9050c5d6925e 539 measurements.percentage_SOC = ltc2943.accumulatedCharge();
DasSidG 4:9050c5d6925e 540 measurements.SOC = (measurements.percentage_SOC /100) * BATTERY_CAPACITY;
maxv008 23:a1af4439c1fc 541
maxv008 23:a1af4439c1fc 542 // Check data for errors
maxv008 23:a1af4439c1fc 543 return check_measurements(measurements);
lcockerton62 1:51477fe4851b 544 }
lcockerton62 1:51477fe4851b 545
lcockerton62 0:0a5f554d2a16 546 void init()
lcockerton62 0:0a5f554d2a16 547 {
maxv008 18:521ffdd724f3 548 //Comment out measurement stuff with BCU testing
maxv008 31:888b2602aab2 549 temperature_init(); // Initialise the temperature sensors
DasSidG 4:9050c5d6925e 550 LTC2943_initialise(); //Initialises the fixed parameters of the LTC2943
DasSidG 15:e901aff1f5b3 551 LTC6804_init(MD_FAST, DCP_DISABLED, CELL_CH_ALL, AUX_CH_VREF2); //Initialises the LTC6804s
maxv008 31:888b2602aab2 552
maxv008 14:e0e88a009f4c 553 for(int i=0; i<CAN_BUFFER_SIZE; i++)
maxv008 14:e0e88a009f4c 554 {
maxv008 14:e0e88a009f4c 555 buffer[i].id = BLANK_ID;
maxv008 14:e0e88a009f4c 556 safe_to_write[i]= true;
maxv008 14:e0e88a009f4c 557 }
maxv008 14:e0e88a009f4c 558
maxv008 14:e0e88a009f4c 559 //Initialise CAN stuff, attach CAN interrupt handlers
maxv008 14:e0e88a009f4c 560 can.frequency(CAN_BIT_RATE); //set transmission rate to agreed bit rate (ELEC-006)
maxv008 14:e0e88a009f4c 561 can.reset(); // (FUNC-018)
maxv008 14:e0e88a009f4c 562 can.attach(&interruptHandler, CAN::RxIrq); //receive interrupt handler
maxv008 14:e0e88a009f4c 563 can.attach(&CANDataSentCallback, CAN::TxIrq); //send interrupt handler
maxv008 17:94dd9a0d3870 564
maxv008 17:94dd9a0d3870 565 //Initialize voltage array
maxv008 17:94dd9a0d3870 566 for(int i = 0; i < NO_CMUS; i++)
maxv008 17:94dd9a0d3870 567 {
maxv008 17:94dd9a0d3870 568 for(int j = 0; j < NO_READINGS_PER_CMU; j++)
maxv008 17:94dd9a0d3870 569 {
maxv008 17:94dd9a0d3870 570 voltage_readings[i].voltages[j] = 0;
maxv008 17:94dd9a0d3870 571 }
maxv008 17:94dd9a0d3870 572 }
maxv008 20:a1a1bfc938da 573 //Initialize Temperature Array
maxv008 20:a1a1bfc938da 574 for(int i = 0; i < NO_TEMPERATURE_SENSORS; i++)
maxv008 20:a1a1bfc938da 575 {
maxv008 28:f1f882bd1653 576 templist[i].measurement = INFINITY;
maxv008 20:a1a1bfc938da 577 templist[i].ID = 0;
maxv008 20:a1a1bfc938da 578 }
maxv008 28:f1f882bd1653 579 //initialize stuff used in reading test:
maxv008 28:f1f882bd1653 580 packSOC = INFINITY;
maxv008 28:f1f882bd1653 581 packSOCPercentage = INFINITY;
maxv008 28:f1f882bd1653 582
maxv008 28:f1f882bd1653 583 minVolt.voltage = 0;
maxv008 28:f1f882bd1653 584 maxVolt.voltage = 0;
maxv008 28:f1f882bd1653 585
maxv008 28:f1f882bd1653 586 minTemp.temperature = 0; minTemp.ID = 0;
maxv008 28:f1f882bd1653 587 maxTemp.temperature = 0; maxTemp.ID = 0;
maxv008 31:888b2602aab2 588
maxv008 31:888b2602aab2 589 batteryCurrent = INFINITY; batteryVoltage = 0;
maxv008 14:e0e88a009f4c 590 }
maxv008 14:e0e88a009f4c 591
maxv008 14:e0e88a009f4c 592 void CANDataSentCallback(void) {
maxv008 14:e0e88a009f4c 593 CAN_data_sent = true;
lcockerton62 0:0a5f554d2a16 594 }
lcockerton62 0:0a5f554d2a16 595
maxv008 14:e0e88a009f4c 596 void interruptHandler()
maxv008 14:e0e88a009f4c 597 {
maxv008 14:e0e88a009f4c 598 CANMessage msg;
DasSidG 16:b2ef68c9a4fd 599 can.read(msg);
maxv008 14:e0e88a009f4c 600 for(int i=0; i<CAN_BUFFER_SIZE; i++) {
maxv008 14:e0e88a009f4c 601 if((buffer[i].id == msg.id || buffer[i].id==BLANK_ID) && safe_to_write[i]) {
maxv008 14:e0e88a009f4c 602 //("id %d added to buffer \r\n", msg.id);
maxv008 14:e0e88a009f4c 603 buffer[i] = msg;
maxv008 14:e0e88a009f4c 604 //return required so that only first blank buffer entry is converted to incoming message ID each time new message ID is encountered
maxv008 14:e0e88a009f4c 605 return;
maxv008 14:e0e88a009f4c 606 }
maxv008 14:e0e88a009f4c 607 }
maxv008 14:e0e88a009f4c 608 }
maxv008 14:e0e88a009f4c 609
maxv008 14:e0e88a009f4c 610 void test_read_CAN_buffer()
maxv008 14:e0e88a009f4c 611 {
maxv008 14:e0e88a009f4c 612 //Import the data from the buffer into a non-volatile, more usable format
maxv008 14:e0e88a009f4c 613 CAN_Data can_data[CAN_BUFFER_SIZE]; //container for all of the raw data
maxv008 17:94dd9a0d3870 614 CANMessage msgArray[CAN_BUFFER_SIZE]; //Same as above but some functions take message as their parameter
maxv008 14:e0e88a009f4c 615 int received_CAN_IDs[CAN_BUFFER_SIZE]; //needed to keep track of which IDs we've received so far
maxv008 14:e0e88a009f4c 616 for (int i = 0; i<CAN_BUFFER_SIZE; ++i)
maxv008 14:e0e88a009f4c 617 {
maxv008 14:e0e88a009f4c 618 safe_to_write[i] = false;
maxv008 14:e0e88a009f4c 619 can_data[i].importCANData(buffer[i]);
maxv008 14:e0e88a009f4c 620 received_CAN_IDs[i] = buffer[i].id;
maxv008 17:94dd9a0d3870 621 msgArray[i] = buffer[i];
maxv008 14:e0e88a009f4c 622 safe_to_write[i] = true;
maxv008 31:888b2602aab2 623 //printf("Id recieved %d \r\n", buffer[i].id);
maxv008 14:e0e88a009f4c 624 }
maxv008 17:94dd9a0d3870 625
maxv008 23:a1af4439c1fc 626 //voltage and Temp and SOC readings:
maxv008 18:521ffdd724f3 627 for(int i = 0; i < CAN_BUFFER_SIZE; i++)
maxv008 18:521ffdd724f3 628 {
maxv008 18:521ffdd724f3 629 //voltage
maxv008 28:f1f882bd1653 630 if(decodeVoltageTelemetry(msgArray[i], voltage_readings))
ItsJustZi 29:44924d2b1293 631 continue;
maxv008 28:f1f882bd1653 632 //temperature
maxv008 20:a1a1bfc938da 633 if(msgArray[i].id >= 0x700)
maxv008 18:521ffdd724f3 634 {
maxv008 20:a1a1bfc938da 635 individual_temperature dataPoint = decodeTemperatureTelemetry(msgArray[i]);
maxv008 20:a1a1bfc938da 636 for(int j = 0; j < NO_TEMPERATURE_SENSORS; j++)
maxv008 20:a1a1bfc938da 637 {
maxv008 20:a1a1bfc938da 638 if(dataPoint.ID == templist[j].ID)
maxv008 20:a1a1bfc938da 639 {
maxv008 20:a1a1bfc938da 640 templist[j] = dataPoint;
maxv008 20:a1a1bfc938da 641 break;
maxv008 20:a1a1bfc938da 642 }
maxv008 20:a1a1bfc938da 643 else if(templist[j].ID == 0)
maxv008 20:a1a1bfc938da 644 {
maxv008 20:a1a1bfc938da 645 templist[j] = dataPoint;
maxv008 20:a1a1bfc938da 646 break;
maxv008 20:a1a1bfc938da 647 }
maxv008 20:a1a1bfc938da 648 }
maxv008 20:a1a1bfc938da 649
maxv008 23:a1af4439c1fc 650 }
maxv008 23:a1af4439c1fc 651 //SOC
maxv008 23:a1af4439c1fc 652 if(msgArray[i].id == 0x6F4)
maxv008 23:a1af4439c1fc 653 {
maxv008 23:a1af4439c1fc 654 packSOC = decodePackSOC(msgArray[i]);
maxv008 23:a1af4439c1fc 655 packSOCPercentage = decodePackSOCPercentage(msgArray[i]);
maxv008 28:f1f882bd1653 656 }
maxv008 23:a1af4439c1fc 657
maxv008 23:a1af4439c1fc 658 if(msgArray[i].id == BMS_BASE_ID + MIN_TEMPERATURE)
maxv008 23:a1af4439c1fc 659 minTemp = decodeCellTemperatureMAXMIN(msgArray[i]);
maxv008 23:a1af4439c1fc 660 if(msgArray[i].id == BMS_BASE_ID + MAX_TEMPERATURE)
maxv008 23:a1af4439c1fc 661 maxTemp = decodeCellTemperatureMAXMIN(msgArray[i]);
maxv008 28:f1f882bd1653 662
maxv008 23:a1af4439c1fc 663 if(msgArray[i].id == BMS_BASE_ID + MAX_MIN_VOLTAGE)
maxv008 23:a1af4439c1fc 664 {
maxv008 23:a1af4439c1fc 665 decodeCellVoltageMAXMIN(msgArray[i], minVolt, maxVolt);
maxv008 23:a1af4439c1fc 666 }
maxv008 23:a1af4439c1fc 667
maxv008 31:888b2602aab2 668 if(msgArray[i].id == BMS_BASE_ID + BATTERY_VI_ID)
maxv008 31:888b2602aab2 669 {
maxv008 31:888b2602aab2 670 batteryVoltage = decodeBatteryVoltage(msgArray[i]);
maxv008 31:888b2602aab2 671 batteryCurrent = decodeBatteryCurrent(msgArray[i]);
maxv008 31:888b2602aab2 672 }
maxv008 31:888b2602aab2 673
maxv008 23:a1af4439c1fc 674 if(msgArray[i].id == BMS_BASE_ID + BATTERY_STATUS_ID)
maxv008 28:f1f882bd1653 675 status = decodeExtendedBatteryPackStatus(msgArray[i]);
maxv008 31:888b2602aab2 676
maxv008 31:888b2602aab2 677 if(msgArray[i].id == BMS_BASE_ID)
DasSidG 36:1b23c0692f54 678 if (DEBUG) printf("BMS Heartbeat Recieved \r\n");
maxv008 28:f1f882bd1653 679 }
maxv008 18:521ffdd724f3 680 //Print obtained Readings:
maxv008 18:521ffdd724f3 681 for(int i = 0; i < NO_CMUS; i++)
maxv008 18:521ffdd724f3 682 for(int j = 0; j < 12; j++)
DasSidG 36:1b23c0692f54 683 if (DEBUG) printf("Voltage number %d for CMU %d is %d \r\n", j, i, voltage_readings[i].voltages[j]);
maxv008 17:94dd9a0d3870 684
maxv008 18:521ffdd724f3 685 for(int i = 0; i < NO_TEMPERATURE_SENSORS; i++)
DasSidG 36:1b23c0692f54 686 if (DEBUG) printf("Temperature of Sensor with ID %d is %f \r\n", templist[i].ID, templist[i].measurement);
maxv008 23:a1af4439c1fc 687
DasSidG 36:1b23c0692f54 688 if (DEBUG) printf("SOC is %f and SOC Percentage is %f \r\n", packSOC, packSOCPercentage);
maxv008 23:a1af4439c1fc 689
DasSidG 36:1b23c0692f54 690 if (DEBUG) printf("Battery Current is %f and Battery Voltage is %d \r\n", batteryCurrent, batteryVoltage);
maxv008 31:888b2602aab2 691
DasSidG 36:1b23c0692f54 692 if (DEBUG) printf("Voltage (Max,Min),(Max_CMU,Max_num) = (%d,%d),(%d,%d) \r\n", maxVolt.voltage, minVolt.voltage, maxVolt.CMU_number, maxVolt.cell_number);
maxv008 23:a1af4439c1fc 693
DasSidG 36:1b23c0692f54 694 if (DEBUG) printf("(Temperature, ID): Minimum = (%d,%d). Maximum = (%d,%d) \r\n",
maxv008 23:a1af4439c1fc 695 minTemp.temperature,minTemp.ID,maxTemp.temperature,maxTemp.ID);
maxv008 23:a1af4439c1fc 696
DasSidG 36:1b23c0692f54 697 if (DEBUG) printf("Status value is: %d \r\n", status);
maxv008 14:e0e88a009f4c 698 }
maxv008 23:a1af4439c1fc 699
DasSidG 12:fa9b1a459e47 700 bool test_read_voltage_CAN(uint16_t readings[], int can_ids[])
maxv008 10:1079f8e52d65 701 {
maxv008 10:1079f8e52d65 702 CANMessage msg;
maxv008 10:1079f8e52d65 703 int can_id;
maxv008 10:1079f8e52d65 704 int offset;
maxv008 10:1079f8e52d65 705 int first_index;
maxv008 10:1079f8e52d65 706 int second_index;
maxv008 10:1079f8e52d65 707
maxv008 10:1079f8e52d65 708 if(can.read(msg))
maxv008 10:1079f8e52d65 709 {
maxv008 10:1079f8e52d65 710 for(int i =0; i < 4; i++)
maxv008 10:1079f8e52d65 711 {
maxv008 10:1079f8e52d65 712 readings[i] = (msg.data[2 * i]) + (msg.data[2*i+1] << 8); //Since data is 8 8bit ints not 4 16 bit ones
maxv008 10:1079f8e52d65 713 }
DasSidG 12:fa9b1a459e47 714 can_id = msg.id;
DasSidG 12:fa9b1a459e47 715 can_ids[0] = msg.id;
DasSidG 12:fa9b1a459e47 716
DasSidG 11:cf2db05cfa56 717 offset = can_id - 1536; //1536 = 0x600
maxv008 10:1079f8e52d65 718 first_index = (offset - 1)/4; //offset of 2,3,4 is CMU 1; 6,7,8, is CMU 2; etc.
DasSidG 11:cf2db05cfa56 719 second_index = ((offset - 1) % 4) - 1; //Makes it so 0,1,2 represent each voltage set //SID: subtracted 1 to make it work
DasSidG 12:fa9b1a459e47 720
DasSidG 12:fa9b1a459e47 721 return true;
maxv008 10:1079f8e52d65 722 }
maxv008 10:1079f8e52d65 723 else
DasSidG 12:fa9b1a459e47 724 return false;
maxv008 10:1079f8e52d65 725 }
maxv008 10:1079f8e52d65 726
maxv008 10:1079f8e52d65 727 void test_CAN_send()
maxv008 10:1079f8e52d65 728 {
maxv008 10:1079f8e52d65 729 CANMessage msg;
DasSidG 11:cf2db05cfa56 730 char value = 142;
maxv008 10:1079f8e52d65 731 msg = CANMessage(1, &value,1);
maxv008 10:1079f8e52d65 732 if(can.write(msg))
DasSidG 36:1b23c0692f54 733 if (DEBUG) printf("Succesfully sent %d \r\n", value);
maxv008 10:1079f8e52d65 734 else
DasSidG 36:1b23c0692f54 735 if (DEBUG) printf("Sending Failed \r\n");
maxv008 10:1079f8e52d65 736 }
maxv008 10:1079f8e52d65 737
maxv008 10:1079f8e52d65 738 void test_CAN_read()
maxv008 10:1079f8e52d65 739 {
maxv008 10:1079f8e52d65 740 CANMessage msg;
maxv008 10:1079f8e52d65 741 if(can.read(msg))
DasSidG 36:1b23c0692f54 742 if (DEBUG) printf("Successfully recieved %d \r\n", msg.data[0]);
maxv008 10:1079f8e52d65 743 else
DasSidG 36:1b23c0692f54 744 if (DEBUG) printf("Reading Failed \r\n");
maxv008 10:1079f8e52d65 745 }