Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ced8dd0
Initial changeover, totally untested
dchansen06 May 12, 2026
02521cc
Bring back HOOTL testing
dchansen06 May 12, 2026
44484e6
Set bspd sense in test to new good value
kzwicker May 13, 2026
ebe95dd
Fix analog data and inverter command frequency
dchansen06 May 13, 2026
2e36676
Sanity set initial statics to 0
dchansen06 May 13, 2026
619f576
Fix can dlc size
dchansen06 May 13, 2026
d8bfa01
Revise dti send can
dchansen06 May 13, 2026
b018016
Scale torque request respectfully
dchansen06 May 13, 2026
5d63c9d
Random tested values for throttle
dchansen06 May 13, 2026
0b7fc64
Automatic Clang-Format: Standardized formatting automatically
github-actions[bot] May 13, 2026
de64947
Switch to custom bytes to CAN DLC function for hootl test
dchansen06 May 13, 2026
3a1c390
Allegedly fix rtd button press latch
dchansen06 May 13, 2026
a2a6bee
Read and reset the variable set by the button read interrupt exactly …
kzwicker May 13, 2026
4f9ad78
Explicitly send do not torque
dchansen06 May 13, 2026
55ea9e2
Driving check?
dchansen06 May 13, 2026
42392ff
ADC alpha is useless if not rate limited
dchansen06 May 13, 2026
3e558c0
Remove sketchy APPS debug logic
dchansen06 May 14, 2026
3e01c85
Migrate analog data message out of state ticks to be something always…
dchansen06 May 14, 2026
daabfdf
Merge branch 'main' into HV-test
dchansen06 May 14, 2026
483657d
Merge branch 'main' into HV-test
dchansen06 May 14, 2026
32f2d30
added a scary FIXME for the code causing HOOTLTest failures
SlowThomas May 15, 2026
524477e
No more DWT
dchansen06 May 15, 2026
0b52ba7
Set clock div 4, oversample 64, bitshift right 6
dchansen06 May 15, 2026
76afff7
Cycle adc init values into real values while in hot loop waiting for …
dchansen06 May 15, 2026
928b3dc
Grab 20V level from ACU
kzwicker May 18, 2026
383b275
consolidate comparisons of ams bms bspd sense lines to one function
kzwicker May 18, 2026
f26a0e4
Unfuck the bspd (does not depend on GLV 20V)
kzwicker May 18, 2026
b1715d3
give 20v line a default value so something sensible happens on startup
kzwicker May 19, 2026
0656b50
is good
kzwicker May 19, 2026
330bbed
double unfuck the bspd
kzwicker May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ECU/Application/Inc/CANutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
void ECU_CAN_Send(GRCAN_BUS_ID bus, GRCAN_NODE_ID destNode, GRCAN_MSG_ID messageID, void *data, uint32_t size);
void ECU_CAN_Send_DTI(GRCAN_CUSTOM_ID msgID, void *data, uint32_t size);
void SendECUStateDataOverCAN(ECU_StateData *stateData);
void SendECUAnalogDataOverCAN(ECU_StateData *stateData);

