Code to run on the charger board (used to charge the car from the mains).

Dependencies:   mbed CUER_CAN

Committer:
DasSidG
Date:
Tue Sep 12 05:42:43 2017 +0000
Revision:
12:77d493b3320b
Parent:
7:70cf5bff23f9
Added charger and bms timeouts to the charger board CAN packet

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DasSidG 1:0c77e20b4d4c 1 // Here are the functions to generate the CAN messages
DasSidG 1:0c77e20b4d4c 2 #include "CANParserCharger.h"
DasSidG 1:0c77e20b4d4c 3 #include "mbed.h"
DasSidG 1:0c77e20b4d4c 4 #include "CAN_IDs.h"
DasSidG 1:0c77e20b4d4c 5
DasSidG 1:0c77e20b4d4c 6
DasSidG 1:0c77e20b4d4c 7 using namespace CAN_IDs;
DasSidG 1:0c77e20b4d4c 8
DasSidG 7:70cf5bff23f9 9 //CAN stuff. Not that there are two sets because there are two separate CAN buses here; one to communicate with the charger, and one to communicate with the rest of the car (importantly the BMS).
DasSidG 7:70cf5bff23f9 10 //The reason that there are two separate CAN buses is because the charger uses the extended CAN frame format, with a 29 bit ID, whereas the car uses the default 11 bit ID.
DasSidG 7:70cf5bff23f9 11 CAN car_can(CAR_CAN_READ_PIN, CAR_CAN_WRITE_PIN); //Create a CAN object to handle CAN comms
DasSidG 7:70cf5bff23f9 12 CANMessage car_buffer[CAN_BUFFER_SIZE]; //CAN receive buffer
DasSidG 7:70cf5bff23f9 13 bool car_safe_to_write[CAN_BUFFER_SIZE]; //Semaphore bit indicating that it's safe to write to the software buffer
DasSidG 7:70cf5bff23f9 14 bool car_CAN_data_sent = false;
DasSidG 7:70cf5bff23f9 15
DasSidG 7:70cf5bff23f9 16 CAN charger_can(CHARGER_CAN_READ_PIN, CHARGER_CAN_WRITE_PIN); //Create a CAN object to handle CAN comms
DasSidG 7:70cf5bff23f9 17 CANMessage charger_buffer[CAN_BUFFER_SIZE]; //CAN receive buffer
DasSidG 7:70cf5bff23f9 18 bool charger_safe_to_write[CAN_BUFFER_SIZE]; //Semaphore bit indicating that it's safe to write to the software buffer
DasSidG 7:70cf5bff23f9 19 bool charger_CAN_data_sent = false;
DasSidG 7:70cf5bff23f9 20
DasSidG 1:0c77e20b4d4c 21 void get_max_min_voltage(CANMessage msg, float &_min_cell_voltage, float &_max_cell_voltage) {
DasSidG 1:0c77e20b4d4c 22 CAN_Data data;
DasSidG 1:0c77e20b4d4c 23 data.importCANData(msg);
DasSidG 1:0c77e20b4d4c 24
DasSidG 3:a7626dffb64a 25 _min_cell_voltage = (float) data.get_u16(0);
DasSidG 3:a7626dffb64a 26 _max_cell_voltage = (float) data.get_u16(1);
DasSidG 1:0c77e20b4d4c 27 }
DasSidG 1:0c77e20b4d4c 28
DasSidG 1:0c77e20b4d4c 29 void get_battery_status(CANMessage msg, bool &error) { //note using extended battery pack status
DasSidG 1:0c77e20b4d4c 30 CAN_Data data;
DasSidG 1:0c77e20b4d4c 31 data.importCANData(msg);
DasSidG 1:0c77e20b4d4c 32
DasSidG 1:0c77e20b4d4c 33 error = data.getLower_uLong() > 0;
DasSidG 1:0c77e20b4d4c 34 //ignore the rest of the status as we don't care
DasSidG 1:0c77e20b4d4c 35 }
DasSidG 1:0c77e20b4d4c 36
DasSidG 1:0c77e20b4d4c 37 void get_charger_VI_info(CANMessage msg, float &_charger_voltage, float &_charger_current, uint8_t &_charger_status) {
DasSidG 1:0c77e20b4d4c 38 CAN_Data data;
DasSidG 1:0c77e20b4d4c 39 data.importCANData(msg);
DasSidG 1:0c77e20b4d4c 40
DasSidG 1:0c77e20b4d4c 41 _charger_voltage = data.get_u16(0)*100.0;
DasSidG 1:0c77e20b4d4c 42 _charger_current = data.get_u16(1)*100.0;
DasSidG 1:0c77e20b4d4c 43 _charger_status = data.get_u8(4);
DasSidG 1:0c77e20b4d4c 44 }
DasSidG 1:0c77e20b4d4c 45
DasSidG 5:756fae795d37 46 void check_precharge_status (CANMessage msg, bool &_precharge_ready) {
DasSidG 5:756fae795d37 47 CAN_Data data;
DasSidG 5:756fae795d37 48 data.importCANData(msg);
DasSidG 5:756fae795d37 49
DasSidG 5:756fae795d37 50 if(data.get_u8(1) == 4) _precharge_ready = true;
DasSidG 5:756fae795d37 51 else _precharge_ready = false;
DasSidG 5:756fae795d37 52 }
DasSidG 5:756fae795d37 53
DasSidG 1:0c77e20b4d4c 54 CANMessage generate_charger_control_msg(float _desired_voltage, float _desired_current, uint8_t _charger_control) {
DasSidG 1:0c77e20b4d4c 55 CANMessage msg;
DasSidG 1:0c77e20b4d4c 56 msg.format = CANExtended; //the charger uses the extended CAN frame format
DasSidG 1:0c77e20b4d4c 57 msg.len = 8;
DasSidG 1:0c77e20b4d4c 58 msg.id = CHARGER_VI_CONTROL_ID;
DasSidG 1:0c77e20b4d4c 59 CAN_Data data;
DasSidG 1:0c77e20b4d4c 60 data.set_u16(0, (uint16_t) (_desired_voltage/100));
DasSidG 1:0c77e20b4d4c 61 data.set_u16(1, (uint16_t) (_desired_current/100));
DasSidG 1:0c77e20b4d4c 62 data.set_u8(4, _charger_control);
DasSidG 1:0c77e20b4d4c 63 data.set_u8(5,0);
DasSidG 1:0c77e20b4d4c 64 data.set_u8(6,0);
DasSidG 1:0c77e20b4d4c 65 data.set_u8(7,0);
DasSidG 1:0c77e20b4d4c 66
DasSidG 1:0c77e20b4d4c 67 for(int i=0; i<8; i++) {
DasSidG 1:0c77e20b4d4c 68 msg.data[i] = data.get_u8(i);
DasSidG 1:0c77e20b4d4c 69 }
DasSidG 1:0c77e20b4d4c 70
DasSidG 1:0c77e20b4d4c 71 return msg;
DasSidG 1:0c77e20b4d4c 72 }
DasSidG 1:0c77e20b4d4c 73
DasSidG 12:77d493b3320b 74 CANMessage generate_charger_info_msg(float _charger_voltage, float _charger_current, uint8_t _charger_status, bool _charger_timeout, bool _bms_timeout) {
DasSidG 1:0c77e20b4d4c 75 CANMessage msg;
DasSidG 1:0c77e20b4d4c 76 msg.len = 8;
DasSidG 1:0c77e20b4d4c 77 msg.id = CHARGER_ID;
DasSidG 1:0c77e20b4d4c 78 CAN_Data data;
DasSidG 1:0c77e20b4d4c 79 data.set_u16(0, (uint16_t) (_charger_voltage/100));
DasSidG 1:0c77e20b4d4c 80 data.set_u16(1, (uint16_t) (_charger_current/100));
DasSidG 1:0c77e20b4d4c 81 data.set_u8(4, _charger_status);
DasSidG 12:77d493b3320b 82 data.set_u8(5, _charger_timeout);
DasSidG 12:77d493b3320b 83 data.set_u8(6, _bms_timeout);
DasSidG 1:0c77e20b4d4c 84 data.set_u8(7,0);
DasSidG 1:0c77e20b4d4c 85
DasSidG 1:0c77e20b4d4c 86 for(int i=0; i<8; i++) {
DasSidG 1:0c77e20b4d4c 87 msg.data[i] = data.get_u8(i);
DasSidG 1:0c77e20b4d4c 88 }
DasSidG 1:0c77e20b4d4c 89
DasSidG 1:0c77e20b4d4c 90 return msg;
DasSidG 3:a7626dffb64a 91 }
DasSidG 3:a7626dffb64a 92
DasSidG 3:a7626dffb64a 93 CANMessage generate_charging_finished_msg() {
DasSidG 3:a7626dffb64a 94 CANMessage msg;
DasSidG 3:a7626dffb64a 95 msg.len = 8;
DasSidG 3:a7626dffb64a 96 msg.id = BMS_BASE_ID + EEPROM_RESET_ID;
DasSidG 3:a7626dffb64a 97
DasSidG 3:a7626dffb64a 98 CAN_Data data;
DasSidG 5:756fae795d37 99 data.setLowerFloat(PACK_CAPACITY); //42 is the pack capacity in Ah
DasSidG 3:a7626dffb64a 100 data.setUpperFloat(100); //100% as fully charged
DasSidG 3:a7626dffb64a 101
DasSidG 3:a7626dffb64a 102 for(int i=0; i<8; i++) {
DasSidG 3:a7626dffb64a 103 msg.data[i] = data.get_u8(i);
DasSidG 3:a7626dffb64a 104 }
DasSidG 3:a7626dffb64a 105 return msg;
DasSidG 7:70cf5bff23f9 106 }
DasSidG 7:70cf5bff23f9 107
DasSidG 7:70cf5bff23f9 108 void get_CAN_data() {
DasSidG 7:70cf5bff23f9 109
DasSidG 7:70cf5bff23f9 110 //Import the data from the buffer into a non-volatile, more usable format
DasSidG 7:70cf5bff23f9 111 CANMessage car_msgArray[CAN_BUFFER_SIZE]; //Same as above but some functions take message as their parameter
DasSidG 7:70cf5bff23f9 112 int car_received_CAN_IDs[CAN_BUFFER_SIZE]; //needed to keep track of which IDs we've received so far
DasSidG 7:70cf5bff23f9 113 for (int i = 0; i<CAN_BUFFER_SIZE; ++i)
DasSidG 7:70cf5bff23f9 114 {
DasSidG 7:70cf5bff23f9 115 car_safe_to_write[i] = false;
DasSidG 7:70cf5bff23f9 116 car_received_CAN_IDs[i] = car_buffer[i].id;
DasSidG 7:70cf5bff23f9 117 car_msgArray[i] = car_buffer[i];
DasSidG 7:70cf5bff23f9 118 car_buffer[i].id = BLANK_ID; //this effectively clears the buffer, so that we never reuse old values
DasSidG 7:70cf5bff23f9 119 car_safe_to_write[i] = true;
DasSidG 7:70cf5bff23f9 120
DasSidG 7:70cf5bff23f9 121 //Now actually import the data from the CAN packets into the global variables
DasSidG 7:70cf5bff23f9 122 switch (car_received_CAN_IDs[i]) {
DasSidG 7:70cf5bff23f9 123
DasSidG 7:70cf5bff23f9 124 case BMS_BASE_ID:
DasSidG 7:70cf5bff23f9 125 break;
DasSidG 7:70cf5bff23f9 126
DasSidG 7:70cf5bff23f9 127 case BMS_BASE_ID + MAX_MIN_VOLTAGE:
DasSidG 7:70cf5bff23f9 128 get_max_min_voltage(car_msgArray[i], min_cell_voltage, max_cell_voltage);
DasSidG 7:70cf5bff23f9 129 break;
DasSidG 7:70cf5bff23f9 130
DasSidG 7:70cf5bff23f9 131 case BMS_BASE_ID + BATTERY_STATUS_ID:
DasSidG 7:70cf5bff23f9 132 get_battery_status(car_msgArray[i], bms_error);
DasSidG 7:70cf5bff23f9 133 break;
DasSidG 7:70cf5bff23f9 134
DasSidG 7:70cf5bff23f9 135 case BMS_BASE_ID + BATTERY_PRECHARGE_ID:
DasSidG 7:70cf5bff23f9 136 check_precharge_status(car_msgArray[i], precharge_status);
DasSidG 7:70cf5bff23f9 137 break;
DasSidG 7:70cf5bff23f9 138
DasSidG 7:70cf5bff23f9 139 case BLANK_ID: //This means we haven't received this type of message yet, so do nothing
DasSidG 7:70cf5bff23f9 140 break;
DasSidG 7:70cf5bff23f9 141 default:
DasSidG 7:70cf5bff23f9 142 break;
DasSidG 7:70cf5bff23f9 143 }
DasSidG 7:70cf5bff23f9 144 }
DasSidG 7:70cf5bff23f9 145
DasSidG 7:70cf5bff23f9 146 //Import the data from the buffer into a non-volatile, more usable format
DasSidG 7:70cf5bff23f9 147 CANMessage charger_msgArray[CAN_BUFFER_SIZE]; //Same as above but some functions take message as their parameter
DasSidG 7:70cf5bff23f9 148 int charger_received_CAN_IDs[CAN_BUFFER_SIZE]; //needed to keep track of which IDs we've received so far
DasSidG 7:70cf5bff23f9 149 for (int i = 0; i<CAN_BUFFER_SIZE; ++i)
DasSidG 7:70cf5bff23f9 150 {
DasSidG 7:70cf5bff23f9 151 charger_safe_to_write[i] = false;
DasSidG 7:70cf5bff23f9 152 charger_received_CAN_IDs[i] = charger_buffer[i].id;
DasSidG 7:70cf5bff23f9 153 charger_msgArray[i] = charger_buffer[i];
DasSidG 7:70cf5bff23f9 154 charger_buffer[i].id = BLANK_ID;
DasSidG 7:70cf5bff23f9 155 charger_safe_to_write[i] = true;
DasSidG 7:70cf5bff23f9 156
DasSidG 7:70cf5bff23f9 157 //Now actually import the data from the CAN packets into the global variables
DasSidG 7:70cf5bff23f9 158 switch (charger_received_CAN_IDs[i]) {
DasSidG 7:70cf5bff23f9 159
DasSidG 7:70cf5bff23f9 160 case CHARGER_VI_INFO_ID:
DasSidG 7:70cf5bff23f9 161 get_charger_VI_info(charger_msgArray[i], charger_voltage, charger_current, charger_status);
DasSidG 7:70cf5bff23f9 162 if(charger_status bitand 1 == 1) {
DasSidG 7:70cf5bff23f9 163 if (DEBUG) printf("Charger status: Hardware Failure\r\n");
DasSidG 7:70cf5bff23f9 164 charger_failure = true;
DasSidG 7:70cf5bff23f9 165 }
DasSidG 7:70cf5bff23f9 166
DasSidG 7:70cf5bff23f9 167 if(charger_status bitand 2 == 2) {
DasSidG 7:70cf5bff23f9 168 if (DEBUG) printf("Charger status: Over Temperature\r\n");
DasSidG 7:70cf5bff23f9 169 charger_failure = true;
DasSidG 7:70cf5bff23f9 170 }
DasSidG 7:70cf5bff23f9 171
DasSidG 7:70cf5bff23f9 172 if(charger_status bitand 4 == 4) {
DasSidG 7:70cf5bff23f9 173 if (DEBUG) printf("Charger status: Input Voltage Wrong\r\n");
DasSidG 7:70cf5bff23f9 174 charger_failure = true;
DasSidG 7:70cf5bff23f9 175 }
DasSidG 7:70cf5bff23f9 176
DasSidG 7:70cf5bff23f9 177 if(charger_status bitand 8 == 8) {
DasSidG 7:70cf5bff23f9 178 if (DEBUG) printf("Charger status: Reverse Polarity\r\n");
DasSidG 7:70cf5bff23f9 179 charger_failure = true;
DasSidG 7:70cf5bff23f9 180 }
DasSidG 7:70cf5bff23f9 181
DasSidG 7:70cf5bff23f9 182 if(charger_status bitand 16 == 16) {
DasSidG 7:70cf5bff23f9 183 if (DEBUG) printf("Charger status: communication timeout\r\n");
DasSidG 7:70cf5bff23f9 184 charger_failure = true;
DasSidG 7:70cf5bff23f9 185 }
DasSidG 7:70cf5bff23f9 186 break;
DasSidG 7:70cf5bff23f9 187 case BLANK_ID: //This means we haven't received this type of message yet, so do nothing
DasSidG 7:70cf5bff23f9 188 break;
DasSidG 7:70cf5bff23f9 189 default:
DasSidG 7:70cf5bff23f9 190 break;
DasSidG 7:70cf5bff23f9 191 }
DasSidG 7:70cf5bff23f9 192 }
DasSidG 7:70cf5bff23f9 193 }
DasSidG 7:70cf5bff23f9 194
DasSidG 7:70cf5bff23f9 195 void car_CANDataSentCallback(void) {
DasSidG 7:70cf5bff23f9 196 car_CAN_data_sent = true;
DasSidG 7:70cf5bff23f9 197 }
DasSidG 7:70cf5bff23f9 198
DasSidG 7:70cf5bff23f9 199 void charger_CANDataSentCallback(void) {
DasSidG 7:70cf5bff23f9 200 charger_CAN_data_sent = true;
DasSidG 7:70cf5bff23f9 201 }
DasSidG 7:70cf5bff23f9 202
DasSidG 7:70cf5bff23f9 203 void car_interruptHandler()
DasSidG 7:70cf5bff23f9 204 {
DasSidG 7:70cf5bff23f9 205 CANMessage msg;
DasSidG 7:70cf5bff23f9 206 car_can.read(msg);
DasSidG 7:70cf5bff23f9 207 //if(DEBUG) printf("id %d incoming \r\n", msg.id);
DasSidG 7:70cf5bff23f9 208 if(idAccepted(msg.id)) {
DasSidG 7:70cf5bff23f9 209 for(int i=0; i<CAN_BUFFER_SIZE; i++) {
DasSidG 7:70cf5bff23f9 210 if((car_buffer[i].id == msg.id || car_buffer[i].id==BLANK_ID) && car_safe_to_write[i]) {
DasSidG 7:70cf5bff23f9 211 //("id %d added to buffer \r\n", msg.id);
DasSidG 7:70cf5bff23f9 212 car_buffer[i] = msg;
DasSidG 7:70cf5bff23f9 213 //return required so that only first blank buffer entry is converted to incoming message ID each time new message ID is encountered
DasSidG 7:70cf5bff23f9 214 return;
DasSidG 7:70cf5bff23f9 215 }
DasSidG 7:70cf5bff23f9 216 }
DasSidG 7:70cf5bff23f9 217 }
DasSidG 7:70cf5bff23f9 218 }
DasSidG 7:70cf5bff23f9 219
DasSidG 7:70cf5bff23f9 220 void charger_interruptHandler()
DasSidG 7:70cf5bff23f9 221 {
DasSidG 7:70cf5bff23f9 222 CANMessage msg;
DasSidG 7:70cf5bff23f9 223 charger_can.read(msg);
DasSidG 7:70cf5bff23f9 224 //if(DEBUG) printf("id %d incoming \r\n", msg.id);
DasSidG 7:70cf5bff23f9 225 if(idAccepted(msg.id)) {
DasSidG 7:70cf5bff23f9 226 for(int i=0; i<CAN_BUFFER_SIZE; i++) {
DasSidG 7:70cf5bff23f9 227 if((charger_buffer[i].id == msg.id || charger_buffer[i].id==BLANK_ID) && charger_safe_to_write[i]) {
DasSidG 7:70cf5bff23f9 228 //("id %d added to buffer \r\n", msg.id);
DasSidG 7:70cf5bff23f9 229 charger_buffer[i] = msg;
DasSidG 7:70cf5bff23f9 230 //return required so that only first blank buffer entry is converted to incoming message ID each time new message ID is encountered
DasSidG 7:70cf5bff23f9 231 return;
DasSidG 7:70cf5bff23f9 232 }
DasSidG 7:70cf5bff23f9 233 }
DasSidG 7:70cf5bff23f9 234 }
DasSidG 7:70cf5bff23f9 235 }
DasSidG 7:70cf5bff23f9 236
DasSidG 7:70cf5bff23f9 237 bool idAccepted(int id)
DasSidG 7:70cf5bff23f9 238 {
DasSidG 7:70cf5bff23f9 239 switch(id) {
DasSidG 7:70cf5bff23f9 240 case BMS_BASE_ID:
DasSidG 7:70cf5bff23f9 241 timeouts.BMS_timeout.reset();
DasSidG 7:70cf5bff23f9 242 return true;
DasSidG 7:70cf5bff23f9 243
DasSidG 7:70cf5bff23f9 244 case BMS_BASE_ID + MAX_MIN_VOLTAGE:
DasSidG 7:70cf5bff23f9 245 case BMS_BASE_ID + BATTERY_STATUS_ID:
DasSidG 7:70cf5bff23f9 246 case BMS_BASE_ID + BATTERY_PRECHARGE_ID:
DasSidG 7:70cf5bff23f9 247 return true;
DasSidG 7:70cf5bff23f9 248 case CHARGER_VI_INFO_ID:
DasSidG 7:70cf5bff23f9 249 timeouts.charger_timeout.reset();
DasSidG 7:70cf5bff23f9 250 return true;
DasSidG 7:70cf5bff23f9 251 default:
DasSidG 7:70cf5bff23f9 252 return false;
DasSidG 7:70cf5bff23f9 253 }
DasSidG 7:70cf5bff23f9 254 }
DasSidG 7:70cf5bff23f9 255
DasSidG 7:70cf5bff23f9 256 void CAN_Init() {
DasSidG 7:70cf5bff23f9 257 for(int i=0; i<CAN_BUFFER_SIZE; i++)
DasSidG 7:70cf5bff23f9 258 {
DasSidG 7:70cf5bff23f9 259 car_buffer[i].id = BLANK_ID;
DasSidG 7:70cf5bff23f9 260 //("%d",buffer[i].id);
DasSidG 7:70cf5bff23f9 261 car_safe_to_write[i]= true;
DasSidG 7:70cf5bff23f9 262
DasSidG 7:70cf5bff23f9 263 charger_buffer[i].id = BLANK_ID;
DasSidG 7:70cf5bff23f9 264 //("%d",buffer[i].id);
DasSidG 7:70cf5bff23f9 265 charger_safe_to_write[i]= true;
DasSidG 7:70cf5bff23f9 266 }
DasSidG 7:70cf5bff23f9 267
DasSidG 7:70cf5bff23f9 268 //Initialise CAN stuff, attach CAN interrupt handlers
DasSidG 7:70cf5bff23f9 269 car_can.frequency(CAN_BIT_RATE); //set transmission rate to agreed bit rate
DasSidG 7:70cf5bff23f9 270 car_can.reset();
DasSidG 7:70cf5bff23f9 271 car_can.attach(&car_interruptHandler, CAN::RxIrq); //receive interrupt handler
DasSidG 7:70cf5bff23f9 272 car_can.attach(&car_CANDataSentCallback, CAN::TxIrq); //send interrupt handler
DasSidG 7:70cf5bff23f9 273
DasSidG 7:70cf5bff23f9 274 charger_can.frequency(CHARGER_CAN_BIT_RATE); //set transmission rate to agreed bit rate
DasSidG 7:70cf5bff23f9 275 charger_can.reset();
DasSidG 7:70cf5bff23f9 276 charger_can.attach(&charger_interruptHandler, CAN::RxIrq); //receive interrupt handler
DasSidG 7:70cf5bff23f9 277 charger_can.attach(&charger_CANDataSentCallback, CAN::TxIrq); //send interrupt handler
DasSidG 7:70cf5bff23f9 278 }