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:
12:77d493b3320b
--- a/CANParserCharger.cpp	Sun Jul 30 23:01:15 2017 +0000
+++ b/CANParserCharger.cpp	Sun Sep 10 11:10:54 2017 +0000
@@ -6,6 +6,18 @@
 
 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);
@@ -91,4 +103,176 @@
         msg.data[i] = data.get_u8(i);
     }
     return msg;    
-}
\ No newline at end of file
+}
+
+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
+}