#endif
7 changes: 4 additions & 3 deletions ECU/Application/Inc/StateData.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ typedef volatile struct ECU_StateData {

float min_amk_heat_cap_throttle_percent;
float ts_voltage;
float glv_voltage_20V;
float max_cell_temp_c; /** Temperature of hottest cell, celsius */

float vehicle_speed_mph; /** Vehicle speed, MPH */
Expand All @@ -62,9 +63,7 @@ typedef volatile struct ECU_StateData {
float rr_wheel_rpm; /** RRv wheel, RPM */
float rl_wheel_rpm; /** RL wheel, RPM */

// 0.5V when things go to shit (X_OK low) (BAD)
// 3V when things almost poggers (X_OK high but SDC not reset) (BAD)
// 2.4V when things are actually poggers (X_OK high and SDC is not triggered)

float ams_sense;
float imd_sense;
float bspd_sense;
Expand All @@ -87,7 +86,9 @@ typedef volatile struct ECU_StateData {
uint8_t glv_soc;
uint8_t acu_error_warning_bits;
uint8_t inverter_fault_map;
bool ts_active_button_press_interrupt;
bool ts_active_button_pressed;
bool rtd_button_press_interrupt;
bool rtd_button_pressed;
bool ir_plus;
bool ir_minus;
Expand Down
19 changes: 15 additions & 4 deletions ECU/Application/Inc/StateUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ uint32_t MillisecondsSinceBoot(void);
#define BRAKE_F_MAX 4095 // TODO: need to be determined FIXME: Rename better
#define BRAKE_R_MIN 0 // TODO: need to be determined FIXME: Rename better
#define BRAKE_R_MAX 4095 // TODO: need to be determined FIXME: Rename better
#define THROTTLE_MIN_1 0 // TODO: need to be determined
#define THROTTLE_MAX_1 4095 // TODO: need to be determined
#define THROTTLE_MIN_2 0 // TODO: need to be determined
#define THROTTLE_MAX_2 4095 // TODO: need to be determined
#define THROTTLE_MIN_1 306 // TODO: need to be determined
#define THROTTLE_MAX_1 3704 // TODO: need to be determined
#define THROTTLE_MIN_2 336 // TODO: need to be determined
#define THROTTLE_MAX_2 3794 // TODO: need to be determined
#define BSE_MAX 4096.0f
#define BSE_DEADZONE 1.2f
#define MAX_BSE_FAILURE_TIME 100
Expand All @@ -42,8 +42,17 @@ uint32_t MillisecondsSinceBoot(void);
#define RATE_LIMIT_100_HZ(x, y) (x - y > 10)
#define RATE_LIMIT_10_HZ(x, y) (x - y > 100)

typedef enum {
SDC_OK,
SDC_ONGOING_FAILURE,
SDC_LATCHED_FAILURE
} SDC_Level;

// Checks stateData for critical errors
bool CriticalError(volatile const ECU_StateData *stateData);
SDC_Level bmsLevel(volatile const ECU_StateData *stateData);
SDC_Level imdLevel(volatile const ECU_StateData *stateData);
SDC_Level bspdLevel(volatile const ECU_StateData *stateData);
bool bmsFailure(volatile const ECU_StateData *stateData);
bool imdFailure(volatile const ECU_StateData *stateData);
bool bspdFailure(volatile const ECU_StateData *stateData);
Expand All @@ -54,5 +63,7 @@ float CalcAccPedalTravel(volatile const ECU_StateData *stateData);
bool APPS_Plausible(volatile const ECU_StateData *stateData);
bool BSE_Plausible(volatile const ECU_StateData *stateData);
bool vehicle_is_moving(volatile const ECU_StateData *stateData);
/* Disable inverter for both DTI and Custom */
void disable_inverter(void);

#endif
11 changes: 5 additions & 6 deletions ECU/Application/Src/CANdler.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GRCAN_BUS_ID bus_id, GRCA
state_data->ir_minus = GETBIT(acu_status_2->precharge_latch_flags, 4);
state_data->ir_plus = GETBIT(acu_status_2->precharge_latch_flags, 5);
state_data->acu_software_latch = GETBIT(acu_status_2->precharge_latch_flags, 6);
state_data->glv_voltage_20V = acu_status_2->_20v_voltage * 0.1f;
break;

case GRCAN_INVERTER_STATUS_1:
Expand Down Expand Up @@ -110,17 +111,15 @@ void ECU_CAN_MessageHandler(ECU_StateData *state_data, GRCAN_BUS_ID bus_id, GRCA

// LET IT BE KNOWN: these things are LSB FIRST, TODO: I'll get it right later
if (state_data->ecu_state == GR_GLV_ON) {
state_data->ts_active_button_pressed = dash_data->button_flags & 1;
state_data->ts_active_button_press_interrupt = dash_data->button_flags & 1;
} else {
state_data->ts_active_button_pressed = (dash_data->button_flags >> 2) & 1;
state_data->ts_active_button_press_interrupt = (dash_data->button_flags >> 2) & 1;
}

if (state_data->ecu_state == GR_PRECHARGE_COMPLETE) {
state_data->rtd_button_pressed = (dash_data->button_flags >> 1) & 1;
state_data->rtd_button_press_interrupt = (dash_data->button_flags >> 1) & 1;
} else if (state_data->ecu_state == GR_DRIVE_ACTIVE) {
state_data->rtd_button_pressed = (dash_data->button_flags >> 3) & 1;
} else {
state_data->rtd_button_pressed = false;
state_data->rtd_button_press_interrupt = (dash_data->button_flags >> 3) & 1;
}

break;
Expand Down
35 changes: 28 additions & 7 deletions ECU/Application/Src/CANutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void ECU_CAN_Send(GRCAN_BUS_ID bus, GRCAN_NODE_ID destNode, GRCAN_MSG_ID message
.IdType = FDCAN_EXTENDED_ID,
.TxFrameType = FDCAN_DATA_FRAME,
.ErrorStateIndicator = FDCAN_ESI_ACTIVE,
.DataLength = size,
.DataLength = BytesToCANDLC(size),
.BitRateSwitch = FDCAN_BRS_OFF,
.TxEventFifoControl = FDCAN_NO_TX_EVENTS,
.MessageMarker = 0,
Expand Down Expand Up @@ -78,17 +78,20 @@ void ECU_CAN_Send_DTI(GRCAN_CUSTOM_ID msgID, void *data, uint32_t size)
TxHeader.Identifier = msgID;
TxHeader.DataLength = size;

TxHeader.IdType = FDCAN_EXTENDED_ID;

TxHeader.FDFormat = FDCAN_CLASSIC_CAN;

FDCANTxMessage msg = {0};
msg.tx_header = TxHeader;

for (uint32_t i = 0; i < size; i++) {
msg.data[size - i - 1] = ((uint8_t *)data)[i];
uint8_t temp;
for (uint16_t i = 0; i < size / 2; ++i) {
temp = ((uint8_t *)data)[i];
((uint8_t *)data)[i] = ((uint8_t *)data)[size - i - 1];
((uint8_t *)data)[size - i - 1] = temp;
}

memcpy(&(msg.data), data, size);

// can_send(primary_can, &msg);
can_enqueue(stateLump.primary_can, &msg);
}
Expand Down Expand Up @@ -116,9 +119,27 @@ void SendECUStateDataOverCAN(ECU_StateData *stateData)
.RRWheelRPM = (uint16_t)(stateData->rr_wheel_rpm * 10 + 32768),
.RLWheelRPM = (uint16_t)(stateData->rl_wheel_rpm * 10 + 32768)};

// LOGOMATIC("Sending ECU State Data over CAN\n");

ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_ALL, GRCAN_ECU_STATUS_1, (void *)&messages.ECUStatusMsgOne, sizeof(messages.ECUStatusMsgOne));
ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_ALL, GRCAN_ECU_STATUS_2, (void *)&messages.ECUStatusMsgTwo, sizeof(messages.ECUStatusMsgTwo));
ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_ALL, GRCAN_ECU_STATUS_3, (void *)&messages.ECUStatusMsgThree, sizeof(messages.ECUStatusMsgThree));
}

