Has base BMU code but sends dummy temperature and voltage readings to test CAN

Dependencies:   CUER_CAN DS1820 LTC2943 LTC6804 mbed

Fork of BMS_BMUCore_Max by CUER

Committer:
maxv008
Date:
Sun Jul 02 01:45:39 2017 +0000
Revision:
14:e0e88a009f4c
Parent:
13:7b42af989cd1
Child:
15:e901aff1f5b3
Added a proper unique identification to the temperature CAN. Implemented an interrupt based CAN read setup, currently configured with Dummy data and test code that will be cleaned up in a future commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lcockerton62 0:0a5f554d2a16 1 #include "mbed.h"
lcockerton62 0:0a5f554d2a16 2 #include "CANParserBMU.h"
lcockerton62 0:0a5f554d2a16 3 #include "Data_Types_BMU.h"
lcockerton62 0:0a5f554d2a16 4 #include "CAN_Data.h"
lcockerton62 0:0a5f554d2a16 5 #include "CAN_IDs.h"
lcockerton62 1:51477fe4851b 6 #include "EEPROM_I2C.h"
lcockerton62 1:51477fe4851b 7 #include "Temperature.h"
DasSidG 4:9050c5d6925e 8 #include "LTC2943_Read.h"
maxv008 10:1079f8e52d65 9 #include "Cell_Voltage.h"
maxv008 7:d00f4433cea9 10 #include "SPI_I2C_Parser.h"
lcockerton62 0:0a5f554d2a16 11
msharma97 9:82ba050a7e13 12
lcockerton62 0:0a5f554d2a16 13 using namespace CAN_IDs;
lcockerton62 0:0a5f554d2a16 14
lcockerton62 0:0a5f554d2a16 15 // Function definitions
lcockerton62 1:51477fe4851b 16 void transmit_data(BMU_data measurements,uint32_t status);
lcockerton62 1:51477fe4851b 17 void read_temperature_sensors(BMU_data &measurements);
lcockerton62 0:0a5f554d2a16 18 void update_SOC();
lcockerton62 0:0a5f554d2a16 19 void init();
maxv008 14:e0e88a009f4c 20 void interruptHandler();
maxv008 14:e0e88a009f4c 21 void CANDataSentCallback();
lcockerton62 1:51477fe4851b 22 void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address);
lcockerton62 1:51477fe4851b 23 uint16_t read_EEPROM_startup(BMU_data &measurements);
lcockerton62 1:51477fe4851b 24 uint32_t check_measurements(BMU_data &measurements);
lcockerton62 1:51477fe4851b 25 void take_measurements(BMU_data &measurements);
maxv008 14:e0e88a009f4c 26 void test_read_CAN_buffer();
DasSidG 12:fa9b1a459e47 27 bool test_read_voltage_CAN(uint16_t readings[], int can_ids[]);
maxv008 10:1079f8e52d65 28 void test_CAN_send();
maxv008 10:1079f8e52d65 29 void test_CAN_read();
lcockerton62 0:0a5f554d2a16 30
lcockerton62 0:0a5f554d2a16 31 CAN can(CAN_READ_PIN, CAN_WRITE_PIN); //Create a CAN object to handle CAN comms
maxv008 14:e0e88a009f4c 32 CANMessage buffer[CAN_BUFFER_SIZE]; //CAN receive buffer
maxv008 14:e0e88a009f4c 33 bool safe_to_write[CAN_BUFFER_SIZE]; //Semaphore bit indicating that it's safe to write to the software buffer
maxv008 14:e0e88a009f4c 34 bool CAN_data_sent = false;
maxv008 14:e0e88a009f4c 35
DasSidG 4:9050c5d6925e 36 uint16_t eeprom_start_address; //the initial address where we store/read SoC values
lcockerton62 0:0a5f554d2a16 37
lcockerton62 1:51477fe4851b 38 Timeout loop_delay;
lcockerton62 1:51477fe4851b 39 bool delay_finished = false;
lcockerton62 2:94716229ecc3 40
maxv008 14:e0e88a009f4c 41
lcockerton62 2:94716229ecc3 42 void loop_delay_callback(void)
lcockerton62 2:94716229ecc3 43 {
lcockerton62 1:51477fe4851b 44 delay_finished = true;
lcockerton62 1:51477fe4851b 45 }
lcockerton62 1:51477fe4851b 46
lcockerton62 0:0a5f554d2a16 47 int main()
DasSidG 11:cf2db05cfa56 48 {
lcockerton62 1:51477fe4851b 49 BMU_data measurements;
lcockerton62 1:51477fe4851b 50 uint16_t current_EEPROM_address;
lcockerton62 1:51477fe4851b 51 uint32_t status;
DasSidG 12:fa9b1a459e47 52 uint16_t volt_readings[36];
DasSidG 12:fa9b1a459e47 53 int can_ids[9];
maxv008 10:1079f8e52d65 54
DasSidG 12:fa9b1a459e47 55
maxv008 14:e0e88a009f4c 56 /**while(true)
maxv008 10:1079f8e52d65 57 {
DasSidG 12:fa9b1a459e47 58 for (int i = 0; i < 9; ++i) {
DasSidG 12:fa9b1a459e47 59 while(!test_read_voltage_CAN(&volt_readings[(i*4)], &can_ids[i]));
DasSidG 12:fa9b1a459e47 60 }
DasSidG 12:fa9b1a459e47 61
DasSidG 12:fa9b1a459e47 62 for (int i = 0; i < 36; ++i) {
DasSidG 12:fa9b1a459e47 63 printf("Cellvoltage %d = %d, CAN ID is %d \r\n", i, volt_readings[i], can_ids[i/4]);
DasSidG 12:fa9b1a459e47 64 volt_readings[i] = -1;
DasSidG 12:fa9b1a459e47 65 can_ids[i/4] = 0;
DasSidG 12:fa9b1a459e47 66 }
DasSidG 12:fa9b1a459e47 67 printf("\r\n");
DasSidG 12:fa9b1a459e47 68
maxv008 14:e0e88a009f4c 69 } */
lcockerton62 0:0a5f554d2a16 70 init();
maxv008 10:1079f8e52d65 71
DasSidG 11:cf2db05cfa56 72
DasSidG 11:cf2db05cfa56 73
DasSidG 11:cf2db05cfa56 74 //current_EEPROM_address = read_EEPROM_startup(measurements); // Read from the eeprom at startup to fill in the values of SoC
DasSidG 11:cf2db05cfa56 75 //ltc2943.accumulatedCharge(measurements.percentage_SOC); // Initialise the LTC2943 with the current state of charge
DasSidG 4:9050c5d6925e 76
lcockerton62 1:51477fe4851b 77 while (true) {
DasSidG 11:cf2db05cfa56 78
lcockerton62 1:51477fe4851b 79 // Take measurements from the sensors
lcockerton62 1:51477fe4851b 80 take_measurements(measurements);
DasSidG 11:cf2db05cfa56 81 /*// Dont want to read the temperature sensors during each iteration of the loop
lcockerton62 1:51477fe4851b 82 if (c == 0) {
lcockerton62 1:51477fe4851b 83 read_temperature_sensors(measurements);
lcockerton62 1:51477fe4851b 84 } else if(c >= 4) {
lcockerton62 0:0a5f554d2a16 85 c = -1;
lcockerton62 0:0a5f554d2a16 86 }
lcockerton62 0:0a5f554d2a16 87 c++;
lcockerton62 0:0a5f554d2a16 88
lcockerton62 1:51477fe4851b 89 // Check data for errors
lcockerton62 1:51477fe4851b 90 status = check_measurements(measurements);
lcockerton62 1:51477fe4851b 91
lcockerton62 0:0a5f554d2a16 92 // Update the SOC
lcockerton62 0:0a5f554d2a16 93 update_SOC();
lcockerton62 0:0a5f554d2a16 94
lcockerton62 1:51477fe4851b 95 //Store data in the eeprom
lcockerton62 1:51477fe4851b 96 write_SOC_EEPROM(measurements, current_EEPROM_address);
DasSidG 11:cf2db05cfa56 97 */
lcockerton62 0:0a5f554d2a16 98
lcockerton62 5:793afeef45dc 99 // CAN bus
maxv008 14:e0e88a009f4c 100 CAN_data_sent = false;//Currently does nothing, adding this line in more places then using
maxv008 14:e0e88a009f4c 101 //while(!CAN_data_sent); in order to ensure sending completes
maxv008 14:e0e88a009f4c 102 //transmit_data(measurements,status);
maxv008 14:e0e88a009f4c 103 test_read_CAN_buffer();
DasSidG 11:cf2db05cfa56 104
DasSidG 11:cf2db05cfa56 105 /*
lcockerton62 0:0a5f554d2a16 106 // Conserve power - enter a low powered mode
lcockerton62 2:94716229ecc3 107 delay_finished = false;
lcockerton62 1:51477fe4851b 108 loop_delay.attach(loop_delay_callback, LOOP_DELAY_S);
lcockerton62 1:51477fe4851b 109 while (!delay_finished) sleep();
DasSidG 11:cf2db05cfa56 110 */
DasSidG 11:cf2db05cfa56 111
DasSidG 11:cf2db05cfa56 112 //test_CAN_send();
DasSidG 11:cf2db05cfa56 113 //test_CAN_read();
DasSidG 11:cf2db05cfa56 114 wait(1);
maxv008 10:1079f8e52d65 115 }
lcockerton62 0:0a5f554d2a16 116 }
lcockerton62 0:0a5f554d2a16 117
lcockerton62 1:51477fe4851b 118 void transmit_data(BMU_data measurements, uint32_t status)
lcockerton62 0:0a5f554d2a16 119 {
msharma97 9:82ba050a7e13 120 CANMessage msg;
lcockerton62 0:0a5f554d2a16 121 /*
lcockerton62 0:0a5f554d2a16 122 Place all of the collected data onto the CAN bus
lcockerton62 0:0a5f554d2a16 123 */
lcockerton62 5:793afeef45dc 124 // Send cell voltages
maxv008 13:7b42af989cd1 125 //voltages sent in sets of 4 + one cmu data set
msharma97 9:82ba050a7e13 126 int repeating_unit_length = NO_READINGS_PER_CMU /4 + 1;
maxv008 10:1079f8e52d65 127 for(uint16_t i= 0; i < NO_CMUS; i++) {
msharma97 9:82ba050a7e13 128 //input id is offset, data structure is info, voltage, voltage, ......
maxv008 10:1079f8e52d65 129 //This is a slightly modified version of the Tritium BMS datasheet, to add an extra voltage reading set.
maxv008 10:1079f8e52d65 130 msg = createVoltageTelemetry(repeating_unit_length*i+2, measurements.cell_voltages[i].voltages);
msharma97 9:82ba050a7e13 131 can.write(msg);
DasSidG 11:cf2db05cfa56 132 wait(0.1);
maxv008 10:1079f8e52d65 133 //CONSIDER WAITS JUST IN CASE
msharma97 9:82ba050a7e13 134 //+4 - 4 cell voltages sent per measurement
maxv008 10:1079f8e52d65 135 msg = createVoltageTelemetry(repeating_unit_length*i+3, measurements.cell_voltages[i].voltages + 4);
msharma97 9:82ba050a7e13 136 can.write(msg);
DasSidG 11:cf2db05cfa56 137 wait(0.1);
maxv008 10:1079f8e52d65 138 msg = createVoltageTelemetry(repeating_unit_length*i+4, measurements.cell_voltages[i].voltages + 8);
msharma97 9:82ba050a7e13 139 can.write(msg);
DasSidG 11:cf2db05cfa56 140 wait(0.1);
DasSidG 11:cf2db05cfa56 141 //printf("Message id: %d \r\n", msg.id);
lcockerton62 1:51477fe4851b 142 }
maxv008 13:7b42af989cd1 143
maxv008 13:7b42af989cd1 144 //Transmitting all of the individual probes:
maxv008 14:e0e88a009f4c 145 //for(uint8_t i = 0; i < devices_found; i++) REPLACED BY DUMMY LOOP
maxv008 14:e0e88a009f4c 146 for(uint8_t i = 0; i < 10; i++)
maxv008 13:7b42af989cd1 147 {
maxv008 14:e0e88a009f4c 148 individual_temperature tempreading = measurements.temperature_measurements[i];
maxv008 14:e0e88a009f4c 149 msg = createTemperatureTelemetry(i, &tempreading.ROMID[0], tempreading.measurement);
maxv008 14:e0e88a009f4c 150 if(can.write(msg))
maxv008 14:e0e88a009f4c 151 printf("Message sent succesfully \r\n");
maxv008 14:e0e88a009f4c 152 else
maxv008 14:e0e88a009f4c 153 printf("message failed to send \r\n");
maxv008 14:e0e88a009f4c 154 individual_temperature testOut = decodeTemperatureTelemetry(msg);
maxv008 14:e0e88a009f4c 155 printf("ID[6] is %d and temp is %f \r\n",testOut.ROMID[6],testOut.measurement);
maxv008 13:7b42af989cd1 156 wait(0.1);
maxv008 13:7b42af989cd1 157 }
lcockerton62 1:51477fe4851b 158
lcockerton62 1:51477fe4851b 159 // Create SOC CAN message
lcockerton62 1:51477fe4851b 160 createPackSOC(measurements.SOC, measurements.percentage_SOC);
lcockerton62 0:0a5f554d2a16 161
lcockerton62 1:51477fe4851b 162 // Min/max cell voltages
lcockerton62 1:51477fe4851b 163 createCellVoltageMAXMIN(measurements.max_cell_voltage, measurements.min_cell_voltage);
lcockerton62 2:94716229ecc3 164
maxv008 13:7b42af989cd1 165 // Min/Max cell temperature, Currently the meaning of temp max/min is a ambiguous
maxv008 13:7b42af989cd1 166 // due to changes to Temperature reading (namely the CMU ID portion of it), @TODO change MAXMIN
lcockerton62 1:51477fe4851b 167 createCellTemperatureMAXMIN(measurements.min_cell_temp,measurements.max_cell_temp);
lcockerton62 2:94716229ecc3 168
lcockerton62 2:94716229ecc3 169 // Battery voltage and current
lcockerton62 5:793afeef45dc 170 // @TODO add the voltage
lcockerton62 1:51477fe4851b 171 createBatteryVI(measurements.battery_voltage,measurements.battery_current);
lcockerton62 2:94716229ecc3 172
lcockerton62 1:51477fe4851b 173 //Extended battery pack status
lcockerton62 1:51477fe4851b 174 createExtendedBatteryPackStatus(status);
lcockerton62 2:94716229ecc3 175
lcockerton62 0:0a5f554d2a16 176 }
lcockerton62 0:0a5f554d2a16 177
maxv008 10:1079f8e52d65 178
lcockerton62 1:51477fe4851b 179 uint16_t read_EEPROM_startup(BMU_data &measurements)
lcockerton62 0:0a5f554d2a16 180 {
lcockerton62 1:51477fe4851b 181 /* The first page of the EEPROM, specifically the first 2 addresses store a
lcockerton62 1:51477fe4851b 182 pointer of the first memory location of measurement data. The EEPROM only has a finite number of
lcockerton62 1:51477fe4851b 183 read/write cycles which is why we aren't writing to the same location throughout
lcockerton62 1:51477fe4851b 184 */
lcockerton62 5:793afeef45dc 185
lcockerton62 1:51477fe4851b 186 uint16_t start_address;
lcockerton62 1:51477fe4851b 187 char start_address_array[2];
lcockerton62 1:51477fe4851b 188 char SOC_out[8]; // 4 bytes for the 2 floats one is SOC and the other % charge
lcockerton62 1:51477fe4851b 189 float *fp1,*fp2; // temporary storage for float conversion
lcockerton62 1:51477fe4851b 190
lcockerton62 1:51477fe4851b 191 // Get a pointer to the start address for the data stored in the eeprom
lcockerton62 1:51477fe4851b 192 i2c_page_read(0x0000,2,start_address_array);
lcockerton62 1:51477fe4851b 193
lcockerton62 1:51477fe4851b 194 // Read the data from this address
lcockerton62 1:51477fe4851b 195 start_address = (start_address_array[1]<< 8) | start_address_array[0]; // mbed little endian follow this convention
lcockerton62 1:51477fe4851b 196 i2c_page_read(start_address, 8,SOC_out);
lcockerton62 0:0a5f554d2a16 197
lcockerton62 1:51477fe4851b 198 // Convert the SOC_out values back into floats
lcockerton62 1:51477fe4851b 199 fp1 = (float*)(&SOC_out[0]);
lcockerton62 1:51477fe4851b 200 fp2 = (float*)(&SOC_out[4]);
lcockerton62 1:51477fe4851b 201 measurements.SOC = *fp1;
lcockerton62 1:51477fe4851b 202 measurements.percentage_SOC = *fp2;
lcockerton62 1:51477fe4851b 203
lcockerton62 1:51477fe4851b 204 // Select the next address to write to
lcockerton62 1:51477fe4851b 205 start_address += 0x0040;
lcockerton62 1:51477fe4851b 206 if(start_address > MAX_WRITE_ADDRESS) {
lcockerton62 5:793afeef45dc 207 start_address = START_WRITE_ADDRESS; // Loop to the start of the eeprom
lcockerton62 1:51477fe4851b 208 }
lcockerton62 1:51477fe4851b 209
lcockerton62 5:793afeef45dc 210 /*@TODO need to include a CRC check for the address pointer for the scenario
lcockerton62 5:793afeef45dc 211 when power is removed and we are writing to the eeprom*/
lcockerton62 1:51477fe4851b 212 // write the new address to location 0x0000
lcockerton62 1:51477fe4851b 213 start_address_array[0] = start_address | 0x00FF;
lcockerton62 1:51477fe4851b 214 start_address_array[1] = start_address >> 8;
lcockerton62 1:51477fe4851b 215 i2c_page_write(0x0000, 2, start_address_array);
lcockerton62 1:51477fe4851b 216
lcockerton62 1:51477fe4851b 217 return start_address;
lcockerton62 0:0a5f554d2a16 218 }
lcockerton62 0:0a5f554d2a16 219
lcockerton62 1:51477fe4851b 220 void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address)
lcockerton62 0:0a5f554d2a16 221 {
lcockerton62 1:51477fe4851b 222 char data_out[8];
lcockerton62 1:51477fe4851b 223 float *fp1,*fp2;
lcockerton62 1:51477fe4851b 224
lcockerton62 1:51477fe4851b 225 fp1 = (float*)(&measurements.SOC);
lcockerton62 1:51477fe4851b 226 fp2 = (float*)(&measurements.percentage_SOC);
lcockerton62 0:0a5f554d2a16 227
lcockerton62 1:51477fe4851b 228 for(int i = 0; i < 4; i++ ) {
lcockerton62 1:51477fe4851b 229 data_out[i] = *fp1;
lcockerton62 1:51477fe4851b 230 fp1++;
lcockerton62 1:51477fe4851b 231 }
lcockerton62 1:51477fe4851b 232 for(int j = 4; j < 7; j++ ) {
lcockerton62 1:51477fe4851b 233 data_out[j] = *fp2;
lcockerton62 1:51477fe4851b 234 fp2++;
lcockerton62 1:51477fe4851b 235 }
lcockerton62 1:51477fe4851b 236 i2c_page_write(start_address, 8,data_out);
lcockerton62 0:0a5f554d2a16 237 }
lcockerton62 0:0a5f554d2a16 238
lcockerton62 1:51477fe4851b 239 void read_temperature_sensors(BMU_data &measurements)
lcockerton62 0:0a5f554d2a16 240 {
lcockerton62 1:51477fe4851b 241 float min_temperature;
lcockerton62 1:51477fe4851b 242 float max_temperature;
DasSidG 12:fa9b1a459e47 243 DigitalOut isotherm_12V_pin(ISOTHERM_12V_PIN);
DasSidG 12:fa9b1a459e47 244 isotherm_12V_pin = 1;
lcockerton62 1:51477fe4851b 245 probe[0]->convert_temperature(DS1820::all_devices);
DasSidG 12:fa9b1a459e47 246 isotherm_12V_pin = 0;
lcockerton62 1:51477fe4851b 247 min_temperature = probe[0]->temperature('C');
lcockerton62 1:51477fe4851b 248 max_temperature = min_temperature; // Initially set the max and min temperature equal
maxv008 14:e0e88a009f4c 249 /**for (int i=0; i<devices_found; i++) {
maxv008 14:e0e88a009f4c 250 for(int j = 0; j < 7; j++)
maxv008 14:e0e88a009f4c 251 measurements.temperature_measurements[i].ROMID[j] = probe[i]->ROM[j];
lcockerton62 1:51477fe4851b 252 measurements.temperature_measurements[i].measurement = probe[i] ->temperature('C');
maxv008 14:e0e88a009f4c 253
maxv008 14:e0e88a009f4c 254
maxv008 14:e0e88a009f4c 255
lcockerton62 1:51477fe4851b 256 if(measurements.temperature_measurements[i].measurement > max_temperature) {
lcockerton62 1:51477fe4851b 257 max_temperature = measurements.temperature_measurements[i].measurement;
lcockerton62 2:94716229ecc3 258 } else if (measurements.temperature_measurements[i].measurement < min_temperature) {
lcockerton62 1:51477fe4851b 259 min_temperature = measurements.temperature_measurements[i].measurement;
lcockerton62 1:51477fe4851b 260 }
DasSidG 12:fa9b1a459e47 261
DasSidG 12:fa9b1a459e47 262 printf("Device %d temperature is %3.3f degrees Celcius.\r\n",i+1 ,probe[i]->temperature('C'));
maxv008 14:e0e88a009f4c 263 }ABOVE BLOCK REPLACED BY DUMMY MEASUREMENTS */
maxv008 14:e0e88a009f4c 264 //Dummy data goes here
maxv008 14:e0e88a009f4c 265 for(int i = 0; i < 10; i++)
maxv008 14:e0e88a009f4c 266 {
maxv008 14:e0e88a009f4c 267 for(int j = 0; j < 7; j++)
maxv008 14:e0e88a009f4c 268 measurements.temperature_measurements[i].ROMID[j] = j;
maxv008 14:e0e88a009f4c 269
maxv008 14:e0e88a009f4c 270 measurements.temperature_measurements[i].measurement = 22.7 + (float) i;
maxv008 14:e0e88a009f4c 271
maxv008 14:e0e88a009f4c 272 if(measurements.temperature_measurements[i].measurement > max_temperature) {
maxv008 14:e0e88a009f4c 273 max_temperature = measurements.temperature_measurements[i].measurement;
maxv008 14:e0e88a009f4c 274 } else if (measurements.temperature_measurements[i].measurement < min_temperature) {
maxv008 14:e0e88a009f4c 275 min_temperature = measurements.temperature_measurements[i].measurement;
maxv008 14:e0e88a009f4c 276 }
lcockerton62 1:51477fe4851b 277 }
maxv008 14:e0e88a009f4c 278
maxv008 13:7b42af989cd1 279 //There is also a CMU # component of this struct, currently unfilled, perhaps not needed at all.
lcockerton62 1:51477fe4851b 280 measurements.max_cell_temp.temperature = max_temperature;
lcockerton62 1:51477fe4851b 281 measurements.min_cell_temp.temperature = min_temperature;
lcockerton62 0:0a5f554d2a16 282 }
lcockerton62 0:0a5f554d2a16 283
lcockerton62 0:0a5f554d2a16 284 void update_SOC()
lcockerton62 0:0a5f554d2a16 285 {
lcockerton62 1:51477fe4851b 286 // Update the SOC value
lcockerton62 0:0a5f554d2a16 287 }
lcockerton62 0:0a5f554d2a16 288
lcockerton62 0:0a5f554d2a16 289
lcockerton62 1:51477fe4851b 290 uint32_t check_measurements(BMU_data &measurements)
lcockerton62 1:51477fe4851b 291 {
lcockerton62 1:51477fe4851b 292 uint32_t status;
lcockerton62 2:94716229ecc3 293
lcockerton62 2:94716229ecc3 294 if(measurements.max_cell_voltage.voltage > MAX_CELL_VOLTAGE) {
lcockerton62 2:94716229ecc3 295 status = status | CELL_OVER_VOLTAGE;
lcockerton62 2:94716229ecc3 296 } else if (measurements.min_cell_voltage.voltage < MIN_CELL_VOLTAGE) {
lcockerton62 1:51477fe4851b 297 status = status | CELL_UNDER_VOLTAGE;
lcockerton62 2:94716229ecc3 298 } else if (measurements.max_cell_temp.temperature > MAX_CELL_TEMPERATURE) {
lcockerton62 1:51477fe4851b 299 status = status | CELL_OVER_TEMPERATURE;
lcockerton62 1:51477fe4851b 300 }
lcockerton62 2:94716229ecc3 301
lcockerton62 1:51477fe4851b 302 /*
lcockerton62 1:51477fe4851b 303 @TODO also include errors for:
lcockerton62 1:51477fe4851b 304 *untrusted measurement
lcockerton62 1:51477fe4851b 305 *CMU timeout
lcockerton62 1:51477fe4851b 306 *SOC not valid
lcockerton62 1:51477fe4851b 307 */
lcockerton62 1:51477fe4851b 308 return status;
lcockerton62 1:51477fe4851b 309 }
lcockerton62 1:51477fe4851b 310
lcockerton62 1:51477fe4851b 311 void take_measurements(BMU_data &measurements)
lcockerton62 1:51477fe4851b 312 {
maxv008 6:b567fcb604aa 313 uint16_t cellvoltages[NO_CMUS][12];
maxv008 6:b567fcb604aa 314 //TODO Use LTC6804_acquireVoltage to fill this array, and then properly format
maxv008 6:b567fcb604aa 315 //it to be sent over CAN
maxv008 6:b567fcb604aa 316
maxv008 14:e0e88a009f4c 317 //LTC6804_acquireVoltage(cellvoltages); REPLACED BY DUMMY DATA
maxv008 14:e0e88a009f4c 318 for(int i = 0; i < NO_CMUS; i++)
maxv008 14:e0e88a009f4c 319 {
maxv008 14:e0e88a009f4c 320 for(int j = 0; j < 12; j++)
maxv008 14:e0e88a009f4c 321 cellvoltages[i][j] = i*j; //Just to have some data variation
maxv008 14:e0e88a009f4c 322 }
maxv008 10:1079f8e52d65 323 for(int i=0; i<NO_CMUS; i++){
maxv008 10:1079f8e52d65 324 for(int j=0; j<12; j++){
maxv008 14:e0e88a009f4c 325 measurements.cell_voltages[i].voltages[j] = cellvoltages[i][j]; // / 10; REMOVED FOR DUMMY DATA
maxv008 14:e0e88a009f4c 326 //printf("Cellvoltage[%d][%d] = %d \r\n",i,j,cellvoltages[i][j]); // SAME AS ABOVE /10);
maxv008 10:1079f8e52d65 327 }
maxv008 14:e0e88a009f4c 328 }
DasSidG 4:9050c5d6925e 329
maxv008 13:7b42af989cd1 330 //Add code to take all temperature measurements and add it to measurements struct.
maxv008 13:7b42af989cd1 331 read_temperature_sensors(measurements);
maxv008 13:7b42af989cd1 332
DasSidG 4:9050c5d6925e 333 //Current, SoC
maxv008 13:7b42af989cd1 334 measurements.battery_current = (uint32_t) ltc2943.current()*1000; //*1000 to convert to mA
DasSidG 4:9050c5d6925e 335 measurements.percentage_SOC = ltc2943.accumulatedCharge();
DasSidG 4:9050c5d6925e 336 measurements.SOC = (measurements.percentage_SOC /100) * BATTERY_CAPACITY;
lcockerton62 1:51477fe4851b 337 }
lcockerton62 1:51477fe4851b 338
lcockerton62 0:0a5f554d2a16 339 void init()
lcockerton62 0:0a5f554d2a16 340 {
lcockerton62 1:51477fe4851b 341 temperature_init(); // Initialise the temperature sensors
DasSidG 4:9050c5d6925e 342 LTC2943_initialise(); //Initialises the fixed parameters of the LTC2943
maxv008 14:e0e88a009f4c 343
maxv008 14:e0e88a009f4c 344 for(int i=0; i<CAN_BUFFER_SIZE; i++)
maxv008 14:e0e88a009f4c 345 {
maxv008 14:e0e88a009f4c 346 buffer[i].id = BLANK_ID;
maxv008 14:e0e88a009f4c 347 //("%d",buffer[i].id);
maxv008 14:e0e88a009f4c 348 safe_to_write[i]= true;
maxv008 14:e0e88a009f4c 349 }
maxv008 14:e0e88a009f4c 350
maxv008 14:e0e88a009f4c 351 //Initialise CAN stuff, attach CAN interrupt handlers
maxv008 14:e0e88a009f4c 352 can.frequency(CAN_BIT_RATE); //set transmission rate to agreed bit rate (ELEC-006)
maxv008 14:e0e88a009f4c 353 can.reset(); // (FUNC-018)
maxv008 14:e0e88a009f4c 354 can.attach(&interruptHandler, CAN::RxIrq); //receive interrupt handler
maxv008 14:e0e88a009f4c 355 can.attach(&CANDataSentCallback, CAN::TxIrq); //send interrupt handler
maxv008 14:e0e88a009f4c 356
maxv008 14:e0e88a009f4c 357 }
maxv008 14:e0e88a009f4c 358
maxv008 14:e0e88a009f4c 359 void CANDataSentCallback(void) {
maxv008 14:e0e88a009f4c 360 CAN_data_sent = true;
maxv008 14:e0e88a009f4c 361 printf("Some CAN was sent \r\n");
lcockerton62 0:0a5f554d2a16 362 }
lcockerton62 0:0a5f554d2a16 363
maxv008 14:e0e88a009f4c 364 void interruptHandler()
maxv008 14:e0e88a009f4c 365 {
maxv008 14:e0e88a009f4c 366 CANMessage msg;
maxv008 14:e0e88a009f4c 367 if(can.read(msg))
maxv008 14:e0e88a009f4c 368 printf("interrupt reached with id %d \r\n",msg.id);
maxv008 14:e0e88a009f4c 369 else
maxv008 14:e0e88a009f4c 370 printf("reading failed \r\n");
maxv008 14:e0e88a009f4c 371 for(int i=0; i<CAN_BUFFER_SIZE; i++) {
maxv008 14:e0e88a009f4c 372 if((buffer[i].id == msg.id || buffer[i].id==BLANK_ID) && safe_to_write[i]) {
maxv008 14:e0e88a009f4c 373 //("id %d added to buffer \r\n", msg.id);
maxv008 14:e0e88a009f4c 374 buffer[i] = msg;
maxv008 14:e0e88a009f4c 375 //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 376 return;
maxv008 14:e0e88a009f4c 377 }
maxv008 14:e0e88a009f4c 378 }
maxv008 14:e0e88a009f4c 379 }
maxv008 14:e0e88a009f4c 380
maxv008 14:e0e88a009f4c 381 void test_read_CAN_buffer()
maxv008 14:e0e88a009f4c 382 {
maxv008 14:e0e88a009f4c 383 //Import the data from the buffer into a non-volatile, more usable format
maxv008 14:e0e88a009f4c 384 CAN_Data can_data[CAN_BUFFER_SIZE]; //container for all of the raw data
maxv008 14:e0e88a009f4c 385 int received_CAN_IDs[CAN_BUFFER_SIZE]; //needed to keep track of which IDs we've received so far
maxv008 14:e0e88a009f4c 386 for (int i = 0; i<CAN_BUFFER_SIZE; ++i)
maxv008 14:e0e88a009f4c 387 {
maxv008 14:e0e88a009f4c 388 safe_to_write[i] = false;
maxv008 14:e0e88a009f4c 389 can_data[i].importCANData(buffer[i]);
maxv008 14:e0e88a009f4c 390 received_CAN_IDs[i] = buffer[i].id;
maxv008 14:e0e88a009f4c 391 safe_to_write[i] = true;
maxv008 14:e0e88a009f4c 392 }
maxv008 14:e0e88a009f4c 393
maxv008 14:e0e88a009f4c 394 for(int i = 0; i < CAN_BUFFER_SIZE; i++)
maxv008 14:e0e88a009f4c 395 {
maxv008 14:e0e88a009f4c 396 individual_temperature testpoint;
maxv008 14:e0e88a009f4c 397 if(!(buffer[i].id == BLANK_ID) && buffer[i].id < 10)
maxv008 14:e0e88a009f4c 398 {
maxv008 14:e0e88a009f4c 399 testpoint = decodeTemperatureTelemetry(buffer[i]);
maxv008 14:e0e88a009f4c 400 printf("Temperature is %f and ID[5] is %d \r\n", testpoint.measurement, testpoint.ROMID[5]);
maxv008 14:e0e88a009f4c 401 }else if(buffer[i].id == 1538)
maxv008 14:e0e88a009f4c 402 printf("id 1538 was recieved\r\n");
maxv008 14:e0e88a009f4c 403 }
maxv008 14:e0e88a009f4c 404 }
DasSidG 12:fa9b1a459e47 405 bool test_read_voltage_CAN(uint16_t readings[], int can_ids[])
maxv008 10:1079f8e52d65 406 {
maxv008 10:1079f8e52d65 407 CANMessage msg;
maxv008 10:1079f8e52d65 408 int can_id;
maxv008 10:1079f8e52d65 409 int offset;
maxv008 10:1079f8e52d65 410 int first_index;
maxv008 10:1079f8e52d65 411 int second_index;
maxv008 10:1079f8e52d65 412
maxv008 10:1079f8e52d65 413 if(can.read(msg))
maxv008 10:1079f8e52d65 414 {
maxv008 10:1079f8e52d65 415 for(int i =0; i < 4; i++)
maxv008 10:1079f8e52d65 416 {
maxv008 10:1079f8e52d65 417 readings[i] = (msg.data[2 * i]) + (msg.data[2*i+1] << 8); //Since data is 8 8bit ints not 4 16 bit ones
maxv008 10:1079f8e52d65 418 }
DasSidG 12:fa9b1a459e47 419 can_id = msg.id;
DasSidG 12:fa9b1a459e47 420 can_ids[0] = msg.id;
DasSidG 12:fa9b1a459e47 421
DasSidG 11:cf2db05cfa56 422 offset = can_id - 1536; //1536 = 0x600
maxv008 10:1079f8e52d65 423 first_index = (offset - 1)/4; //offset of 2,3,4 is CMU 1; 6,7,8, is CMU 2; etc.
DasSidG 11:cf2db05cfa56 424 second_index = ((offset - 1) % 4) - 1; //Makes it so 0,1,2 represent each voltage set //SID: subtracted 1 to make it work
DasSidG 12:fa9b1a459e47 425
DasSidG 12:fa9b1a459e47 426 return true;
maxv008 10:1079f8e52d65 427 }
maxv008 10:1079f8e52d65 428 else
DasSidG 12:fa9b1a459e47 429 return false;
maxv008 10:1079f8e52d65 430 }
maxv008 10:1079f8e52d65 431
maxv008 10:1079f8e52d65 432 void test_CAN_send()
maxv008 10:1079f8e52d65 433 {
maxv008 10:1079f8e52d65 434 CANMessage msg;
DasSidG 11:cf2db05cfa56 435 char value = 142;
maxv008 10:1079f8e52d65 436 msg = CANMessage(1, &value,1);
maxv008 10:1079f8e52d65 437 if(can.write(msg))
maxv008 10:1079f8e52d65 438 printf("Succesfully sent %d \r\n", value);
maxv008 10:1079f8e52d65 439 else
maxv008 10:1079f8e52d65 440 printf("Sending Failed \r\n");
maxv008 10:1079f8e52d65 441 }
maxv008 10:1079f8e52d65 442
maxv008 10:1079f8e52d65 443 void test_CAN_read()
maxv008 10:1079f8e52d65 444 {
maxv008 10:1079f8e52d65 445 CANMessage msg;
maxv008 10:1079f8e52d65 446 if(can.read(msg))
maxv008 10:1079f8e52d65 447 printf("Successfully recieved %d \r\n", msg.data[0]);
maxv008 10:1079f8e52d65 448 else
maxv008 10:1079f8e52d65 449 printf("Reading Failed \r\n");
maxv008 10:1079f8e52d65 450 }