Cell voltages fork (SoC)

Dependencies:   CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl

Committer:
DasSidG
Date:
Sat Aug 19 19:57:30 2017 +0000
Revision:
56:decc4973d272
Parent:
52:63e84c6a9cfd
I'm confused as to why this has changes, publishing in case they are important

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