void SendECUAnalogDataOverCAN(ECU_StateData *stateData)
{
uint32_t millis_since_boot = MillisecondsSinceBoot();

static uint32_t last_can_tcm_request_millis = 0;

if (millis_since_boot - last_can_tcm_request_millis > 100) {
GRCAN_ECU_ANALOG_DATA_MSG message = {.bspd_signal = stateData->bspd_signal,
.bse_signal = stateData->bse_signal,
.apps_1_signal = stateData->APPS1_Signal,
.apps_2_signal = stateData->APPS2_Signal,
.brakeline_f_signal = stateData->Brake_F_Signal,
.brakeline_r_signal = stateData->Brake_R_Signal,
.steering_angle_signal = stateData->steering_angle_signal,
.aux_signal = stateData->aux_signal};
ECU_CAN_Send(GRCAN_BUS_DATA, GRCAN_TCM, GRCAN_ECU_ANALOG_DATA, &message, sizeof(message));
last_can_tcm_request_millis = millis_since_boot;
}
}
73 changes: 33 additions & 40 deletions ECU/Application/Src/StateTicks.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @remark Intentionally not a globally accessible variable
*/

ECU_StateData stateLump = {.ecu_state = GR_GLV_ON, .acu_software_latch = 1};
ECU_StateData stateLump = {.ecu_state = GR_GLV_ON, .acu_software_latch = 1, .glv_voltage_20V = 20.0f};

static uint32_t millis_since_boot;
void ECU_State_Tick(void)
Expand Down Expand Up @@ -53,13 +53,30 @@ void ECU_State_Tick(void)
// stateLump.bms_light &= (bmsFailure(&stateLump));
// stateLump.imd_light &= (imdFailure(&stateLump));

stateLump.bms_light = (stateLump.ams_sense <= 0.5f) || (stateLump.bms_light && bmsFailure(&stateLump));
stateLump.imd_light = (stateLump.ams_sense <= 0.5f) || (stateLump.imd_light && imdFailure(&stateLump));
SDC_Level bms_level = bmsLevel(&stateLump);
SDC_Level imd_level = imdLevel(&stateLump);

