Cell voltages fork (SoC)

Dependencies:   CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl

Committer:
maxv008
Date:
Sun Jul 02 13:35:18 2017 +0000
Revision:
17:94dd9a0d3870
Parent:
16:b2ef68c9a4fd
Child:
18:521ffdd724f3
added decoder for voltage messages

Who changed what in which revision?

UserRevisionLine numberNew 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 17:94dd9a0d3870 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 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 17:94dd9a0d3870 87 void 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;
maxv008 17:94dd9a0d3870 93
maxv008 17:94dd9a0d3870 94 int cellsubset = ((offset-1) % repeating_length) - 1; //Which set of 4 voltages within the CMU
maxv008 17:94dd9a0d3870 95 int CMU_number = (offset-1) / repeating_length;
maxv008 17:94dd9a0d3870 96 for(int i = 0; i < 4; i++)
maxv008 17:94dd9a0d3870 97 {
maxv008 17:94dd9a0d3870 98 readings[CMU_number].voltages[cellsubset*4 + i] = voltData.get_u16(i);
maxv008 17:94dd9a0d3870 99 }
maxv008 17:94dd9a0d3870 100 }
lcockerton62 0:0a5f554d2a16 101
lcockerton62 0:0a5f554d2a16 102 CANMessage createPackSOC(float SOC, float percentageCharge)
lcockerton62 0:0a5f554d2a16 103 {
lcockerton62 0:0a5f554d2a16 104 CANMessage msg;
lcockerton62 0:0a5f554d2a16 105 msg.len = 8;
lcockerton62 0:0a5f554d2a16 106 msg.id = BMS_BASE_ID + BATTERY_SOC_ID;
lcockerton62 0:0a5f554d2a16 107 CAN_Data data;
lcockerton62 0:0a5f554d2a16 108 data.setLowerFloat(SOC);
lcockerton62 0:0a5f554d2a16 109 data.setUpperFloat(percentageCharge);
lcockerton62 1:51477fe4851b 110 for(int i=0; i<8; i++) {
lcockerton62 0:0a5f554d2a16 111 msg.data[i] = data.get_u8(i);
lcockerton62 0:0a5f554d2a16 112 }
lcockerton62 1:51477fe4851b 113
lcockerton62 0:0a5f554d2a16 114 return msg;
lcockerton62 0:0a5f554d2a16 115 }
lcockerton62 0:0a5f554d2a16 116
lcockerton62 0:0a5f554d2a16 117 CANMessage createPackBalanceSOC(float SOC, float percentageCharge)
lcockerton62 0:0a5f554d2a16 118 {
lcockerton62 0:0a5f554d2a16 119 // @TODO - check is this being used?? section 5.4 trituim BMU CAN data sheet
lcockerton62 0:0a5f554d2a16 120 CANMessage msg;
lcockerton62 0:0a5f554d2a16 121 msg.len = 8;
lcockerton62 1:51477fe4851b 122 msg.id = BMS_BASE_ID + BATTERY_SOC_BASE_ID;
lcockerton62 1:51477fe4851b 123
lcockerton62 0:0a5f554d2a16 124 CAN_Data data;
lcockerton62 0:0a5f554d2a16 125 data.setLowerFloat(SOC);
lcockerton62 0:0a5f554d2a16 126 data.setUpperFloat(percentageCharge);
lcockerton62 1:51477fe4851b 127 for(int i=0; i<8; i++) {
lcockerton62 0:0a5f554d2a16 128 msg.data[i] = data.get_u8(i);
lcockerton62 0:0a5f554d2a16 129 }
lcockerton62 1:51477fe4851b 130
lcockerton62 0:0a5f554d2a16 131 return msg;
lcockerton62 0:0a5f554d2a16 132 }
lcockerton62 0:0a5f554d2a16 133
lcockerton62 1:51477fe4851b 134 CANMessage createCellVoltageMAXMIN(pack_voltage_extremes max_voltage, pack_voltage_extremes min_voltage)
lcockerton62 0:0a5f554d2a16 135 {
lcockerton62 0:0a5f554d2a16 136 CANMessage msg;
lcockerton62 0:0a5f554d2a16 137 msg.len = 8;
lcockerton62 1:51477fe4851b 138 msg.id = BMS_BASE_ID + MAX_MIN_VOLTAGE;
lcockerton62 1:51477fe4851b 139
lcockerton62 0:0a5f554d2a16 140 CAN_Data data;
lcockerton62 1:51477fe4851b 141 data.set_u16(0,min_voltage.voltage); //Min voltage
lcockerton62 1:51477fe4851b 142 data.set_u16(1,max_voltage.voltage); //Max voltage
lcockerton62 1:51477fe4851b 143 data.set_u8(4,min_voltage.CMU_number); //CMU number of lowest cell
lcockerton62 1:51477fe4851b 144 data.set_u8(5,min_voltage.cell_number); //Cell number in CMU with lowest voltage
lcockerton62 1:51477fe4851b 145 data.set_u8(6,min_voltage.CMU_number); //CMU number of maxiumum cell
lcockerton62 1:51477fe4851b 146 data.set_u8(7,min_voltage.cell_number); //Cell number in CMU with highest voltage
lcockerton62 1:51477fe4851b 147
lcockerton62 1:51477fe4851b 148 for(int i=0; i<8; i++) {
lcockerton62 0:0a5f554d2a16 149 msg.data[i] = data.get_u8(i);
lcockerton62 0:0a5f554d2a16 150 }
lcockerton62 1:51477fe4851b 151
lcockerton62 0:0a5f554d2a16 152 return msg;
lcockerton62 0:0a5f554d2a16 153 }
lcockerton62 0:0a5f554d2a16 154
lcockerton62 1:51477fe4851b 155 CANMessage createCellTemperatureMAXMIN(pack_temperature_extremes min_temperature, pack_temperature_extremes max_temperature)
lcockerton62 0:0a5f554d2a16 156 {
lcockerton62 0:0a5f554d2a16 157 CANMessage msg;
lcockerton62 0:0a5f554d2a16 158 msg.len = 8;
lcockerton62 1:51477fe4851b 159 msg.id = BMS_BASE_ID + MAX_MIN_TEMPERATURE;
lcockerton62 1:51477fe4851b 160
lcockerton62 0:0a5f554d2a16 161 CAN_Data data;
lcockerton62 1:51477fe4851b 162 data.set_u16(0,min_temperature.temperature); //Min temperature
lcockerton62 1:51477fe4851b 163 data.set_u16(1,max_temperature.temperature); //Max temperature
lcockerton62 1:51477fe4851b 164 data.set_u8(4,min_temperature.CMU_number); //CMU number of lowest temperature cell
lcockerton62 0:0a5f554d2a16 165 data.set_u8(5,BLANK_DATA); //Dummy data
lcockerton62 1:51477fe4851b 166 data.set_u8(6,max_temperature.CMU_number); //CMU number of maxiumum temperature cell
lcockerton62 1:51477fe4851b 167 data.set_u8(7,BLANK_DATA); //Dummy data
lcockerton62 1:51477fe4851b 168
lcockerton62 1:51477fe4851b 169 for(int i=0; i<8; i++) {
lcockerton62 0:0a5f554d2a16 170 msg.data[i] = data.get_u8(i);
lcockerton62 0:0a5f554d2a16 171 }
lcockerton62 1:51477fe4851b 172
lcockerton62 0:0a5f554d2a16 173 return msg;
lcockerton62 0:0a5f554d2a16 174 }
lcockerton62 0:0a5f554d2a16 175
lcockerton62 0:0a5f554d2a16 176 CANMessage createBatteryVI(uint32_t batteryVoltage,uint32_t batteryCurrent)
lcockerton62 0:0a5f554d2a16 177 {
lcockerton62 0:0a5f554d2a16 178 CANMessage msg;
lcockerton62 0:0a5f554d2a16 179 msg.len = 8;
lcockerton62 1:51477fe4851b 180 msg.id = BMS_BASE_ID + BATTERY_VI_ID;
lcockerton62 1:51477fe4851b 181
lcockerton62 0:0a5f554d2a16 182 CAN_Data data;
lcockerton62 3:527790e4965a 183 data.setLower_uLong(batteryVoltage);
lcockerton62 3:527790e4965a 184 data.setHigher_uLong(batteryCurrent);
lcockerton62 1:51477fe4851b 185
lcockerton62 1:51477fe4851b 186 for(int i=0; i<8; i++) {
lcockerton62 0:0a5f554d2a16 187 msg.data[i] = data.get_u8(i);
lcockerton62 0:0a5f554d2a16 188 }
lcockerton62 0:0a5f554d2a16 189 return msg;
lcockerton62 0:0a5f554d2a16 190 }
lcockerton62 0:0a5f554d2a16 191
lcockerton62 0:0a5f554d2a16 192 CANMessage createBatteryPackStatus(uint16_t voltageThreshold[], uint8_t statusFlag,uint8_t BMS_CMU_Count,uint16_t BMS_Firmware_Build)
lcockerton62 0:0a5f554d2a16 193 {
lcockerton62 1:51477fe4851b 194 CANMessage msg;
lcockerton62 1:51477fe4851b 195 msg.len = 8;
lcockerton62 1:51477fe4851b 196 msg.id = BMS_BASE_ID + BATTERY_PACK_STATUS_ID;
lcockerton62 1:51477fe4851b 197
lcockerton62 1:51477fe4851b 198 CAN_Data data;
lcockerton62 1:51477fe4851b 199 data.set_u16(0,voltageThreshold[0]);
lcockerton62 1:51477fe4851b 200 data.set_u16(1,voltageThreshold[1]);
lcockerton62 1:51477fe4851b 201 data.set_16(3,BMS_Firmware_Build);
lcockerton62 1:51477fe4851b 202 data.set_u8(4,statusFlag);
lcockerton62 1:51477fe4851b 203 data.set_u8(5,BMS_CMU_Count);
lcockerton62 1:51477fe4851b 204
lcockerton62 1:51477fe4851b 205 for(int i=0; i<8; i++) {
lcockerton62 1:51477fe4851b 206 msg.data[i] = data.get_u8(i);
lcockerton62 1:51477fe4851b 207 }
lcockerton62 1:51477fe4851b 208 return msg;
lcockerton62 0:0a5f554d2a16 209 }
lcockerton62 0:0a5f554d2a16 210
lcockerton62 0:0a5f554d2a16 211 CANMessage createExtendedBatteryPackStatus(uint32_t status)
lcockerton62 0:0a5f554d2a16 212 {
lcockerton62 1:51477fe4851b 213 CANMessage msg;
lcockerton62 1:51477fe4851b 214 msg.len = 8;
lcockerton62 1:51477fe4851b 215 msg.id = BMS_BASE_ID + BATTERY_STATUS_ID;
lcockerton62 1:51477fe4851b 216
lcockerton62 1:51477fe4851b 217 CAN_Data data;
lcockerton62 1:51477fe4851b 218 data.setLower_uLong(status); //@TODO see the data sheet for this
lcockerton62 1:51477fe4851b 219 data.set_u8(4,0x00);//Hardware version random data @TODO check this
lcockerton62 1:51477fe4851b 220 data.set_u8(5,0x00);//Model ID @TODO check this
lcockerton62 1:51477fe4851b 221 data.set_u16(3,0x00); // Unused
lcockerton62 1:51477fe4851b 222
lcockerton62 1:51477fe4851b 223 for(int i=0; i<8; i++) {
lcockerton62 1:51477fe4851b 224 msg.data[i] = data.get_u8(i);
lcockerton62 1:51477fe4851b 225 }
lcockerton62 1:51477fe4851b 226 return msg;
lcockerton62 0:0a5f554d2a16 227 }
lcockerton62 0:0a5f554d2a16 228
lcockerton62 0:0a5f554d2a16 229 void convertFloatFloat(float lower, float upper, CANMessage& msg, bool littleEndian)
lcockerton62 0:0a5f554d2a16 230 {
lcockerton62 0:0a5f554d2a16 231 // Code taken from driver_controls
lcockerton62 0:0a5f554d2a16 232 //two converters for lower and higher float
lcockerton62 0:0a5f554d2a16 233 float2byte convL;
lcockerton62 0:0a5f554d2a16 234 float2byte convH;
lcockerton62 0:0a5f554d2a16 235 convL.f = lower;
lcockerton62 0:0a5f554d2a16 236 convH.f = upper;
lcockerton62 0:0a5f554d2a16 237 if(littleEndian) {
lcockerton62 0:0a5f554d2a16 238 for(int i=0; i<4; i++) {
lcockerton62 0:0a5f554d2a16 239 msg.data[i] = convL.b[i];
lcockerton62 0:0a5f554d2a16 240 //offset for upper float
lcockerton62 0:0a5f554d2a16 241 msg.data[i+4]=convH.b[i];
lcockerton62 0:0a5f554d2a16 242 }
lcockerton62 0:0a5f554d2a16 243 } else {
lcockerton62 0:0a5f554d2a16 244 for(int i=0; i<4; i++) {
lcockerton62 0:0a5f554d2a16 245 /*
lcockerton62 0:0a5f554d2a16 246 * Subtract because output data is Big Endian
lcockerton62 0:0a5f554d2a16 247 * i.e. convL/H is LSB --> MSB
lcockerton62 0:0a5f554d2a16 248 * output is MSB --> LSB
lcockerton62 0:0a5f554d2a16 249 */
lcockerton62 1:51477fe4851b 250
lcockerton62 0:0a5f554d2a16 251 msg.data[4-i] = convL.b[i];
lcockerton62 0:0a5f554d2a16 252 msg.data[7-i] = convH.b[i];
lcockerton62 0:0a5f554d2a16 253 }
lcockerton62 0:0a5f554d2a16 254 }
lcockerton62 0:0a5f554d2a16 255 }
lcockerton62 0:0a5f554d2a16 256