Cell voltages fork (SoC)
Dependencies: CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl
CANParserBMU.cpp@53:4277cdcff69b, 2017-08-19 (annotated)
- Committer:
- maxv008
- Date:
- Sat Aug 19 14:27:32 2017 +0000
- Revision:
- 53:4277cdcff69b
- Parent:
- 48:5c3f42c44036
- Child:
- 66:c884fba9eaea
Fixed Temp Reading;
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 | 53:4277cdcff69b | 48 | 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 | 53:4277cdcff69b | 57 | fullID += (probe_reading.ROMID[i] << (8 * (i-1))); //Bit order not particularly important, must be consistent |
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 | 53:4277cdcff69b | 218 | result.temperature = ((float) decode.get_16(3))/100; |
maxv008 | 23:a1af4439c1fc | 219 | for(int i = 1; i <=6; i++) |
maxv008 | 23:a1af4439c1fc | 220 | { |
maxv008 | 23:a1af4439c1fc | 221 | result.ROMID[i] = decode.get_u8(i-1); |
maxv008 | 23:a1af4439c1fc | 222 | fullID += (result.ROMID[i] << (8 * (i-1))); //Bit order not particularly important |
maxv008 | 23:a1af4439c1fc | 223 | } |
maxv008 | 23:a1af4439c1fc | 224 | result.ID = fullID; |
maxv008 | 23:a1af4439c1fc | 225 | return result; |
maxv008 | 23:a1af4439c1fc | 226 | } |
maxv008 | 23:a1af4439c1fc | 227 | |
maxv008 | 31:888b2602aab2 | 228 | CANMessage createBatteryVI(uint32_t batteryVoltage, float batteryCurrent) |
lcockerton62 | 0:0a5f554d2a16 | 229 | { |
lcockerton62 | 0:0a5f554d2a16 | 230 | CANMessage msg; |
lcockerton62 | 0:0a5f554d2a16 | 231 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 232 | msg.id = BMS_BASE_ID + BATTERY_VI_ID; |
lcockerton62 | 1:51477fe4851b | 233 | |
lcockerton62 | 0:0a5f554d2a16 | 234 | CAN_Data data; |
lcockerton62 | 3:527790e4965a | 235 | data.setLower_uLong(batteryVoltage); |
maxv008 | 31:888b2602aab2 | 236 | data.setUpperFloat(batteryCurrent); |
lcockerton62 | 1:51477fe4851b | 237 | |
lcockerton62 | 1:51477fe4851b | 238 | for(int i=0; i<8; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 239 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 0:0a5f554d2a16 | 240 | } |
lcockerton62 | 0:0a5f554d2a16 | 241 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 242 | } |
lcockerton62 | 0:0a5f554d2a16 | 243 | |
maxv008 | 31:888b2602aab2 | 244 | uint32_t decodeBatteryVoltage(CANMessage msg) |
maxv008 | 31:888b2602aab2 | 245 | { |
maxv008 | 31:888b2602aab2 | 246 | uint32_t result = 0; |
maxv008 | 31:888b2602aab2 | 247 | CAN_Data decode; |
maxv008 | 31:888b2602aab2 | 248 | decode.importCANData(msg); |
maxv008 | 31:888b2602aab2 | 249 | result = decode.getLower_uLong(); |
maxv008 | 31:888b2602aab2 | 250 | return result; |
maxv008 | 31:888b2602aab2 | 251 | } |
maxv008 | 31:888b2602aab2 | 252 | |
maxv008 | 31:888b2602aab2 | 253 | float decodeBatteryCurrent(CANMessage msg) |
maxv008 | 31:888b2602aab2 | 254 | { |
maxv008 | 48:5c3f42c44036 | 255 | float result = 0; |
maxv008 | 31:888b2602aab2 | 256 | CAN_Data decode; |
maxv008 | 31:888b2602aab2 | 257 | decode.importCANData(msg); |
maxv008 | 31:888b2602aab2 | 258 | result = decode.getUpperFloat(); |
maxv008 | 31:888b2602aab2 | 259 | return result; |
maxv008 | 45:c288d7cbdb4a | 260 | } |
maxv008 | 45:c288d7cbdb4a | 261 | |
maxv008 | 45:c288d7cbdb4a | 262 | CANMessage createIVTACurrent(int32_t current) |
maxv008 | 45:c288d7cbdb4a | 263 | { |
maxv008 | 45:c288d7cbdb4a | 264 | CANMessage msg; |
maxv008 | 45:c288d7cbdb4a | 265 | msg.len = 8; |
maxv008 | 45:c288d7cbdb4a | 266 | msg.id = BMS_BASE_ID + IVTA_ID; |
maxv008 | 45:c288d7cbdb4a | 267 | |
maxv008 | 45:c288d7cbdb4a | 268 | CAN_Data data; |
maxv008 | 45:c288d7cbdb4a | 269 | data.setLower_Long(current); |
maxv008 | 45:c288d7cbdb4a | 270 | data.setHigher_Long(0); |
maxv008 | 45:c288d7cbdb4a | 271 | |
maxv008 | 45:c288d7cbdb4a | 272 | for(int i=0; i<8; i++) { |
maxv008 | 45:c288d7cbdb4a | 273 | msg.data[i] = data.get_u8(i); |
maxv008 | 45:c288d7cbdb4a | 274 | } |
maxv008 | 45:c288d7cbdb4a | 275 | return msg; |
maxv008 | 31:888b2602aab2 | 276 | } |
maxv008 | 31:888b2602aab2 | 277 | |
maxv008 | 45:c288d7cbdb4a | 278 | int32_t decodeIVTACurrent(CANMessage msg) |
maxv008 | 45:c288d7cbdb4a | 279 | { |
maxv008 | 45:c288d7cbdb4a | 280 | int32_t result = 0; |
maxv008 | 45:c288d7cbdb4a | 281 | CAN_Data decode; |
maxv008 | 45:c288d7cbdb4a | 282 | decode.importCANData(msg); |
maxv008 | 45:c288d7cbdb4a | 283 | result = decode.getLower_Long(); |
maxv008 | 45:c288d7cbdb4a | 284 | return result; |
maxv008 | 45:c288d7cbdb4a | 285 | } |
maxv008 | 45:c288d7cbdb4a | 286 | |
lcockerton62 | 0:0a5f554d2a16 | 287 | CANMessage createBatteryPackStatus(uint16_t voltageThreshold[], uint8_t statusFlag,uint8_t BMS_CMU_Count,uint16_t BMS_Firmware_Build) |
lcockerton62 | 0:0a5f554d2a16 | 288 | { |
lcockerton62 | 1:51477fe4851b | 289 | CANMessage msg; |
lcockerton62 | 1:51477fe4851b | 290 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 291 | msg.id = BMS_BASE_ID + BATTERY_PACK_STATUS_ID; |
lcockerton62 | 1:51477fe4851b | 292 | |
lcockerton62 | 1:51477fe4851b | 293 | CAN_Data data; |
lcockerton62 | 1:51477fe4851b | 294 | data.set_u16(0,voltageThreshold[0]); |
lcockerton62 | 1:51477fe4851b | 295 | data.set_u16(1,voltageThreshold[1]); |
lcockerton62 | 1:51477fe4851b | 296 | data.set_16(3,BMS_Firmware_Build); |
lcockerton62 | 1:51477fe4851b | 297 | data.set_u8(4,statusFlag); |
lcockerton62 | 1:51477fe4851b | 298 | data.set_u8(5,BMS_CMU_Count); |
lcockerton62 | 1:51477fe4851b | 299 | |
lcockerton62 | 1:51477fe4851b | 300 | for(int i=0; i<8; i++) { |
lcockerton62 | 1:51477fe4851b | 301 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 1:51477fe4851b | 302 | } |
lcockerton62 | 1:51477fe4851b | 303 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 304 | } |
lcockerton62 | 0:0a5f554d2a16 | 305 | |
lcockerton62 | 0:0a5f554d2a16 | 306 | CANMessage createExtendedBatteryPackStatus(uint32_t status) |
lcockerton62 | 0:0a5f554d2a16 | 307 | { |
lcockerton62 | 1:51477fe4851b | 308 | CANMessage msg; |
lcockerton62 | 1:51477fe4851b | 309 | msg.len = 8; |
lcockerton62 | 1:51477fe4851b | 310 | msg.id = BMS_BASE_ID + BATTERY_STATUS_ID; |
lcockerton62 | 1:51477fe4851b | 311 | |
lcockerton62 | 1:51477fe4851b | 312 | CAN_Data data; |
lcockerton62 | 1:51477fe4851b | 313 | data.setLower_uLong(status); //@TODO see the data sheet for this |
lcockerton62 | 1:51477fe4851b | 314 | data.set_u8(4,0x00);//Hardware version random data @TODO check this |
lcockerton62 | 1:51477fe4851b | 315 | data.set_u8(5,0x00);//Model ID @TODO check this |
lcockerton62 | 1:51477fe4851b | 316 | data.set_u16(3,0x00); // Unused |
lcockerton62 | 1:51477fe4851b | 317 | |
lcockerton62 | 1:51477fe4851b | 318 | for(int i=0; i<8; i++) { |
lcockerton62 | 1:51477fe4851b | 319 | msg.data[i] = data.get_u8(i); |
lcockerton62 | 1:51477fe4851b | 320 | } |
lcockerton62 | 1:51477fe4851b | 321 | return msg; |
lcockerton62 | 0:0a5f554d2a16 | 322 | } |
lcockerton62 | 0:0a5f554d2a16 | 323 | |
maxv008 | 23:a1af4439c1fc | 324 | uint32_t decodeExtendedBatteryPackStatus(CANMessage msg) |
maxv008 | 23:a1af4439c1fc | 325 | { |
maxv008 | 23:a1af4439c1fc | 326 | CAN_Data decode; |
maxv008 | 23:a1af4439c1fc | 327 | decode.importCANData(msg); |
maxv008 | 23:a1af4439c1fc | 328 | return decode.getLower_uLong(); |
maxv008 | 23:a1af4439c1fc | 329 | } |
maxv008 | 23:a1af4439c1fc | 330 | |
maxv008 | 31:888b2602aab2 | 331 | //Values here don't matter, added just in case. |
maxv008 | 31:888b2602aab2 | 332 | CANMessage createBMSHeartbeat(uint32_t val1, uint32_t val2) |
maxv008 | 31:888b2602aab2 | 333 | { |
maxv008 | 31:888b2602aab2 | 334 | CANMessage msg; |
maxv008 | 31:888b2602aab2 | 335 | msg.len = 8; |
maxv008 | 31:888b2602aab2 | 336 | msg.id = BMS_BASE_ID; |
maxv008 | 31:888b2602aab2 | 337 | |
maxv008 | 31:888b2602aab2 | 338 | CAN_Data data; |
maxv008 | 31:888b2602aab2 | 339 | data.setLower_uLong(val1); |
maxv008 | 31:888b2602aab2 | 340 | data.setHigher_uLong(val2); |
maxv008 | 31:888b2602aab2 | 341 | |
maxv008 | 31:888b2602aab2 | 342 | for(int i=0; i<8; i++) { |
maxv008 | 31:888b2602aab2 | 343 | msg.data[i] = data.get_u8(i); |
maxv008 | 31:888b2602aab2 | 344 | } |
maxv008 | 31:888b2602aab2 | 345 | return msg; |
maxv008 | 31:888b2602aab2 | 346 | } |
maxv008 | 31:888b2602aab2 | 347 | |
maxv008 | 48:5c3f42c44036 | 348 | CANMessage createEEPROMReset(float init_SOC, float init_SOC_Percent) //TODO: Ensure ID doesn't conflict more carefully (It should be fine) |
maxv008 | 48:5c3f42c44036 | 349 | { |
maxv008 | 48:5c3f42c44036 | 350 | CANMessage msg; |
maxv008 | 48:5c3f42c44036 | 351 | msg.len = 8; |
maxv008 | 48:5c3f42c44036 | 352 | msg.id = BMS_BASE_ID + EEPROM_RESET_ID; |
maxv008 | 48:5c3f42c44036 | 353 | |
maxv008 | 48:5c3f42c44036 | 354 | CAN_Data data; |
maxv008 | 48:5c3f42c44036 | 355 | data.setLowerFloat(init_SOC); |
maxv008 | 48:5c3f42c44036 | 356 | data.setUpperFloat(init_SOC_Percent); |
maxv008 | 48:5c3f42c44036 | 357 | |
maxv008 | 48:5c3f42c44036 | 358 | for(int i=0; i<8; i++) { |
maxv008 | 48:5c3f42c44036 | 359 | msg.data[i] = data.get_u8(i); |
maxv008 | 48:5c3f42c44036 | 360 | } |
maxv008 | 48:5c3f42c44036 | 361 | return msg; |
maxv008 | 48:5c3f42c44036 | 362 | } |
maxv008 | 48:5c3f42c44036 | 363 | |
maxv008 | 48:5c3f42c44036 | 364 | float decodeEEPROMSOC(CANMessage msg) |
maxv008 | 48:5c3f42c44036 | 365 | { |
maxv008 | 48:5c3f42c44036 | 366 | float result = 0; |
maxv008 | 48:5c3f42c44036 | 367 | CAN_Data decode; |
maxv008 | 48:5c3f42c44036 | 368 | decode.importCANData(msg); |
maxv008 | 48:5c3f42c44036 | 369 | result = decode.getLowerFloat(); |
maxv008 | 48:5c3f42c44036 | 370 | return result; |
maxv008 | 48:5c3f42c44036 | 371 | } |
maxv008 | 48:5c3f42c44036 | 372 | |
maxv008 | 48:5c3f42c44036 | 373 | float decodeEEPROMSOCPercentage(CANMessage msg) |
maxv008 | 48:5c3f42c44036 | 374 | { |
maxv008 | 48:5c3f42c44036 | 375 | float result = 0; |
maxv008 | 48:5c3f42c44036 | 376 | CAN_Data decode; |
maxv008 | 48:5c3f42c44036 | 377 | decode.importCANData(msg); |
maxv008 | 48:5c3f42c44036 | 378 | result = decode.getUpperFloat(); |
maxv008 | 48:5c3f42c44036 | 379 | return result; |
maxv008 | 48:5c3f42c44036 | 380 | } |
maxv008 | 48:5c3f42c44036 | 381 | |
lcockerton62 | 0:0a5f554d2a16 | 382 | void convertFloatFloat(float lower, float upper, CANMessage& msg, bool littleEndian) |
lcockerton62 | 0:0a5f554d2a16 | 383 | { |
lcockerton62 | 0:0a5f554d2a16 | 384 | // Code taken from driver_controls |
lcockerton62 | 0:0a5f554d2a16 | 385 | //two converters for lower and higher float |
lcockerton62 | 0:0a5f554d2a16 | 386 | float2byte convL; |
lcockerton62 | 0:0a5f554d2a16 | 387 | float2byte convH; |
lcockerton62 | 0:0a5f554d2a16 | 388 | convL.f = lower; |
lcockerton62 | 0:0a5f554d2a16 | 389 | convH.f = upper; |
lcockerton62 | 0:0a5f554d2a16 | 390 | if(littleEndian) { |
lcockerton62 | 0:0a5f554d2a16 | 391 | for(int i=0; i<4; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 392 | msg.data[i] = convL.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 393 | //offset for upper float |
lcockerton62 | 0:0a5f554d2a16 | 394 | msg.data[i+4]=convH.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 395 | } |
lcockerton62 | 0:0a5f554d2a16 | 396 | } else { |
lcockerton62 | 0:0a5f554d2a16 | 397 | for(int i=0; i<4; i++) { |
lcockerton62 | 0:0a5f554d2a16 | 398 | /* |
lcockerton62 | 0:0a5f554d2a16 | 399 | * Subtract because output data is Big Endian |
lcockerton62 | 0:0a5f554d2a16 | 400 | * i.e. convL/H is LSB --> MSB |
lcockerton62 | 0:0a5f554d2a16 | 401 | * output is MSB --> LSB |
lcockerton62 | 0:0a5f554d2a16 | 402 | */ |
lcockerton62 | 1:51477fe4851b | 403 | |
lcockerton62 | 0:0a5f554d2a16 | 404 | msg.data[4-i] = convL.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 405 | msg.data[7-i] = convH.b[i]; |
lcockerton62 | 0:0a5f554d2a16 | 406 | } |
lcockerton62 | 0:0a5f554d2a16 | 407 | } |
lcockerton62 | 0:0a5f554d2a16 | 408 | } |
lcockerton62 | 0:0a5f554d2a16 | 409 |