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