Has base BMU code but sends dummy temperature and voltage readings to test CAN

Dependencies:   CUER_CAN DS1820 LTC2943 LTC6804 mbed

Fork of BMS_BMUCore_Max by CUER

Revision:
1:51477fe4851b
Parent:
0:0a5f554d2a16
Child:
2:94716229ecc3
--- a/main.cpp	Thu Dec 22 15:11:29 2016 +0000
+++ b/main.cpp	Fri Dec 30 16:01:59 2016 +0000
@@ -1,5 +1,4 @@
-/* 
-Should add a sleep in here
+/*
 Should also consider the different errors that need to be sent
 */
 #include "mbed.h"
@@ -7,114 +6,222 @@
 #include "Data_Types_BMU.h"
 #include "CAN_Data.h"
 #include "CAN_IDs.h"
+#include "EEPROM_I2C.h"
+#include "Temperature.h"
 
 using namespace CAN_IDs;
 
 // Function definitions
-void transmit_data();
-void read_EEPROM_startup();
-void write_EEPROM();
-void take_measurements();
-void read_temperature_sensors();
+void transmit_data(BMU_data measurements,uint32_t status);
+void read_temperature_sensors(BMU_data &measurements);
 void update_SOC();
-void read_sensors();
 void init();
+void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address);
+uint16_t read_EEPROM_startup(BMU_data &measurements);
+uint32_t check_measurements(BMU_data &measurements);
+void take_measurements(BMU_data &measurements);
 
 CAN can(CAN_READ_PIN, CAN_WRITE_PIN); //Create a CAN object to handle CAN comms
 
