diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 7594bd0..1ae7fc9 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -13,4 +13,9 @@ V1.2 - added void sm_calibrate_powerground(); void sm_precharge_discharge_manager(); - fixed the clock in mxcube - cleaned up PWM_powerground_control() -- cleaned up the state machine \ No newline at end of file +- cleaned up the state machine + +V1.3 +- added eeprom.h and eeprom.c, is still WIP +- void sm_check_charging(); was removed, you need to call 0xF1XX to enter charging mode, precharge is then 3 seconds then the relay closes. call 0x0000 to exit charging +- removed some variables and some functions \ No newline at end of file diff --git a/Core/Inc/eeprom.h b/Core/Inc/eeprom.h new file mode 100755 index 0000000..3d21c7a --- /dev/null +++ b/Core/Inc/eeprom.h @@ -0,0 +1,17 @@ +#ifndef INC_EEPROM_H_ +#define INC_EEPROM_H_ + +#include "stm32f3xx_hal.h" + +#include + +__attribute__((packed)) typedef struct { + uint8_t id; +} EEPROMConfig; + +extern EEPROMConfig eeprom_config; + +void eeprom_init(I2C_HandleTypeDef* hi2c); +void eeprom_config_save(); + +#endif // INC_EEPROM_H_ diff --git a/Core/Inc/state_machine.h b/Core/Inc/state_machine.h index 5219dbf..d9d610b 100644 --- a/Core/Inc/state_machine.h +++ b/Core/Inc/state_machine.h @@ -24,7 +24,6 @@ // Time to wait between closing relays #define RELAY_CLOSE_WAIT 10 // ms -#warning typedef enum { // states -> 3 bit. valid transitions: (all could transition to error) STATE_INACTIVE, // INACTIVE -> PRECHARGE, CHARGING, ERROR STATE_PRECHARGE, // PRECHARGE -> INACTIVE, READY, DISCHARGE, ERROR @@ -59,8 +58,6 @@ typedef struct { } StateHandle; extern StateHandle state; -static bool relay_closed = 0; //NOTE: unused? -static bool precharge_closed = 0; //NOTE: unused? extern int16_t RELAY_BAT_SIDE_VOLTAGE; extern int16_t RELAY_ESC_SIDE_VOLTAGE; extern int16_t CURRENT_MEASUREMENT; @@ -82,15 +79,13 @@ State sm_update_error(); typedef enum { RELAY_MAIN, RELAY_PRECHARGE } Relay; void sm_set_relay_positions(State state); void sm_set_relay(Relay relay, bool closed); -void sm_check_charging(); -void sm_check_battery_temperature(int8_t* id, int16_t* temp); +void sm_check_battery_temperature(int8_t* id, int16_t* temp); int16_t sm_return_cell_temperature(int id); int16_t sm_return_cell_voltage(int id); void sm_calibrate_powerground(); void sm_precharge_discharge_manager(); -void sm_powerground_manager(int8_t percent, bool source); void sm_handle_ams_in(const uint8 *data); void sm_check_errors(); diff --git a/Core/Src/eeprom.c b/Core/Src/eeprom.c new file mode 100755 index 0000000..c6853bb --- /dev/null +++ b/Core/Src/eeprom.c @@ -0,0 +1,60 @@ +#include "eeprom.h" +#include "errors.h" +#include "stm32f3xx_hal.h" + +#include + +#define EEPROM_I2C_ADDR 0xA0 +// Don't use the beginning of the EEPROM, since the testbench writes there +#define EEPROM_CONFIG_BASE 0x0100 +#define EEPROM_CONFIG_ECC_OFFSET 0x20 + +EEPROMConfig eeprom_config; + +static I2C_HandleTypeDef* hi2c; + +void eeprom_init(I2C_HandleTypeDef* handle) { + hi2c = handle; + uint8_t buf[sizeof(EEPROMConfig) * 3]; + // Read 3 EEPROM config buffers at 32 byte offsets + for (size_t ecc_i = 0; ecc_i < 3; ecc_i++) { + HAL_StatusTypeDef status = HAL_I2C_Mem_Read( + hi2c, EEPROM_I2C_ADDR, + EEPROM_CONFIG_BASE + EEPROM_CONFIG_ECC_OFFSET * ecc_i, 2, + buf + sizeof(EEPROMConfig) * ecc_i, sizeof(EEPROMConfig), 100); + if (status != HAL_OK) { + set_error_source(ERROR_SOURCE_EEPROM); + } + } + // ECC + for (size_t i = 0; i < sizeof(EEPROMConfig); i++) { + const uint8_t a = buf[i + sizeof(EEPROMConfig) * 0]; + const uint8_t b = buf[i + sizeof(EEPROMConfig) * 1]; + const uint8_t c = buf[i + sizeof(EEPROMConfig) * 2]; + if (a == b || a == c) { + buf[i] = a; + } else if (b == c) { + buf[i] = b; + } else { + set_error_source(ERROR_SOURCE_EEPROM); + } + } + + memcpy(&eeprom_config, buf, sizeof(EEPROMConfig)); + // Write back config + // eeprom_config.id = 3; + eeprom_config_save(); +} + +void eeprom_config_save() { + for (size_t ecc_i = 0; ecc_i < 3; ecc_i++) { + HAL_StatusTypeDef status = HAL_I2C_Mem_Write( + hi2c, EEPROM_I2C_ADDR, + EEPROM_CONFIG_BASE + EEPROM_CONFIG_ECC_OFFSET * ecc_i, 2, + (uint8_t*)&eeprom_config, sizeof(eeprom_config), 100); + if (status != HAL_OK) { + set_error_source(ERROR_SOURCE_EEPROM); + } + HAL_Delay(100); + } +} diff --git a/Core/Src/state_machine.c b/Core/Src/state_machine.c index 04266f6..fb70cdf 100644 --- a/Core/Src/state_machine.c +++ b/Core/Src/state_machine.c @@ -16,7 +16,6 @@ bool CURRENT_MEASUREMENT_ON; uint8_t powerground_status; uint32_t precharge_timer; uint32_t discharge_timer; -uint32_t charging_timer; uint32_t powerground_calibration_timer; uint8_t powerground_calibration_stage; @@ -27,14 +26,15 @@ void sm_init(){ state.current_state = STATE_INACTIVE; state.target_state = STATE_INACTIVE; state.error_source = 0; - precharge_timer = discharge_timer = charging_timer = powerground_calibration_timer = 0; + precharge_timer = discharge_timer = powerground_calibration_timer = 0; } +#warning change amsState here void sm_update(){ sm_check_errors(); sm_precharge_discharge_manager(); sm_calibrate_powerground(); - + int16_t base_offset = 0; if (state.current_state == STATE_INACTIVE){ base_offset = module.auxVoltages[0]; @@ -202,24 +202,13 @@ void sm_set_relay(Relay relay, bool closed){ switch (relay) { case RELAY_MAIN: HAL_GPIO_WritePin(RELAY_ENABLE_GPIO_Port, RELAY_ENABLE_Pin, state); - relay_closed = closed; break; case RELAY_PRECHARGE: HAL_GPIO_WritePin(PRECHARGE_ENABLE_GPIO_Port, PRECHARGE_ENABLE_Pin, state); - precharge_closed = closed; break; } } -void sm_check_charging(){ - #warning fix this timestamp check - if (RELAY_BAT_SIDE_VOLTAGE < RELAY_ESC_SIDE_VOLTAGE && timestamp == 0) - timestamp = HAL_GetTick() + 5000; - - if (timestamp < HAL_GetTick()) - state.target_state = STATE_CHARGING_PRECHARGE; -} - /* returns the ID and temperature of the hottest cell */ void sm_check_battery_temperature(int8_t *id, int16_t *temp){ for (int i = 0; i < N_TEMP_SENSORS; i++) { @@ -232,13 +221,6 @@ void sm_check_battery_temperature(int8_t *id, int16_t *temp){ void sm_precharge_discharge_manager(){ - if (state.current_state != STATE_DISCHARGE && state.target_state == STATE_DISCHARGE){ - discharge_timer = HAL_GetTick() + DISCHARGE_DURATION; - } else if (state.current_state == STATE_DISCHARGE && discharge_timer < HAL_GetTick()) { - state.target_state = STATE_INACTIVE; - discharge_timer = 0; - } - if (state.current_state != STATE_PRECHARGE && state.target_state == STATE_PRECHARGE){ precharge_timer = HAL_GetTick() + PRECHARGE_DURATION; } else if (state.current_state == STATE_PRECHARGE && precharge_timer < HAL_GetTick()) { @@ -249,32 +231,17 @@ void sm_precharge_discharge_manager(){ if (state.current_state != STATE_CHARGING_PRECHARGE && state.target_state == STATE_CHARGING_PRECHARGE){ precharge_timer = HAL_GetTick() + PRECHARGE_DURATION; } else if (state.current_state == STATE_CHARGING_PRECHARGE && precharge_timer < HAL_GetTick()) { - state.target_state = STATE_READY; + state.target_state = STATE_CHARGING; precharge_timer = 0; } -} - -// source 0 -> sm_update() -// source 1 -> sm_ams_in() -void sm_powerground_manager(int8_t percent, bool source){ - if (powerground_calibration_stage != 4 && state.current_state == STATE_ACTIVE){ - sm_calibrate_powerground(); - } else if (powerground_calibration_stage == 4){ - if (state.current_state == STATE_PRECHARGE){ - PWM_powerground_control(0); - } else if (state.current_state == STATE_READY || state.current_state == STATE_ACTIVE){ - if (percent < 10){ - PWM_powerground_control(0); - } else if (percent > 100){ - PWM_powerground_control(255); - state.current_state = STATE_ACTIVE; - } - PWM_powerground_control(percent); - } else { - PWM_powerground_control(255); - } + if (state.current_state != STATE_DISCHARGE && state.target_state == STATE_DISCHARGE){ + discharge_timer = HAL_GetTick() + DISCHARGE_DURATION; + } else if (state.current_state == STATE_DISCHARGE && discharge_timer < HAL_GetTick()) { + state.target_state = STATE_INACTIVE; + discharge_timer = 0; } + } void sm_calibrate_powerground(){ @@ -330,7 +297,15 @@ void sm_handle_ams_in(const uint8_t *data){ state.target_state = STATE_ACTIVE; // READY -> ACTIVE } break; - case 0xFF: // emergency shutdown or EEPROM + case 0xF0: + if (state.current_state == STATE_INACTIVE){ + state.target_state = STATE_CHARGING_PRECHARGE; + } + break; + #warning implement this + case 0xF1: // EEPROM + break; + case 0xFF: // EMERGENCY SHUTDOWN break; } } @@ -380,13 +355,9 @@ void sm_check_errors(){ } } -int16_t sm_return_cell_temperature(int id){ - return tmp1075_temps[id]; -} +int16_t sm_return_cell_temperature(int id){ return tmp1075_temps[id]; } -int16_t sm_return_cell_voltage(int id){ - return module.cellVoltages[id]; -} +int16_t sm_return_cell_voltage(int id){ return module.cellVoltages[id]; } void sm_test_cycle_states(){ RELAY_BAT_SIDE_VOLTAGE = module.auxVoltages[0]; @@ -419,7 +390,11 @@ void sm_test_cycle_states(){ state.current_state = STATE_INACTIVE; timestamp = HAL_GetTick() + 10000; break; - } + case STATE_CHARGING_PRECHARGE: + case STATE_CHARGING: + case STATE_ERROR: + break; + } state.target_state = state.current_state; }