![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
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
Diff: main.cpp
- 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 }