CUER
/
charger_code
Code to run on the charger board (used to charge the car from the mains).
CANParserCharger.cpp
- Committer:
- DasSidG
- Date:
- 2017-09-12
- Revision:
- 12:77d493b3320b
- Parent:
- 7:70cf5bff23f9
File content as of revision 12:77d493b3320b:
// Here are the functions to generate the CAN messages #include "CANParserCharger.h" #include "mbed.h" #include "CAN_IDs.h" using namespace CAN_IDs; //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). //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. CAN car_can(CAR_CAN_READ_PIN, CAR_CAN_WRITE_PIN); //Create a CAN object to handle CAN comms CANMessage car_buffer[CAN_BUFFER_SIZE]; //CAN receive buffer bool car_safe_to_write[CAN_BUFFER_SIZE]; //Semaphore bit indicating that it's safe to write to the software buffer bool car_CAN_data_sent = false; CAN charger_can(CHARGER_CAN_READ_PIN, CHARGER_CAN_WRITE_PIN); //Create a CAN object to handle CAN comms CANMessage charger_buffer[CAN_BUFFER_SIZE]; //CAN receive buffer bool charger_safe_to_write[CAN_BUFFER_SIZE]; //Semaphore bit indicating that it's safe to write to the software buffer bool charger_CAN_data_sent = false; void get_max_min_voltage(CANMessage msg, float &_min_cell_voltage, float &_max_cell_voltage) { CAN_Data data; data.importCANData(msg); _min_cell_voltage = (float) data.get_u16(0); _max_cell_voltage = (float) data.get_u16(1); } void get_battery_status(CANMessage msg, bool &error) { //note using extended battery pack status CAN_Data data; data.importCANData(msg); error = data.getLower_uLong() > 0; //ignore the rest of the status as we don't care } void get_charger_VI_info(CANMessage msg, float &_charger_voltage, float &_charger_current, uint8_t &_charger_status) { CAN_Data data; data.importCANData(msg); _charger_voltage = data.get_u16(0)*100.0; _charger_current = data.get_u16(1)*100.0; _charger_status = data.get_u8(4); } void check_precharge_status (CANMessage msg, bool &_precharge_ready) { CAN_Data data; data.importCANData(msg); if(data.get_u8(1) == 4) _precharge_ready = true; else _precharge_ready = false; } CANMessage generate_charger_control_msg(float _desired_voltage, float _desired_current, uint8_t _charger_control) { CANMessage msg; msg.format = CANExtended; //the charger uses the extended CAN frame format msg.len = 8; msg.id = CHARGER_VI_CONTROL_ID; CAN_Data data; data.set_u16(0, (uint16_t) (_desired_voltage/100)); data.set_u16(1, (uint16_t) (_desired_current/100)); data.set_u8(4, _charger_control); data.set_u8(5,0); data.set_u8(6,0); data.set_u8(7,0); for(int i=0; i<8; i++) { msg.data[i] = data.get_u8(i); } return msg; } CANMessage generate_charger_info_msg(float _charger_voltage, float _charger_current, uint8_t _charger_status, bool _charger_timeout, bool _bms_timeout) { CANMessage msg; msg.len = 8; msg.id = CHARGER_ID; CAN_Data data; data.set_u16(0, (uint16_t) (_charger_voltage/100)); data.set_u16(1, (uint16_t) (_charger_current/100)); data.set_u8(4, _charger_status); data.set_u8(5, _charger_timeout); data.set_u8(6, _bms_timeout); data.set_u8(7,0); for(int i=0; i<8; i++) { msg.data[i] = data.get_u8(i); } return msg; } CANMessage generate_charging_finished_msg() { CANMessage msg; msg.len = 8; msg.id = BMS_BASE_ID + EEPROM_RESET_ID; CAN_Data data; data.setLowerFloat(PACK_CAPACITY); //42 is the pack capacity in Ah data.setUpperFloat(100); //100% as fully charged for(int i=0; i<8; i++) { msg.data[i] = data.get_u8(i); } return msg; } void get_CAN_data() { //Import the data from the buffer into a non-volatile, more usable format CANMessage car_msgArray[CAN_BUFFER_SIZE]; //Same as above but some functions take message as their parameter int car_received_CAN_IDs[CAN_BUFFER_SIZE]; //needed to keep track of which IDs we've received so far for (int i = 0; i<CAN_BUFFER_SIZE; ++i) { car_safe_to_write[i] = false; car_received_CAN_IDs[i] = car_buffer[i].id; car_msgArray[i] = car_buffer[i]; car_buffer[i].id = BLANK_ID; //this effectively clears the buffer, so that we never reuse old values car_safe_to_write[i] = true; //Now actually import the data from the CAN packets into the global variables switch (car_received_CAN_IDs[i]) { case BMS_BASE_ID: break; case BMS_BASE_ID + MAX_MIN_VOLTAGE: get_max_min_voltage(car_msgArray[i], min_cell_voltage, max_cell_voltage); break; case BMS_BASE_ID + BATTERY_STATUS_ID: get_battery_status(car_msgArray[i], bms_error); break; case BMS_BASE_ID + BATTERY_PRECHARGE_ID: check_precharge_status(car_msgArray[i], precharge_status); break; case BLANK_ID: //This means we haven't received this type of message yet, so do nothing break; default: break; } } //Import the data from the buffer into a non-volatile, more usable format CANMessage charger_msgArray[CAN_BUFFER_SIZE]; //Same as above but some functions take message as their parameter int charger_received_CAN_IDs[CAN_BUFFER_SIZE]; //needed to keep track of which IDs we've received so far for (int i = 0; i<CAN_BUFFER_SIZE; ++i) { charger_safe_to_write[i] = false; charger_received_CAN_IDs[i] = charger_buffer[i].id; charger_msgArray[i] = charger_buffer[i]; charger_buffer[i].id = BLANK_ID; charger_safe_to_write[i] = true; //Now actually import the data from the CAN packets into the global variables switch (charger_received_CAN_IDs[i]) { case CHARGER_VI_INFO_ID: get_charger_VI_info(charger_msgArray[i], charger_voltage, charger_current, charger_status); if(charger_status bitand 1 == 1) { if (DEBUG) printf("Charger status: Hardware Failure\r\n"); charger_failure = true; } if(charger_status bitand 2 == 2) { if (DEBUG) printf("Charger status: Over Temperature\r\n"); charger_failure = true; } if(charger_status bitand 4 == 4) { if (DEBUG) printf("Charger status: Input Voltage Wrong\r\n"); charger_failure = true; } if(charger_status bitand 8 == 8) { if (DEBUG) printf("Charger status: Reverse Polarity\r\n"); charger_failure = true; } if(charger_status bitand 16 == 16) { if (DEBUG) printf("Charger status: communication timeout\r\n"); charger_failure = true; } break; case BLANK_ID: //This means we haven't received this type of message yet, so do nothing break; default: break; } } } void car_CANDataSentCallback(void) { car_CAN_data_sent = true; } void charger_CANDataSentCallback(void) { charger_CAN_data_sent = true; } void car_interruptHandler() { CANMessage msg; car_can.read(msg); //if(DEBUG) printf("id %d incoming \r\n", msg.id); if(idAccepted(msg.id)) { for(int i=0; i<CAN_BUFFER_SIZE; i++) { if((car_buffer[i].id == msg.id || car_buffer[i].id==BLANK_ID) && car_safe_to_write[i]) { //("id %d added to buffer \r\n", msg.id); car_buffer[i] = msg; //return required so that only first blank buffer entry is converted to incoming message ID each time new message ID is encountered return; } } } } void charger_interruptHandler() { CANMessage msg; charger_can.read(msg); //if(DEBUG) printf("id %d incoming \r\n", msg.id); if(idAccepted(msg.id)) { for(int i=0; i<CAN_BUFFER_SIZE; i++) { if((charger_buffer[i].id == msg.id || charger_buffer[i].id==BLANK_ID) && charger_safe_to_write[i]) { //("id %d added to buffer \r\n", msg.id); charger_buffer[i] = msg; //return required so that only first blank buffer entry is converted to incoming message ID each time new message ID is encountered return; } } } } bool idAccepted(int id) { switch(id) { case BMS_BASE_ID: timeouts.BMS_timeout.reset(); return true; case BMS_BASE_ID + MAX_MIN_VOLTAGE: case BMS_BASE_ID + BATTERY_STATUS_ID: case BMS_BASE_ID + BATTERY_PRECHARGE_ID: return true; case CHARGER_VI_INFO_ID: timeouts.charger_timeout.reset(); return true; default: return false; } } void CAN_Init() { for(int i=0; i<CAN_BUFFER_SIZE; i++) { car_buffer[i].id = BLANK_ID; //("%d",buffer[i].id); car_safe_to_write[i]= true; charger_buffer[i].id = BLANK_ID; //("%d",buffer[i].id); charger_safe_to_write[i]= true; } //Initialise CAN stuff, attach CAN interrupt handlers car_can.frequency(CAN_BIT_RATE); //set transmission rate to agreed bit rate car_can.reset(); car_can.attach(&car_interruptHandler, CAN::RxIrq); //receive interrupt handler car_can.attach(&car_CANDataSentCallback, CAN::TxIrq); //send interrupt handler charger_can.frequency(CHARGER_CAN_BIT_RATE); //set transmission rate to agreed bit rate charger_can.reset(); charger_can.attach(&charger_interruptHandler, CAN::RxIrq); //receive interrupt handler charger_can.attach(&charger_CANDataSentCallback, CAN::TxIrq); //send interrupt handler }