CUER
/
charger_code
Code to run on the charger board (used to charge the car from the mains).
Diff: charger.cpp
- Revision:
- 7:70cf5bff23f9
- Parent:
- 5:756fae795d37
- Child:
- 8:e5c07b9b8593
--- a/charger.cpp Sun Jul 30 23:01:15 2017 +0000 +++ b/charger.cpp Sun Sep 10 11:10:54 2017 +0000 @@ -7,25 +7,21 @@ using namespace CAN_IDs; -void car_interruptHandler(); -void car_CANDataSentCallback(); -void charger_interruptHandler(); -void charger_CANDataSentCallback(); + void init(); -void get_CAN_data(); + -void calculate_current(float ¤t); +float calculate_desired_current(float charger_current, float min_cell_voltage); void check_timeouts(); void update_LEDS(); -bool idAccepted(int id); + DigitalOut green_led(p21); //charging LED DigitalOut yellow_led(p22); //timeout LED DigitalOut red_led(p23); //error LED DigitalIn charge_switch(p8); //switch to enable charging -void calculate_current(float voltage_error, float temp_margin, float *current, float *voltage); uint8_t charger_status; //status packet given by charger, see Elcon CAN Specification in google drive bool precharge_status; @@ -33,9 +29,7 @@ bool charger_failure; bool charge_finished; bool bms_error; - - -//float temp_margin = 0; //degrees C, this is the max cell temperature minus max cell temperature limit, need to avoid this hitting 0 +bool charging; float min_cell_voltage = 3600; //mV float max_cell_voltage = 3600;//mV @@ -44,7 +38,7 @@ float charger_voltage; //mV float desired_current = 0; //mA -float desired_voltage = MAX_VOLTAGE; //mV +float desired_voltage = MAX_PACK_VOLTAGE; //mV float voltage_error = 1000; //mV //This = RISING_BALANCE_THRESHOLD - max_cell_voltage @@ -52,29 +46,12 @@ timeouts_t timeouts; -//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; - int main() { init(); while(1) { - - //Reset error indicators - comms_timeout = false; - charger_failure = false; - bms_error = false; - + //get the various data from the CAN packets get_CAN_data(); @@ -83,15 +60,20 @@ charger_control = STOP_CHARGING; - if (min_cell_voltage > RISING_BALANCE_THRESHOLD || charge_finished) { + //if (min_cell_voltage > RISING_BALANCE_THRESHOLD || charge_finished) { //Note: if balancing is implemented, use this version instead + if ((max_cell_voltage > CHARGING_FINISHED_THRESHOLD_VOLTAGE && charger_current < CHARGING_FINISHED_THRESHOLD_CURRENT) + || charge_finished + || max_cell_voltage > MAX_CELL_VOLTAGE) { charge_finished = true; + charging = false; if (DEBUG) printf("Charge Finished\r\n"); car_can.write(generate_charging_finished_msg()); charger_control = STOP_CHARGING; //set charger control bit to stop charging } - else if (precharge_status && charge_switch.read()) { - calculate_current(desired_current); - desired_voltage = MAX_VOLTAGE; + else if (precharge_status && !bms_error && !comms_timeout && !charger_failure && charge_switch.read()) { + charging = true; + desired_current = calculate_desired_current(charger_current, min_cell_voltage); + desired_voltage = MAX_PACK_VOLTAGE; charge_finished = false; charger_control = START_CHARGING; //set charger control bit to start charging } @@ -117,140 +99,48 @@ printf("Min cell voltage = %f \r\n", min_cell_voltage); printf("Max cell voltage = %f \r\n", max_cell_voltage); printf("Precharge status is %d \r\n", precharge_status); + printf("Voltage error is %f \r\n", voltage_error); + printf("\r\n"); } - wait(TIME_STEP); + wait_ms(500); } } -void calculate_current(float ¤t){ - - float Idot; +float calculate_desired_current(float _charger_current, float _min_cell_voltage){ + float _desired_current; + _desired_current += 500; //gradually ramp up current when charging starts - static bool balancing = false; - if (current < 800 && voltage_error < 100 || balancing) { - balancing = true; - if (DEBUG) printf("balancing\r\n"); - Idot = voltage_error *KI_BALANCE; - } - else { - Idot = voltage_error*KI_CHARGE; + if (_min_cell_voltage < DEEP_DISCHARGE_THRESHOLD_VOLTAGE) { + if(_desired_current > DEEP_DISCHARGE_MAX_CURRENT) { + _desired_current = DEEP_DISCHARGE_MAX_CURRENT; + } + } + + else if(_desired_current > MAX_CURRENT) { + _desired_current = MAX_CURRENT; + } + if(_desired_current < 0) { + _desired_current = 0; } - current += Idot*TIME_STEP/1000.0; - - if(current > MAX_CURRENT) { - current = MAX_CURRENT; - } - if(current < 0) { - current = 0; - } - /* - //Reduce current if temperature is too high - if (temp_margin > TEMP_RAMP_START) { - I = 1 - ((temp_margin - TEMP_RAMP_START) / (TEMP_RAMP_FINISH - TEMP_RAMP_START)); - } - if (temp_margin > TEMP_RAMP_FINISH) { - I *= 0; - } - */ + return _desired_current; } void 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 - //Start comms timeout timers - timeouts.BMS_timeout.start(); timeouts.charger_timeout.start(); - precharge_status = false; -} - -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; - } - } - } + //Reset error indicators + comms_timeout = false; + charger_failure = false; + bms_error = false; + charging = false; } -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 check_timeouts() //Check if it's been too long since any of the other devices in the car have communicated { @@ -290,90 +180,3 @@ } -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); - voltage_error = RISING_BALANCE_THRESHOLD - 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; - } - } -} \ No newline at end of file