|
|
|
|
@ -6,6 +6,7 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "state_machine.h"
|
|
|
|
|
#include "ADBMS_Abstraction.h"
|
|
|
|
|
#include "AMS_HighLevel.h"
|
|
|
|
|
#include "PWM_control.h"
|
|
|
|
|
#include "TMP1075.h"
|
|
|
|
|
@ -89,6 +90,138 @@ void sm_update(){
|
|
|
|
|
state.target_state = state.current_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sm_handle_ams_in(const uint8_t *data){
|
|
|
|
|
CAN_timer = HAL_GetTick() + CAN_TIMEOUT;
|
|
|
|
|
switch (data[0]) {
|
|
|
|
|
case 0x00:
|
|
|
|
|
if (state.current_state != STATE_INACTIVE){
|
|
|
|
|
state.target_state = STATE_DISCHARGE;
|
|
|
|
|
PWM_powerground_control(255);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0x01:
|
|
|
|
|
if (state.target_state == STATE_INACTIVE || state.target_state == STATE_DISCHARGE){
|
|
|
|
|
state.target_state = STATE_PRECHARGE;
|
|
|
|
|
PWM_powerground_control(0);
|
|
|
|
|
} else if (state.target_state == STATE_ACTIVE){
|
|
|
|
|
state.target_state = STATE_READY;
|
|
|
|
|
PWM_powerground_control(0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0x02:
|
|
|
|
|
if (state.current_state == STATE_READY || state.current_state == STATE_ACTIVE){
|
|
|
|
|
PWM_powerground_control(data[1]);
|
|
|
|
|
state.target_state = STATE_ACTIVE; // READY -> ACTIVE
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
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
|
|
|
|
|
state.current_state = STATE_DISCHARGE;
|
|
|
|
|
state.target_state = STATE_ERROR;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sm_precharge_discharge_manager(){
|
|
|
|
|
|
|
|
|
|
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()) {
|
|
|
|
|
state.target_state = STATE_READY;
|
|
|
|
|
precharge_timer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_CHARGING;
|
|
|
|
|
precharge_timer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(){
|
|
|
|
|
if (powerground_calibration_stage != 4 && state.current_state == STATE_READY){
|
|
|
|
|
switch (powerground_calibration_stage) {
|
|
|
|
|
case 0:
|
|
|
|
|
powerground_calibration_timer = HAL_GetTick() + 0;
|
|
|
|
|
powerground_calibration_stage = 1;
|
|
|
|
|
return;
|
|
|
|
|
case 1:
|
|
|
|
|
if (powerground_calibration_timer < HAL_GetTick()){
|
|
|
|
|
powerground_calibration_timer = HAL_GetTick() + 2000;
|
|
|
|
|
powerground_calibration_stage = 2;
|
|
|
|
|
PWM_powerground_control(100);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 2:
|
|
|
|
|
if (powerground_calibration_timer < HAL_GetTick()){
|
|
|
|
|
powerground_calibration_timer = HAL_GetTick() + 1000;
|
|
|
|
|
powerground_calibration_stage = 3;
|
|
|
|
|
PWM_powerground_control(0);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 3:
|
|
|
|
|
if (powerground_calibration_timer < HAL_GetTick()){
|
|
|
|
|
powerground_calibration_stage = 4;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#warning TODO: add error checking for everything here
|
|
|
|
|
void sm_check_errors(){
|
|
|
|
|
state.error_type.temperature_error = (error_data.error_sources & (1 << 0) || error_data.error_sources & (1 << 1) || error_data.error_sources & (1 << 4)) ? 1 : 0;
|
|
|
|
|
state.error_type.voltage_error = (error_data.error_sources & (1 << 2)|| error_data.error_sources & (1 << 3)|| error_data.error_sources & (1 << 5) || RELAY_BAT_SIDE_VOLTAGE < 30000) ? 1 : 0;
|
|
|
|
|
state.error_type.bms_timeout = (error_data.error_sources & (1 << 7)) ? 1 : 0;
|
|
|
|
|
state.error_type.bms_fault = (error_data.error_sources & (1 << 8) || error_data.error_sources & (1 << 10) || error_data.error_sources & (1 << 9)) ? 1 : 0;
|
|
|
|
|
//SEK_EEPROM_ERR: state.error_type.eeprom_error = 1;
|
|
|
|
|
//state.error_type.current_error = (powerground_status > 10 && CURRENT_MEASUREMENT < 500) ? 1 : 0;
|
|
|
|
|
state.error_type.current_sensor_missing = (!CURRENT_MEASUREMENT_ON) ? 1 : 0;
|
|
|
|
|
state.error_type.voltage_missing = (RELAY_BAT_SIDE_VOLTAGE < 1000) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( state.error_type.current_error == 1 || state.error_type.current_sensor_missing == 1 || //state.error_type.eeprom_error == 1 ||
|
|
|
|
|
state.error_type.state_transition_fail == 1 || state.error_type.temperature_error == 1 || state.error_type.voltage_error == 1 ||
|
|
|
|
|
state.error_type.voltage_missing == 1 || state.error_type.bms_fault == 1 || state.error_type.bms_timeout == 1){
|
|
|
|
|
if (state.current_state != STATE_INACTIVE && state.current_state != STATE_ERROR)
|
|
|
|
|
state.current_state = STATE_DISCHARGE;
|
|
|
|
|
state.target_state = STATE_ERROR;
|
|
|
|
|
PWM_powerground_control(255);
|
|
|
|
|
} else if (state.current_state == STATE_ERROR){
|
|
|
|
|
state.target_state = STATE_INACTIVE;
|
|
|
|
|
}
|
|
|
|
|
sm_set_error_source();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sm_set_error_source(){
|
|
|
|
|
state.error_source = 0;
|
|
|
|
|
state.error_source |= (state.error_type.bms_timeout << 0);
|
|
|
|
|
state.error_source |= (state.error_type.bms_fault << 1);
|
|
|
|
|
state.error_source |= (state.error_type.temperature_error << 2);
|
|
|
|
|
state.error_source |= (state.error_type.current_error << 3);
|
|
|
|
|
|
|
|
|
|
state.error_source |= (state.error_type.current_sensor_missing << 4);
|
|
|
|
|
state.error_source |= (state.error_type.voltage_error << 5);
|
|
|
|
|
state.error_source |= (state.error_type.voltage_missing << 6);
|
|
|
|
|
state.error_source |= (state.error_type.state_transition_fail << 7);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
State sm_update_inactive(){
|
|
|
|
|
switch (state.target_state) {
|
|
|
|
|
case STATE_PRECHARGE:
|
|
|
|
|
@ -162,6 +295,8 @@ State sm_update_charging(){
|
|
|
|
|
case STATE_DISCHARGE:
|
|
|
|
|
return STATE_DISCHARGE;
|
|
|
|
|
default:
|
|
|
|
|
//amsConfigBalancing((1 << 7), 0xF);
|
|
|
|
|
//amsStartBalancing(0);e
|
|
|
|
|
return STATE_CHARGING;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -236,135 +371,6 @@ void sm_check_battery_temperature(int8_t *id, int16_t *temp){
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sm_precharge_discharge_manager(){
|
|
|
|
|
|
|
|
|
|
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()) {
|
|
|
|
|
state.target_state = STATE_READY;
|
|
|
|
|
precharge_timer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_CHARGING;
|
|
|
|
|
precharge_timer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(){
|
|
|
|
|
if (powerground_calibration_stage != 4 && state.current_state == STATE_READY){
|
|
|
|
|
switch (powerground_calibration_stage) {
|
|
|
|
|
case 0:
|
|
|
|
|
powerground_calibration_timer = HAL_GetTick() + 0;
|
|
|
|
|
powerground_calibration_stage = 1;
|
|
|
|
|
return;
|
|
|
|
|
case 1:
|
|
|
|
|
if (powerground_calibration_timer < HAL_GetTick()){
|
|
|
|
|
powerground_calibration_timer = HAL_GetTick() + 2000;
|
|
|
|
|
powerground_calibration_stage = 2;
|
|
|
|
|
PWM_powerground_control(100);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 2:
|
|
|
|
|
if (powerground_calibration_timer < HAL_GetTick()){
|
|
|
|
|
powerground_calibration_timer = HAL_GetTick() + 1000;
|
|
|
|
|
powerground_calibration_stage = 3;
|
|
|
|
|
PWM_powerground_control(0);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 3:
|
|
|
|
|
if (powerground_calibration_timer < HAL_GetTick()){
|
|
|
|
|
powerground_calibration_stage = 4;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sm_handle_ams_in(const uint8_t *data){
|
|
|
|
|
CAN_timer = HAL_GetTick() + CAN_TIMEOUT;
|
|
|
|
|
switch (data[0]) {
|
|
|
|
|
case 0x00:
|
|
|
|
|
if (state.current_state != STATE_INACTIVE){
|
|
|
|
|
state.target_state = STATE_DISCHARGE;
|
|
|
|
|
PWM_powerground_control(255);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0x01:
|
|
|
|
|
if (state.target_state == STATE_INACTIVE || state.target_state == STATE_DISCHARGE){
|
|
|
|
|
state.target_state = STATE_PRECHARGE;
|
|
|
|
|
PWM_powerground_control(0);
|
|
|
|
|
} else if (state.target_state == STATE_ACTIVE){
|
|
|
|
|
state.target_state = STATE_READY;
|
|
|
|
|
PWM_powerground_control(0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0x02:
|
|
|
|
|
if (state.current_state == STATE_READY || state.current_state == STATE_ACTIVE){
|
|
|
|
|
PWM_powerground_control(data[1]);
|
|
|
|
|
state.target_state = STATE_ACTIVE; // READY -> ACTIVE
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
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
|
|
|
|
|
state.current_state = STATE_DISCHARGE;
|
|
|
|
|
state.target_state = STATE_ERROR;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sm_set_error(ErrorKind error_kind, bool is_errored){}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
bool sm_is_errored(){
|
|
|
|
|
return state.error_type.current_error == 1 || state.error_type.current_sensor_missing == 1 || //state.error_type.eeprom_error == 1 ||
|
|
|
|
|
state.error_type.state_transition_fail == 1 || state.error_type.temperature_error == 1 || state.error_type.voltage_error == 1 ||
|
|
|
|
|
state.error_type.voltage_missing == 1 || state.error_type.bms_fault == 1 || state.error_type.bms_timeout == 1;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#warning TODO: add error checking for everything here
|
|
|
|
|
void sm_check_errors(){
|
|
|
|
|
state.error_type.temperature_error = (error_data.error_sources & (1 << 0) || error_data.error_sources & (1 << 1) || error_data.error_sources & (1 << 4)) ? 1 : 0;
|
|
|
|
|
state.error_type.voltage_error = (error_data.error_sources & (1 << 2)|| error_data.error_sources & (1 << 3)|| error_data.error_sources & (1 << 5) || RELAY_BAT_SIDE_VOLTAGE < 30000) ? 1 : 0;
|
|
|
|
|
state.error_type.bms_timeout = (error_data.error_sources & (1 << 7)) ? 1 : 0;
|
|
|
|
|
state.error_type.bms_fault = (error_data.error_sources & (1 << 8) || error_data.error_sources & (1 << 10) || error_data.error_sources & (1 << 9)) ? 1 : 0;
|
|
|
|
|
//SEK_EEPROM_ERR: state.error_type.eeprom_error = 1;
|
|
|
|
|
//state.error_type.current_error = (powerground_status > 10 && CURRENT_MEASUREMENT < 500) ? 1 : 0;
|
|
|
|
|
state.error_type.current_sensor_missing = (!CURRENT_MEASUREMENT_ON) ? 1 : 0;
|
|
|
|
|
state.error_type.voltage_missing = (RELAY_BAT_SIDE_VOLTAGE < 1000) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( state.error_type.current_error == 1 || state.error_type.current_sensor_missing == 1 || //state.error_type.eeprom_error == 1 ||
|
|
|
|
|
state.error_type.state_transition_fail == 1 || state.error_type.temperature_error == 1 || state.error_type.voltage_error == 1 ||
|
|
|
|
|
state.error_type.voltage_missing == 1 || state.error_type.bms_fault == 1 || state.error_type.bms_timeout == 1){
|
|
|
|
|
if (state.current_state != STATE_INACTIVE && state.current_state != STATE_ERROR)
|
|
|
|
|
state.current_state = STATE_DISCHARGE;
|
|
|
|
|
state.target_state = STATE_ERROR;
|
|
|
|
|
PWM_powerground_control(255);
|
|
|
|
|
} else if (state.current_state == STATE_ERROR){
|
|
|
|
|
state.target_state = STATE_INACTIVE;
|
|
|
|
|
}
|
|
|
|
|
sm_error_source();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int16_t sm_return_cell_temperature(int id){ return tmp1075_temps[id]; }
|
|
|
|
|
|
|
|
|
|
int16_t sm_return_cell_voltage(int id){ return module.cellVoltages[id]; }
|
|
|
|
|
@ -407,17 +413,4 @@ void sm_test_cycle_states(){
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state.target_state = state.current_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sm_error_source(){
|
|
|
|
|
state.error_source = 0;
|
|
|
|
|
state.error_source |= (state.error_type.bms_timeout << 0);
|
|
|
|
|
state.error_source |= (state.error_type.bms_fault << 1);
|
|
|
|
|
state.error_source |= (state.error_type.temperature_error << 2);
|
|
|
|
|
state.error_source |= (state.error_type.current_error << 3);
|
|
|
|
|
|
|
|
|
|
state.error_source |= (state.error_type.current_sensor_missing << 4);
|
|
|
|
|
state.error_source |= (state.error_type.voltage_error << 5);
|
|
|
|
|
state.error_source |= (state.error_type.voltage_missing << 6);
|
|
|
|
|
state.error_source |= (state.error_type.state_transition_fail << 7);
|
|
|
|
|
}
|