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

Dependencies:   mbed CUER_CAN

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 &current);
+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 &current){
-        
-    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