Cell voltages fork (SoC)

Dependencies:   CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl

Committer:
DasSidG
Date:
Mon Sep 04 00:48:19 2017 +0000
Revision:
64:2878a6b3eea8
Parent:
63:2b425006e95d
Child:
65:95f21910cf9d
Changed 'abs' to 'fabs' when applied to the current to allow the offline compiling to work properly (was complaining that 'abs' was defined ambiguously)

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