stateLump.bms_light = (bms_level == SDC_ONGOING_FAILURE) || (stateLump.bms_light && bmsFailure(&stateLump));
stateLump.imd_light = (imd_level == SDC_ONGOING_FAILURE) || (stateLump.imd_light && imdFailure(&stateLump));

stateLump.tssi_fault = stateLump.bms_light || stateLump.imd_light;

// bmsFailure(&stateLump) || imdFailure(&stateLump);

if (stateLump.ts_active_button_press_interrupt) {
stateLump.ts_active_button_press_interrupt = false;
stateLump.ts_active_button_pressed = true;
} else {
stateLump.ts_active_button_pressed = false;
}

if (stateLump.rtd_button_press_interrupt) {
stateLump.rtd_button_press_interrupt = false;
stateLump.rtd_button_pressed = true;
} else {
stateLump.rtd_button_pressed = false;
}

switch (stateLump.ecu_state) {
case GR_GLV_OFF:
ECU_GLV_Off(&stateLump);
Expand Down Expand Up @@ -89,13 +106,16 @@ void ECU_State_Tick(void)

void ECU_GLV_Off(ECU_StateData *stateData)
{
disable_inverter();
UNUSED(stateData);
LOGOMATIC("ECU_GLV_Off state reached... this should never happen!\n");
// TODO ERROR --> GLV_OFF should never be reached
}

void ECU_GLV_On(ECU_StateData *stateData)
{
disable_inverter();

if (stateData->ts_voltage >= SAFE_VOLTAGE_LIMIT) {
LOGOMATIC("Error: TS Voltage >= %d!\n", SAFE_VOLTAGE_LIMIT);
ECU_Transition_To_Tractive_System_Discharge(stateData);
Expand All @@ -106,7 +126,6 @@ void ECU_GLV_On(ECU_StateData *stateData)
if (stateData->ts_active_button_pressed /* && stateData->ir_plus*/) { // TODO: Talk to Owen if this is correct for precharge start confirmation
LOGOMATIC("GLV ON to PRECHARGE START!\n");
ECU_Transition_To_Precharge_Engaged(stateData);
stateData->ts_active_button_pressed = false;
return;
}
}
Expand All @@ -126,6 +145,8 @@ void ECU_Transition_To_Precharge_Engaged(ECU_StateData *stateData)

void ECU_Precharge_Engaged(ECU_StateData *stateData)
{
disable_inverter();

if (stateData->ir_plus) {
stateData->ecu_state = GR_PRECHARGE_COMPLETE;
LOGOMATIC("PRECHARGE ENGAGED to PRECHARGE COMPLETE!\n");
Expand All @@ -142,18 +163,18 @@ void ECU_Precharge_Engaged(ECU_StateData *stateData)
LOGOMATIC("ERROR: ts_active PRESSED! PRECHARGE ENGAGED to TS DISCHARGE START!\n");
ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_Debugger, GRCAN_DEBUG_2_0, "TS-P-ITR", 8);
ECU_Transition_To_Tractive_System_Discharge(stateData);
stateData->ts_active_button_pressed = false;
return;
}
}

// TODO: change for CAN button messenging
void ECU_Precharge_Complete(ECU_StateData *stateData)
{
disable_inverter();

if (stateData->ts_active_button_pressed) {
LOGOMATIC("TS Active Toggled Off. Discharging Tractive System.\n");
ECU_Transition_To_Tractive_System_Discharge(stateData);
stateData->ts_active_button_pressed = false;
return;
}
if (CriticalError(stateData)) {
Expand All @@ -166,19 +187,8 @@ void ECU_Precharge_Complete(ECU_StateData *stateData)
if (PressingBrake(stateData) && stateData->rtd_button_pressed) {
GRCAN_INVERTER_CONFIG_MSG inverter_message = {.max_ac_current = 0xFFFF, .max_dc_current = 0xFFFF, .absolute_max_rpm_limit = 0xFFFF, .motor_direction = 0};
ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_GR_Inverter, GRCAN_INVERTER_CONFIG, &inverter_message, sizeof(inverter_message));
GRCAN_ECU_ANALOG_DATA_MSG pedals_message = {.bspd_signal = stateData->bspd_signal,
.bse_signal = stateData->bse_signal,
.apps_1_signal = stateData->APPS1_Signal,
.apps_2_signal = stateData->APPS2_Signal,
.brakeline_f_signal = stateData->Brake_F_Signal,
.brakeline_r_signal = stateData->Brake_R_Signal,
.steering_angle_signal = stateData->steering_angle_signal,
.aux_signal = stateData->aux_signal};
ECU_CAN_Send(GRCAN_BUS_DATA, GRCAN_TCM, GRCAN_ECU_ANALOG_DATA, &pedals_message, sizeof(pedals_message));
LOGOMATIC("PRECHARGE COMPLETE to DRIVE START/ACTIVE!\n");
ECU_Transition_To_Drive_Active(stateData);
stateData->rtd_button_pressed = false;
return;
}
}

Expand All @@ -202,7 +212,6 @@ void ECU_Drive_Active(ECU_StateData *stateData)
LOGOMATIC("Error: TS active button pressed in Drive Active state. Discharging Tractive System.\n");
ECU_Transition_To_Tractive_System_Discharge(stateData);
ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_Debugger, GRCAN_DEBUG_2_0, "DA-CritE", 8);
stateData->ts_active_button_pressed = false;
return;
}

