Cell voltages fork (SoC)
Dependencies: CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl
CANParserBMU.cpp@48:5c3f42c44036, 2017-07-24 (annotated)
- Committer:
- maxv008
- Date:
- Mon Jul 24 15:00:53 2017 +0000
- Revision:
- 48:5c3f42c44036
- Parent:
- 45:c288d7cbdb4a
- Child:
- 53:4277cdcff69b
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 | // Here are the functions to generate the CAN messages |
lcockerton62 | 0:0a5f554d2a16 | 2 | #include "CANParserBMU.h" |
lcockerton62 | 0:0a5f554d2a16 | 3 | #include "mbed.h" |
maxv008 | 13:7b42af989cd1 | 4 | #include "Data_Types_BMU.h" |
maxv008 | 17:94dd9a0d3870 | 5 | #include "CAN_IDs.h" |
lcockerton62 | 0:0a5f554d2a16 | 6 | |
lcockerton62 | 1:51477fe4851b | 7 | |
lcockerton62 | 0:0a5f554d2a16 | 8 | using namespace CAN_IDs; |
lcockerton62 | 0:0a5f554d2a16 | 9 | |
maxv008 | 13:7b42af989cd1 | 10 | /** |
maxv008 | 13:7b42af989cd1 | 11 | * This function is rewritten to give readings for individual probes rather than |
maxv008 | 13:7b42af989cd1 | 12 | * for specific CMU. As a consequence, 0x800 onwards is being used for these probes, |
maxv008 | 14:e0e88a009f4c | 13 | * as everything above about 0x700 is unused by the Tritium standard. The ID value |
maxv008 | 14:e0e88a009f4c | 14 | * for the probe is based on the ROM field of DS1820, entries 1-6 being the unique |
maxv008 | 14:e0e88a009f4c | 15 | * serial value. |
maxv008 | 13:7b42af989cd1 | 16 | */ |
maxv008 | 14:e0e88a009f4c | 17 | CANMessage createTemperatureTelemetry(uint8_t offset, char ProbeROM[8], float Temperature) |
lcockerton62 | 0:0a5f554d2a16 | 18 | { |
lcockerton62 | 0:0a5f554d2a16 | 19 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 20 | msg.len = 8; |
maxv008 | 13:7b42af989cd1 | 21 | msg.id = TEMPERATURE_BASE_ID + offset; // for temp it is 0x800 onwards |
lcockerton62 | 0:0a5f554d2a16 | 22 | CAN_Data data; |
lcockerton62 | 0:0a5f554d2a16 | 23 | |
maxv008 | 14:e0e88a009f4c | 24 | for(int i = 1; i <= 6; i++) //ID portion of ROM array |
maxv008 | 14:e0e88a009f4c | 25 | { |
maxv008 | 14:e0e88a009f4c | 26 | data.set_u8(i - 1, ProbeROM[i]); |
maxv008 | 14:e0e88a009f4c | 27 | } |
maxv008 | 14:e0e88a009f4c | 28 | //Conversion of float to a short, requires multiplying by 100 to not lose precision |
maxv008 | 14:e0e88a009f4c | 29 | float temp100 = Temperature * 100; |
maxv008 | 14:e0e88a009f4c | 30 | short shortTemp = (short) temp100; |
maxv008 | 14:e0e88a009f4c | 31 | data.set_16(3, shortTemp);//There seems to be an error in the function definition for set_16, (ushort instead of short) |
maxv008 | 14:e0e88a009f4c | 32 | |
lcockerton62 | 0:0a5f554d2a16 | 33 | for (int i = 0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 34 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 35 | } |
lcockerton62 | 0:0a5f554d2a16 | 36 | |
lcockerton62 | 0:0a5f554d2a16 | 37 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 38 | } |
maxv008 | 13:7b42af989cd1 | 39 | /** |
maxv008 | 13:7b42af989cd1 | 40 | * Takes a CANMessage with precondition that it stores temperature of an individual |
maxv008 | 13:7b42af989cd1 | 41 | * probe and returns an individual_temperature object containing ID and reading. |
maxv008 | 14:e0e88a009f4c | 42 | * The ID is stores in ROM array entry 1-6, other entries may be invalid. |
maxv008 | 13:7b42af989cd1 | 43 | */ |
maxv008 | 13:7b42af989cd1 | 44 | individual_temperature decodeTemperatureTelemetry(CANMessage msg) |
maxv008 | 13:7b42af989cd1 | 45 | { |
maxv008 | 13:7b42af989cd1 | 46 | individual_temperature probe_reading; |
maxv008 | 13:7b42af989cd1 | 47 | CAN_Data decode; |
maxv008 | 18:521ffdd724f3 | 48 | unsigned long fullID = 0; |
maxv008 | 13:7b42af989cd1 | 49 | |
maxv008 | 13:7b42af989cd1 | 50 | decode.importCANData(msg); |
maxv008 | 14:e0e88a009f4c | 51 | short shortTemp = decode.get_16(3); |
maxv008 | 14:e0e88a009f4c | 52 | probe_reading.measurement = ((float)shortTemp) / 100; |
maxv008 | 14:e0e88a009f4c | 53 | |
maxv008 | 14:e0e88a009f4c | 54 | for(int i = 1; i <=6; i++) |
maxv008 | 14:e0e88a009f4c | 55 | { |
maxv008 | 17:94dd9a0d3870 | 56 | probe_reading.ROMID[i] = decode.get_u8(i-1); |
maxv008 | 17:94dd9a0d3870 | 57 | fullID += (probe_reading.ROMID[i] << (8 * (i-1))); //Bit order not particularly important |
maxv008 | 14:e0e88a009f4c | 58 | } |
maxv008 | 17:94dd9a0d3870 | 59 | probe_reading.ID = fullID; |
maxv008 | 13:7b42af989cd1 | 60 | return probe_reading; |
maxv008 | 13:7b42af989cd1 | 61 | } |
lcockerton62 | 0:0a5f554d2a16 | 62 | |
msharma97 | 9:82ba050a7e13 | 63 | CANMessage createVoltageTelemetry(int offset_id, uint16_t voltage[]) |
lcockerton62 | 0:0a5f554d2a16 | 64 | { |
lcockerton62 | 0:0a5f554d2a16 | 65 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 66 | msg.len = 8; |
msharma97 | 9:82ba050a7e13 | 67 | msg.id = BMS_BASE_ID + offset_id; // for voltage 0x601 - 0x6EF @TODO |
lcockerton62 | 0:0a5f554d2a16 | 68 | CAN_Data data; |
lcockerton62 | 0:0a5f554d2a16 | 69 | |
lcockerton62 | 0:0a5f554d2a16 | 70 | data.set_u16(0, voltage[0]); |
lcockerton62 | 0:0a5f554d2a16 | 71 | data.set_u16(1, voltage[1]); |
lcockerton62 | 0:0a5f554d2a16 | 72 | data.set_u16(2, voltage[2]); |
lcockerton62 | 0:0a5f554d2a16 | 73 | data.set_u16(3, voltage[3]); |
lcockerton62 | 0:0a5f554d2a16 | 74 | |
lcockerton62 | 0:0a5f554d2a16 | 75 | for (int i = 0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 76 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 77 | } |
lcockerton62 | 0:0a5f554d2a16 | 78 | |
lcockerton62 | 0:0a5f554d2a16 | 79 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 80 | } |
maxv008 | 17:94dd9a0d3870 | 81 | /** |
maxv008 | 17:94dd9a0d3870 | 82 | * This function will properly fill the appropriate entry in an array of voltage |
maxv008 | 17:94dd9a0d3870 | 83 | * readings of the form CMU_voltage voltage[NO_CMUS]. Uses the msg ID and the standard |
maxv008 | 17:94dd9a0d3870 | 84 | * meanings of them as decided in the transmit data function (modified Tritium specs). |
maxv008 | 17:94dd9a0d3870 | 85 | * Function must only be called when the msg has a valid ID for voltage! |
maxv008 | 17:94dd9a0d3870 | 86 | */ |
maxv008 | 18:521ffdd724f3 | 87 | bool decodeVoltageTelemetry(CANMessage msg, CMU_voltage readings[NO_CMUS]) |
maxv008 | 17:94dd9a0d3870 | 88 | { |
maxv008 | 17:94dd9a0d3870 | 89 | CAN_Data voltData; |
maxv008 | 17:94dd9a0d3870 | 90 | voltData.importCANData(msg); |
maxv008 | 17:94dd9a0d3870 | 91 | int repeating_length = NO_READINGS_PER_CMU /4 + 1; |
maxv008 | 17:94dd9a0d3870 | 92 | int offset = msg.id - BMS_BASE_ID; |
ItsJustZi | 29:44924d2b1293 | 93 | if(offset <= 0 || offset >= 0x10 || offset % 4 == 1) |
maxv008 | 18:521ffdd724f3 | 94 | return false; |
maxv008 | 17:94dd9a0d3870 | 95 | |
maxv008 | 17:94dd9a0d3870 | 96 | int cellsubset = ((offset-1) % repeating_length) - 1; //Which set of 4 voltages within the CMU |
maxv008 | 17:94dd9a0d3870 | 97 | int CMU_number = (offset-1) / repeating_length; |
maxv008 | 17:94dd9a0d3870 | 98 | for(int i = 0; i < 4; i++) |
maxv008 | 17:94dd9a0d3870 | 99 | { |
maxv008 | 17:94dd9a0d3870 | 100 | readings[CMU_number].voltages[cellsubset*4 + i] = voltData.get_u16(i); |
maxv008 | 17:94dd9a0d3870 | 101 | } |
maxv008 | 18:521ffdd724f3 | 102 | return true; |
maxv008 | 17:94dd9a0d3870 | 103 | } |
lcockerton62 | 0:0a5f554d2a16 | 104 | |
lcockerton62 | 0:0a5f554d2a16 | 105 | CANMessage createPackSOC(float SOC, float percentageCharge) |
lcockerton62 | 0:0a5f554d2a16 | 106 | { |
lcockerton62 | 0:0a5f554d2a16 | 107 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 108 | msg.len = 8; |
maxv008 | 23:a1af4439c1fc | 109 | msg.id = BMS_BASE_ID + BATTERY_SOC_ID; //0x6F4 |
lcockerton62 | 0:0a5f554d2a16 | 110 | CAN_Data data; |
lcockerton62 | 0:0a5f554d2a16 | 111 | data.setLowerFloat(SOC); |
lcockerton62 | 0:0a5f554d2a16 | 112 | data.setUpperFloat(percentageCharge); |
lcockerton62 | 1:51477fe4851b | 113 | for(int i=0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 114 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 115 | } |
lcockerton62 | 1:51477fe4851b | 116 | |
lcockerton62 | 0:0a5f554d2a16 | 117 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 118 | } |
lcockerton62 | 0:0a5f554d2a16 | 119 | |
lcockerton62 | 0:0a5f554d2a16 | 120 | CANMessage createPackBalanceSOC(float SOC, float percentageCharge) |
lcockerton62 | 0:0a5f554d2a16 | 121 | { |
lcockerton62 | 0:0a5f554d2a16 | 122 | // @TODO - check is this being used?? section 5.4 trituim BMU CAN data sheet |
lcockerton62 | 0:0a5f554d2a16 | 123 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 124 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 125 | msg.id = BMS_BASE_ID + BATTERY_SOC_BASE_ID; |
lcockerton62 | 1:51477fe4851b | 126 | |
lcockerton62 | 0:0a5f554d2a16 | 127 | CAN_Data data; |
lcockerton62 | 0:0a5f554d2a16 | 128 | data.setLowerFloat(SOC); |
lcockerton62 | 0:0a5f554d2a16 | 129 | data.setUpperFloat(percentageCharge); |
lcockerton62 | 1:51477fe4851b | 130 | for(int i=0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 131 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 132 | } |
lcockerton62 | 1:51477fe4851b | 133 | |
lcockerton62 | 0:0a5f554d2a16 | 134 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 135 | } |
lcockerton62 | 0:0a5f554d2a16 | 136 | |
maxv008 | 23:a1af4439c1fc | 137 | /** |
maxv008 | 23:a1af4439c1fc | 138 | * decodePackSOC and decodePackSOCPercentage can be used with both of the SOC msg types |
maxv008 | 23:a1af4439c1fc | 139 | */ |
maxv008 | 23:a1af4439c1fc | 140 | float decodePackSOC(CANMessage msg) |
maxv008 | 23:a1af4439c1fc | 141 | { |
maxv008 | 23:a1af4439c1fc | 142 | CAN_Data data; |
maxv008 | 23:a1af4439c1fc | 143 | data.importCANData(msg); |
maxv008 | 23:a1af4439c1fc | 144 | return data.getLowerFloat(); |
maxv008 | 23:a1af4439c1fc | 145 | } |
maxv008 | 23:a1af4439c1fc | 146 | |
maxv008 | 23:a1af4439c1fc | 147 | float decodePackSOCPercentage(CANMessage msg) |
maxv008 | 23:a1af4439c1fc | 148 | { |
maxv008 | 23:a1af4439c1fc | 149 | CAN_Data data; |
maxv008 | 23:a1af4439c1fc | 150 | data.importCANData(msg); |
maxv008 | 23:a1af4439c1fc | 151 | return data.getUpperFloat(); |
maxv008 | 23:a1af4439c1fc | 152 | } |
maxv008 | 23:a1af4439c1fc | 153 | |
lcockerton62 | 1:51477fe4851b | 154 | CANMessage createCellVoltageMAXMIN(pack_voltage_extremes max_voltage, pack_voltage_extremes min_voltage) |
lcockerton62 | 0:0a5f554d2a16 | 155 | { |
lcockerton62 | 0:0a5f554d2a16 | 156 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 157 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 158 | msg.id = BMS_BASE_ID + MAX_MIN_VOLTAGE; |
lcockerton62 | 1:51477fe4851b | 159 | |
lcockerton62 | 0:0a5f554d2a16 | 160 | CAN_Data data; |
lcockerton62 | 1:51477fe4851b | 161 | data.set_u16(0,min_voltage.voltage); //Min voltage |
lcockerton62 | 1:51477fe4851b | 162 | data.set_u16(1,max_voltage.voltage); //Max voltage |
lcockerton62 | 1:51477fe4851b | 163 | data.set_u8(4,min_voltage.CMU_number); //CMU number of lowest cell |
lcockerton62 | 1:51477fe4851b | 164 | data.set_u8(5,min_voltage.cell_number); //Cell number in CMU with lowest voltage |
maxv008 | 31:888b2602aab2 | 165 | data.set_u8(6,max_voltage.CMU_number); //CMU number of maxiumum cell |
maxv008 | 31:888b2602aab2 | 166 | data.set_u8(7,max_voltage.cell_number); //Cell number in CMU with highest voltage |
lcockerton62 | 1:51477fe4851b | 167 | |
lcockerton62 | 1:51477fe4851b | 168 | for(int i=0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 169 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 170 | } |
lcockerton62 | 1:51477fe4851b | 171 | |
lcockerton62 | 0:0a5f554d2a16 | 172 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 173 | } |
lcockerton62 | 0:0a5f554d2a16 | 174 | |
maxv008 | 23:a1af4439c1fc | 175 | void decodeCellVoltageMAXMIN(CANMessage msg, pack_voltage_extremes &min, pack_voltage_extremes &max) |
maxv008 | 23:a1af4439c1fc | 176 | { |
maxv008 | 23:a1af4439c1fc | 177 | CAN_Data decode; |
maxv008 | 23:a1af4439c1fc | 178 | decode.importCANData(msg); |
maxv008 | 23:a1af4439c1fc | 179 | min.voltage = decode.get_u16(0); |
maxv008 | 23:a1af4439c1fc | 180 | max.voltage = decode.get_u16(1); |
maxv008 | 23:a1af4439c1fc | 181 | min.CMU_number = decode.get_u8(4); |
maxv008 | 23:a1af4439c1fc | 182 | min.cell_number = decode.get_u8(5); |
maxv008 | 23:a1af4439c1fc | 183 | max.CMU_number = decode.get_u8(6); |
maxv008 | 23:a1af4439c1fc | 184 | max.cell_number = decode.get_u8(7); |
maxv008 | 23:a1af4439c1fc | 185 | } |
maxv008 | 23:a1af4439c1fc | 186 | |
maxv008 | 23:a1af4439c1fc | 187 | //Since each CAN message can only support 1 ID, need to send 2 using this function |
maxv008 | 23:a1af4439c1fc | 188 | //Use bool isMin to say if its a minimum or maximum |
maxv008 | 23:a1af4439c1fc | 189 | CANMessage createCellTemperatureMAXMIN(pack_temperature_extremes ex_temperature, bool isMin) |
lcockerton62 | 0:0a5f554d2a16 | 190 | { |
lcockerton62 | 0:0a5f554d2a16 | 191 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 192 | msg.len = 8; |
maxv008 | 23:a1af4439c1fc | 193 | msg.id = BMS_BASE_ID + (isMin ? MIN_TEMPERATURE : MAX_TEMPERATURE) ; |
maxv008 | 23:a1af4439c1fc | 194 | //TODO, CHANGE CMU NUMBER TO ROMID |
lcockerton62 | 0:0a5f554d2a16 | 195 | CAN_Data data; |
maxv008 | 23:a1af4439c1fc | 196 | data.set_u16(3,ex_temperature.temperature); //Extreme temperature |
maxv008 | 23:a1af4439c1fc | 197 | |
maxv008 | 23:a1af4439c1fc | 198 | for(int i = 1; i <= 6; i++) //ID portion of ROM array |
maxv008 | 23:a1af4439c1fc | 199 | { |
maxv008 | 23:a1af4439c1fc | 200 | data.set_u8(i - 1, ex_temperature.ROMID[i]); |
maxv008 | 23:a1af4439c1fc | 201 | } |
lcockerton62 | 1:51477fe4851b | 202 | |
lcockerton62 | 1:51477fe4851b | 203 | for(int i=0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 204 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 205 | } |
lcockerton62 | 1:51477fe4851b | 206 | |
lcockerton62 | 0:0a5f554d2a16 | 207 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 208 | } |
lcockerton62 | 0:0a5f554d2a16 | 209 | |
maxv008 | 23:a1af4439c1fc | 210 | //It is up to function caller to decide by msg.ID if it is minimum or not |
maxv008 | 23:a1af4439c1fc | 211 | pack_temperature_extremes decodeCellTemperatureMAXMIN(CANMessage msg) |
maxv008 | 23:a1af4439c1fc | 212 | { |
maxv008 | 23:a1af4439c1fc | 213 | pack_temperature_extremes result; |
maxv008 | 23:a1af4439c1fc | 214 | CAN_Data decode; |
maxv008 | 23:a1af4439c1fc | 215 | unsigned long fullID = 0; |
maxv008 | 23:a1af4439c1fc | 216 | |
maxv008 | 23:a1af4439c1fc | 217 | decode.importCANData(msg); |
maxv008 | 23:a1af4439c1fc | 218 | result.temperature = decode.get_16(3); |
maxv008 | 23:a1af4439c1fc | 219 | |
maxv008 | 23:a1af4439c1fc | 220 | for(int i = 1; i <=6; i++) |
maxv008 | 23:a1af4439c1fc | 221 | { |
maxv008 | 23:a1af4439c1fc | 222 | result.ROMID[i] = decode.get_u8(i-1); |
maxv008 | 23:a1af4439c1fc | 223 | fullID += (result.ROMID[i] << (8 * (i-1))); //Bit order not particularly important |
maxv008 | 23:a1af4439c1fc | 224 | } |
maxv008 | 23:a1af4439c1fc | 225 | result.ID = fullID; |
maxv008 | 23:a1af4439c1fc | 226 | return result; |
maxv008 | 23:a1af4439c1fc | 227 | } |
maxv008 | 23:a1af4439c1fc | 228 | |
maxv008 | 31:888b2602aab2 | 229 | CANMessage createBatteryVI(uint32_t batteryVoltage, float batteryCurrent) |
lcockerton62 | 0:0a5f554d2a16 | 230 | { |
lcockerton62 | 0:0a5f554d2a16 | 231 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 232 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 233 | msg.id = BMS_BASE_ID + BATTERY_VI_ID; |
lcockerton62 | 1:51477fe4851b | 234 | |
lcockerton62 | 0:0a5f554d2a16 | 235 | CAN_Data data; |
lcockerton62 | 3:527790e4965a | 236 | data.setLower_uLong(batteryVoltage); |
maxv008 | 31:888b2602aab2 | 237 | data.setUpperFloat(batteryCurrent); |
lcockerton62 | 1:51477fe4851b | 238 | |
lcockerton62 | 1:51477fe4851b | 239 | for(int i=0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 240 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 241 | } |
lcockerton62 | 0:0a5f554d2a16 | 242 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 243 | } |
lcockerton62 | 0:0a5f554d2a16 | 244 | |
maxv008 | 31:888b2602aab2 | 245 | uint32_t decodeBatteryVoltage(CANMessage msg) |
maxv008 | 31:888b2602aab2 | 246 | { |
maxv008 | 31:888b2602aab2 | 247 | uint32_t result = 0; |
maxv008 | 31:888b2602aab2 | 248 | CAN_Data decode; |
maxv008 | 31:888b2602aab2 | 249 | decode.importCANData(msg); |
maxv008 | 31:888b2602aab2 | 250 | result = decode.getLower_uLong(); |
maxv008 | 31:888b2602aab2 | 251 | return result; |
maxv008 | 31:888b2602aab2 | 252 | } |
maxv008 | 31:888b2602aab2 | 253 | |
maxv008 | 31:888b2602aab2 | 254 | float decodeBatteryCurrent(CANMessage msg) |
maxv008 | 31:888b2602aab2 | 255 | { |
maxv008 | 48:5c3f42c44036 | 256 | float result = 0; |
maxv008 | 31:888b2602aab2 | 257 | CAN_Data decode; |
maxv008 | 31:888b2602aab2 | 258 | decode.importCANData(msg); |
maxv008 | 31:888b2602aab2 | 259 | result = decode.getUpperFloat(); |
maxv008 | 31:888b2602aab2 | 260 | return result; |
maxv008 | 45:c288d7cbdb4a | 261 | } |
maxv008 | 45:c288d7cbdb4a | 262 | |
maxv008 | 45:c288d7cbdb4a | 263 | CANMessage createIVTACurrent(int32_t current) |
maxv008 | 45:c288d7cbdb4a | 264 | { |
maxv008 | 45:c288d7cbdb4a | 265 | CANMessage msg; |
maxv008 | 45:c288d7cbdb4a | 266 | msg.len = 8; |
maxv008 | 45:c288d7cbdb4a | 267 | msg.id = BMS_BASE_ID + IVTA_ID; |
maxv008 | 45:c288d7cbdb4a | 268 | |
maxv008 | 45:c288d7cbdb4a | 269 | CAN_Data data; |
maxv008 | 45:c288d7cbdb4a | 270 | data.setLower_Long(current); |
maxv008 | 45:c288d7cbdb4a | 271 | data.setHigher_Long(0); |
maxv008 | 45:c288d7cbdb4a | 272 | |
maxv008 | 45:c288d7cbdb4a | 273 | for(int i=0; i<8; i++) { |
maxv008 | 45:c288d7cbdb4a | 274 | msg.data[i] = data.get_u8(i); |
maxv008 | 45:c288d7cbdb4a | 275 | } |
maxv008 | 45:c288d7cbdb4a | 276 | return msg; |
maxv008 | 31:888b2602aab2 | 277 | } |
maxv008 | 31:888b2602aab2 | 278 | |
maxv008 | 45:c288d7cbdb4a | 279 | int32_t decodeIVTACurrent(CANMessage msg) |
maxv008 | 45:c288d7cbdb4a | 280 | { |
maxv008 | 45:c288d7cbdb4a | 281 | int32_t result = 0; |
maxv008 | 45:c288d7cbdb4a | 282 | CAN_Data decode; |
maxv008 | 45:c288d7cbdb4a | 283 | decode.importCANData(msg); |
maxv008 | 45:c288d7cbdb4a | 284 | result = decode.getLower_Long(); |
maxv008 | 45:c288d7cbdb4a | 285 | return result; |
maxv008 | 45:c288d7cbdb4a | 286 | } |
maxv008 | 45:c288d7cbdb4a | 287 | |
lcockerton62 | 0:0a5f554d2a16 | 288 | CANMessage createBatteryPackStatus(uint16_t voltageThreshold[], uint8_t statusFlag,uint8_t BMS_CMU_Count,uint16_t BMS_Firmware_Build) |
lcockerton62 | 0:0a5f554d2a16 | 289 | { |
lcockerton62 | 1:51477fe4851b | 290 | CANMessage msg; |
lcockerton62 | 1:51477fe4851b | 291 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 292 | msg.id = BMS_BASE_ID + BATTERY_PACK_STATUS_ID; |
lcockerton62 | 1:51477fe4851b | 293 | |
lcockerton62 | 1:51477fe4851b | 294 | CAN_Data data; |
lcockerton62 | 1:51477fe4851b | 295 | data.set_u16(0,voltageThreshold[0]); |
lcockerton62 | 1:51477fe4851b | 296 | data.set_u16(1,voltageThreshold[1]); |
lcockerton62 | 1:51477fe4851b | 297 | data.set_16(3,BMS_Firmware_Build); |
lcockerton62 | 1:51477fe4851b | 298 | data.set_u8(4,statusFlag); |
lcockerton62 | 1:51477fe4851b | 299 | data.set_u8(5,BMS_CMU_Count); |
lcockerton62 | 1:51477fe4851b | 300 | |
lcockerton62 | 1:51477fe4851b | 301 | for(int i=0; i<8; i++) { |
lcockerton62 | 1:51477fe4851b | 302 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 1:51477fe4851b | 303 | } |
lcockerton62 | 1:51477fe4851b | 304 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 305 | } |
lcockerton62 | 0:0a5f554d2a16 | 306 | |
lcockerton62 | 0:0a5f554d2a16 | 307 | CANMessage createExtendedBatteryPackStatus(uint32_t status) |
lcockerton62 | 0:0a5f554d2a16 | 308 | { |
lcockerton62 | 1:51477fe4851b | 309 | CANMessage msg; |
lcockerton62 | 1:51477fe4851b | 310 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 311 | msg.id = BMS_BASE_ID + BATTERY_STATUS_ID; |
lcockerton62 | 1:51477fe4851b | 312 | |
lcockerton62 | 1:51477fe4851b | 313 | CAN_Data data; |
lcockerton62 | 1:51477fe4851b | 314 | data.setLower_uLong(status); //@TODO see the data sheet for this |
lcockerton62 | 1:51477fe4851b | 315 | data.set_u8(4,0x00);//Hardware version random data @TODO check this |
lcockerton62 | 1:51477fe4851b | 316 | data.set_u8(5,0x00);//Model ID @TODO check this |
lcockerton62 | 1:51477fe4851b | 317 | data.set_u16(3,0x00); // Unused |
lcockerton62 | 1:51477fe4851b | 318 | |
lcockerton62 | 1:51477fe4851b | 319 | for(int i=0; i<8; i++) { |
lcockerton62 | 1:51477fe4851b | 320 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 1:51477fe4851b | 321 | } |
lcockerton62 | 1:51477fe4851b | 322 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 323 | } |
lcockerton62 | 0:0a5f554d2a16 | 324 | |
maxv008 | 23:a1af4439c1fc | 325 | uint32_t decodeExtendedBatteryPackStatus(CANMessage msg) |
maxv008 | 23:a1af4439c1fc | 326 | { |
maxv008 | 23:a1af4439c1fc | 327 | CAN_Data decode; |
maxv008 | 23:a1af4439c1fc | 328 | decode.importCANData(msg); |
maxv008 | 23:a1af4439c1fc | 329 | return decode.getLower_uLong(); |
maxv008 | 23:a1af4439c1fc | 330 | } |
maxv008 | 23:a1af4439c1fc | 331 | |
maxv008 | 31:888b2602aab2 | 332 | //Values here don't matter, added just in case. |
maxv008 | 31:888b2602aab2 | 333 | CANMessage createBMSHeartbeat(uint32_t val1, uint32_t val2) |
maxv008 | 31:888b2602aab2 | 334 | { |
maxv008 | 31:888b2602aab2 | 335 | CANMessage msg; |
maxv008 | 31:888b2602aab2 | 336 | msg.len = 8; |
maxv008 | 31:888b2602aab2 | 337 | msg.id = BMS_BASE_ID; |
maxv008 | 31:888b2602aab2 | 338 | |
maxv008 | 31:888b2602aab2 | 339 | CAN_Data data; |
maxv008 | 31:888b2602aab2 | 340 | data.setLower_uLong(val1); |
maxv008 | 31:888b2602aab2 | 341 | data.setHigher_uLong(val2); |
maxv008 | 31:888b2602aab2 | 342 | |
maxv008 | 31:888b2602aab2 | 343 | for(int i=0; i<8; i++) { |
maxv008 | 31:888b2602aab2 | 344 | msg.data[i] = data.get_u8(i); |
maxv008 | 31:888b2602aab2 | 345 | } |
maxv008 | 31:888b2602aab2 | 346 | return msg; |
maxv008 | 31:888b2602aab2 | 347 | } |
maxv008 | 31:888b2602aab2 | 348 | |
maxv008 | 48:5c3f42c44036 | 349 | CANMessage createEEPROMReset(float init_SOC, float init_SOC_Percent) //TODO: Ensure ID doesn't conflict more carefully (It should be fine) |
maxv008 | 48:5c3f42c44036 | 350 | { |
maxv008 | 48:5c3f42c44036 | 351 | CANMessage msg; |
maxv008 | 48:5c3f42c44036 | 352 | msg.len = 8; |
maxv008 | 48:5c3f42c44036 | 353 | msg.id = BMS_BASE_ID + EEPROM_RESET_ID; |
maxv008 | 48:5c3f42c44036 | 354 | |
maxv008 | 48:5c3f42c44036 | 355 | CAN_Data data; |
maxv008 | 48:5c3f42c44036 | 356 | data.setLowerFloat(init_SOC); |
maxv008 | 48:5c3f42c44036 | 357 | data.setUpperFloat(init_SOC_Percent); |
maxv008 | 48:5c3f42c44036 | 358 | |
maxv008 | 48:5c3f42c44036 | 359 | for(int i=0; i<8; i++) { |
maxv008 | 48:5c3f42c44036 | 360 | msg.data[i] = data.get_u8(i); |
maxv008 | 48:5c3f42c44036 | 361 | } |
maxv008 | 48:5c3f42c44036 | 362 | return msg; |
maxv008 | 48:5c3f42c44036 | 363 | } |
maxv008 | 48:5c3f42c44036 | 364 | |
maxv008 | 48:5c3f42c44036 | 365 | float decodeEEPROMSOC(CANMessage msg) |
maxv008 | 48:5c3f42c44036 | 366 | { |
maxv008 | 48:5c3f42c44036 | 367 | float result = 0; |
maxv008 | 48:5c3f42c44036 | 368 | CAN_Data decode; |
maxv008 | 48:5c3f42c44036 | 369 | decode.importCANData(msg); |
maxv008 | 48:5c3f42c44036 | 370 | result = decode.getLowerFloat(); |
maxv008 | 48:5c3f42c44036 | 371 | return result; |
maxv008 | 48:5c3f42c44036 | 372 | } |
maxv008 | 48:5c3f42c44036 | 373 | |
maxv008 | 48:5c3f42c44036 | 374 | float decodeEEPROMSOCPercentage(CANMessage msg) |
maxv008 | 48:5c3f42c44036 | 375 | { |
maxv008 | 48:5c3f42c44036 | 376 | float result = 0; |
maxv008 | 48:5c3f42c44036 | 377 | CAN_Data decode; |
maxv008 | 48:5c3f42c44036 | 378 | decode.importCANData(msg); |
maxv008 | 48:5c3f42c44036 | 379 | result = decode.getUpperFloat(); |
maxv008 | 48:5c3f42c44036 | 380 | return result; |
maxv008 | 48:5c3f42c44036 | 381 | } |
maxv008 | 48:5c3f42c44036 | 382 | |
lcockerton62 | 0:0a5f554d2a16 | 383 | void convertFloatFloat(float lower, float upper, CANMessage& msg, bool littleEndian) |
lcockerton62 | 0:0a5f554d2a16 | 384 | { |
lcockerton62 | 0:0a5f554d2a16 | 385 | // Code taken from driver_controls |
lcockerton62 | 0:0a5f554d2a16 | 386 | //two converters for lower and higher float |
lcockerton62 | 0:0a5f554d2a16 | 387 | float2byte convL; |
lcockerton62 | 0:0a5f554d2a16 | 388 | float2byte convH; |
lcockerton62 | 0:0a5f554d2a16 | 389 | convL.f = lower; |
lcockerton62 | 0:0a5f554d2a16 | 390 | convH.f = upper; |
lcockerton62 | 0:0a5f554d2a16 | 391 | if(littleEndian) { |
lcockerton62 | 0:0a5f554d2a16 | 392 | for(int i=0; i<4; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 393 | msg.data[i] = convL.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 394 | //offset for upper float |
lcockerton62 | 0:0a5f554d2a16 | 395 | msg.data[i+4]=convH.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 396 | } |
lcockerton62 | 0:0a5f554d2a16 | 397 | } else { |
lcockerton62 | 0:0a5f554d2a16 | 398 | for(int i=0; i<4; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 399 | /* |
lcockerton62 | 0:0a5f554d2a16 | 400 | * Subtract because output data is Big Endian |
lcockerton62 | 0:0a5f554d2a16 | 401 | * i.e. convL/H is LSB --> MSB |
lcockerton62 | 0:0a5f554d2a16 | 402 | * output is MSB --> LSB |
lcockerton62 | 0:0a5f554d2a16 | 403 | */ |
lcockerton62 | 1:51477fe4851b | 404 | |
lcockerton62 | 0:0a5f554d2a16 | 405 | msg.data[4-i] = convL.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 406 | msg.data[7-i] = convH.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 407 | } |
lcockerton62 | 0:0a5f554d2a16 | 408 | } |
lcockerton62 | 0:0a5f554d2a16 | 409 | } |
lcockerton62 | 0:0a5f554d2a16 | 410 |