+Timeout loop_delay;
+bool delay_finished = false;
+ 
+void loop_delay_callback(void) {
+    delay_finished = true;
+}
+
 int main()
 {
+    BMU_data measurements;
+    uint16_t current_EEPROM_address;
+    uint32_t status;
     int c = 0;
     init();
-    read_EEPROM_startup();
+    current_EEPROM_address = read_EEPROM_startup(measurements);
     // Read from the eeprom at startup to fill in the values
-    while (true)
-    {
-        // Reading
-        read_sensors();
+    while (true) {
+        
+        // Take measurements from the sensors
+        take_measurements(measurements);
         // Dont want to read the temperature sensors during each iteration of the loop
-        if (c == 0)
-        {
-            read_temperature_sensors();
-        }
-        else if(c >= 4)
-        {
+        if (c == 0) {
+            read_temperature_sensors(measurements);
+        } else if(c >= 4) {
             c = -1;
         }
         c++;
 
-        // Check the data
-        take_measurements();
-        
+        // Check data for errors
+        status = check_measurements(measurements);
+
         // Update the SOC
         update_SOC();
 
-        //Store data in the eeprom 
-        write_EEPROM();
+        //Store data in the eeprom
+        write_SOC_EEPROM(measurements, current_EEPROM_address);
 
         // CAN bus transactions
-        transmit_data();
+        transmit_data(measurements,status);
 
         // Conserve power - enter a low powered mode
+        delay_finished = false; 
+        loop_delay.attach(loop_delay_callback, LOOP_DELAY_S);
+        while (!delay_finished) sleep();
     }
 }
 
-void transmit_data()
+void transmit_data(BMU_data measurements, uint32_t status)
 {
     /*
     Place all of the collected data onto the CAN bus
     */
-}
+    // Send cell voltaages voltages
+    for(int i= 0; i < NO_CMUS; i++) {
+        createVoltageTelemetry(i + 2 , measurements.cell_voltages[i].first_cell_voltages);
+        createVoltageTelemetry(i + 3, measurements.cell_voltages[i].last_cell_voltages);
+    }
+
+    // Create SOC CAN message
+    createPackSOC(measurements.SOC, measurements.percentage_SOC);
 
-void read_EEPROM_startup()
-{
-    // Read from location 0 on startup
+    // Min/max cell voltages
+    createCellVoltageMAXMIN(measurements.max_cell_voltage, measurements.min_cell_voltage);
+    
+    // Min/Max cell temperature
+    createCellTemperatureMAXMIN(measurements.min_cell_temp,measurements.max_cell_temp);
+    
+    // Battery voltage and current 
+    // @TODO make add the voltage and current 
+    createBatteryVI(measurements.battery_voltage,measurements.battery_current);
+    
+    //Extended battery pack status
+    createExtendedBatteryPackStatus(status);
     
 }
 
-void write_EEPROM()
+uint16_t read_EEPROM_startup(BMU_data &measurements)
 {
-/*
-    First must read from location 0 to get a pointer to a location
-    Then write the data into the eeprom, using a new location every time
-    Must check that the data you are writing isn't outside the boaunds of the storage space
+    /* The first page of the EEPROM, specifically the first 2 addresses store a
+    pointer of the first memory location of measurement data. The EEPROM only has a finite number of
+    read/write cycles which is why we aren't writing to the same location throughout
+    */
+    uint16_t start_address;
+    char start_address_array[2];
+    char SOC_out[8]; // 4 bytes for the 2 floats one is SOC and the other % charge
+    float *fp1,*fp2; // temporary storage for float conversion
+
+    // Get a pointer to the start address for the data stored in the eeprom
+    i2c_page_read(0x0000,2,start_address_array);
+
+    // Read the data from this address
+    start_address = (start_address_array[1]<< 8) | start_address_array[0]; // mbed little endian follow this convention
+    i2c_page_read(start_address, 8,SOC_out);
 
-*/
+    // Convert the SOC_out values back into floats
+    fp1 = (float*)(&SOC_out[0]);
+    fp2 = (float*)(&SOC_out[4]);
+    measurements.SOC = *fp1;
+    measurements.percentage_SOC = *fp2;
+
+    // Select the next address to write to
+    start_address += 0x0040;
+    if(start_address > MAX_WRITE_ADDRESS) {
+        start_address = START_WRITE_ADDRESS; // Loop round to the start of the eeprom
+    }
+
+    // write the new address to location 0x0000
+    start_address_array[0] = start_address | 0x00FF;
+    start_address_array[1] = start_address >> 8;
+    i2c_page_write(0x0000, 2, start_address_array);
+
+    return start_address;
 }
 
-void take_measurements()
+void write_SOC_EEPROM(BMU_data &measurements,uint16_t start_address)
 {
+    char data_out[8];
+    float *fp1,*fp2;
+
+    fp1 = (float*)(&measurements.SOC);
+    fp2 = (float*)(&measurements.percentage_SOC);
 
-/*Data to check:
-    *No data from the sensore
-    *Temperature bounds
-    *Cell overvoltage
-    *Current overvoltage
-Have an array of error flags
-*/
+    for(int i = 0; i < 4; i++ ) {
+        data_out[i] = *fp1;
+        fp1++;
+    }
+    for(int j = 4; j < 7; j++ ) {
+        data_out[j] = *fp2;
+        fp2++;
+    }
+    i2c_page_write(start_address, 8,data_out);
 }
 
-void read_temperature_sensors()
+void read_temperature_sensors(BMU_data &measurements)
 {
-    //this is a separate function since reading the temperature will be less frequent
+    float min_temperature;
+    float max_temperature;
+
+    probe[0]->convert_temperature(DS1820::all_devices);
+    min_temperature = probe[0]->temperature('C');
+    max_temperature = min_temperature; // Initially set the max and min temperature equal
+    for (int i=1; i<devices_found; i++) {
+        
+        measurements.temperature_measurements[i].ID = i;
+        measurements.temperature_measurements[i].measurement = probe[i] ->temperature('C');
+        
+        if(measurements.temperature_measurements[i].measurement > max_temperature) {
+            max_temperature = measurements.temperature_measurements[i].measurement;
+        } 
+        else if (measurements.temperature_measurements[i].measurement < min_temperature) {
+            min_temperature = measurements.temperature_measurements[i].measurement;
+        }
+    }
+    measurements.max_cell_temp.temperature = max_temperature;
+    measurements.min_cell_temp.temperature = min_temperature;
 }
 
 void update_SOC()
 {
-    // Update the SOC value    
-}
-
-void read_sensors()
-{
-// Like the sound of passing the data in as an array so call by reference could use pointers or a while loop to copy data over??
-// Read every sensor apart from the temperature sensors
-// Read BMS_BCUCORE_balancing
-// Read SOC
+    // Update the SOC value
 }
 
 
+uint32_t check_measurements(BMU_data &measurements)
+{
+    uint32_t status;
+    
+    if(measurements.max_cell_voltage.voltage > MAX_CELL_VOLTAGE)
+    {
+            status = status | CELL_OVER_VOLTAGE;
+    }
+    else if (measurements.min_cell_voltage.voltage < MIN_CELL_VOLTAGE)
+    {
+        status = status | CELL_UNDER_VOLTAGE;
+    }
+    else if (measurements.max_cell_temp.temperature > MAX_CELL_TEMPERATURE)
+    {
+        status = status | CELL_OVER_TEMPERATURE;
+    }
+    
+    /*
+    @TODO also include errors for:
+    *untrusted measurement
+    *CMU timeout
+    *SOC not valid
+    */
+    return status;
+}
+
+void take_measurements(BMU_data &measurements)
+{
+    // Here collect all measured data from the sensors 
+    /*
+    TODO SOC and cell voltages
+    */
+}
+
 void init()
 {
-    // Is this required??
+    temperature_init(); // Initialise the temperature sensors
 }