Expand All @@ -218,7 +227,6 @@ void ECU_Drive_Active(ECU_StateData *stateData)
if (vehicle_is_moving(stateData)) {
LOGOMATIC("Warning: Vehicle is moving during state transition.\n");
}
stateData->rtd_button_pressed = false;
return;
}

Expand Down Expand Up @@ -247,32 +255,15 @@ void ECU_Drive_Active(ECU_StateData *stateData)
torque_request = 0;
}

static uint32_t last_can_inverter_request_millis;
static uint32_t last_can_inverter_request_millis = 0;
if (RATE_LIMIT_100_HZ(millis_since_boot, last_can_inverter_request_millis)) {
GRCAN_INVERTER_COMMAND_MSG message = {.set_ac_current = torque_request * 100 + 32768, .set_dc_current = torque_request * 100 + 32768, .drive_enable = 1, .rpm_limit = 0};
ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_GR_Inverter, GRCAN_INVERTER_COMMAND, &message, sizeof(message));
ECU_CAN_Send_DTI(DTI_CONTROL_12_CAN_ID, &message.drive_enable, 2);
ECU_CAN_Send_DTI(DTI_CONTROL_12_CAN_ID, &message.drive_enable, 1);
message.set_ac_current = torque_request * 10;
ECU_CAN_Send_DTI(DTI_CONTROL_1_CAN_ID, &message.set_ac_current, 2);
last_can_inverter_request_millis = millis_since_boot;
}

// placeholder for pedal data
// TODO: determine send time (15, 20 ms?)

static uint32_t last_can_tcm_request_millis;
if (RATE_LIMIT_100_HZ(millis_since_boot, last_can_tcm_request_millis)) {
GRCAN_ECU_ANALOG_DATA_MSG message = {.bspd_signal = stateData->bspd_signal,
.bse_signal = stateData->bse_signal,
.apps_1_signal = stateData->APPS1_Signal,
.apps_2_signal = stateData->APPS2_Signal,
.brakeline_f_signal = stateData->Brake_F_Signal,
.brakeline_r_signal = stateData->Brake_R_Signal,
.steering_angle_signal = stateData->steering_angle_signal,
.aux_signal = stateData->aux_signal};
UNUSED(message); // FIXME Eventually figure out what to do with this message here
// ECU_CAN_Send(GRCAN_BUS_DATA, GRCAN_TCM, GRCAN_ECU_ANALOG_DATA, &message, sizeof(message)); // FIXME
last_can_inverter_request_millis = millis_since_boot;
}
}

static uint32_t discharge_start_millis;
Expand All @@ -287,6 +278,8 @@ void ECU_Transition_To_Tractive_System_Discharge(ECU_StateData *stateData)

void ECU_Tractive_System_Discharge(ECU_StateData *stateData)
{
disable_inverter();

/*
Discharge the tractive system to below 60(SAFE_VOLTAGE_LIMIT) volts
*/
Expand All @@ -312,4 +305,4 @@ void ECU_Tractive_System_Discharge(ECU_StateData *stateData)
ECU_CAN_Send(GRCAN_BUS_PRIMARY, GRCAN_ACU, GRCAN_ACU_PRECHARGE, &message, sizeof(message));
last_discharge_request_millis = millis_since_boot;
}
} // init
}
Loading
Loading