Cell voltages fork (SoC)

Dependencies:   CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl

Committer:
DasSidG
Date:
Fri Aug 25 18:06:20 2017 +0000
Revision:
59:e8ac52b71d8d
Parent:
58:40d318825b0d
Child:
60:ba1f45b46f97
publish

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