diff --git a/firmware/can.cpp b/firmware/can.cpp index 872066b..fdff4bd 100644 --- a/firmware/can.cpp +++ b/firmware/can.cpp @@ -37,6 +37,11 @@ static void SendAck() canTransmitTimeout(&CAND1, CAN_ANY_MAILBOX, &frame, TIME_INFINITE); } +// Start in Unknown state. If no CAN message is ever received, we operate +// on internal battery sense etc. +static HeaterAllow heaterAllow = HeaterAllow::Unknown; +static float remoteBatteryVoltage = 0; + static THD_WORKING_AREA(waCanRxThread, 256); void CanRxThread(void*) { @@ -60,13 +65,27 @@ void CanRxThread(void*) if (frame.DLC == 2 && frame.EID == WB_MGS_ECU_STATUS) { // This is status from ECU - battery voltage and heater enable signal + // data1 contains heater enable bit + if ((frame.data8[1] & 0x1) == 0x1) + { + heaterAllow = HeaterAllow::Allowed; + } + else + { + heaterAllow = HeaterAllow::NotAllowed; + } + // data0 contains battery voltage in tenths of a volt float vbatt = frame.data8[0] * 0.1f; - SetBatteryVoltage(vbatt); - - // data1 contains heater enable bit - bool heaterAllowed = (frame.data8[1] & 0x1) == 0x1; - SetHeaterAllowed(heaterAllowed); + if (vbatt < 5) + { + // provided vbatt is bogus, default to 14v nominal + remoteBatteryVoltage = 14; + } + else + { + remoteBatteryVoltage = vbatt; + } } // If it's a bootloader entry request, reboot to the bootloader! else if (frame.DLC == 0 && frame.EID == WB_BL_ENTER) @@ -90,6 +109,16 @@ void CanRxThread(void*) } } +HeaterAllow GetHeaterAllowed() +{ + return heaterAllow; +} + +float GetRemoteBatteryVoltage() +{ + return remoteBatteryVoltage; +} + void InitCan() { configuration = GetConfiguration(); diff --git a/firmware/can.h b/firmware/can.h index 25bd081..c0d67a5 100644 --- a/firmware/can.h +++ b/firmware/can.h @@ -5,3 +5,13 @@ void InitCan(); void SendCanData(float lambda, uint16_t measuredResistance); void SendRusefiFormat(uint8_t idx); + +enum class HeaterAllow { + Unknown, + Allowed, + NotAllowed, +}; + +HeaterAllow GetHeaterAllowed(); + +float GetRemoteBatteryVoltage(); diff --git a/firmware/heater_control.cpp b/firmware/heater_control.cpp index 57a7d19..5be58f4 100644 --- a/firmware/heater_control.cpp +++ b/firmware/heater_control.cpp @@ -8,6 +8,7 @@ #include "pwm.h" #include "sampling.h" #include "pid.h" +#include "can.h" using namespace wbo; @@ -25,10 +26,12 @@ enum class HeaterState constexpr int preheatTimeCounter = HEATER_PREHEAT_TIME / HEATER_CONTROL_PERIOD; static int timeCounter = preheatTimeCounter; static float rampVoltage = 0; -static bool heaterAllowed = false; -static HeaterState GetNextState(HeaterState state, float sensorEsr) +static HeaterState GetNextState(HeaterState state, HeaterAllow heaterAllowState, float batteryVoltage, float sensorEsr) { + // TODO: smarter state machine to use internal vbatt when CAN not connected + bool heaterAllowed = heaterAllowState == HeaterAllow::Allowed; + if (!heaterAllowed) { // ECU hasn't allowed preheat yet, reset timer, and force preheat state @@ -130,8 +133,6 @@ static float GetVoltageForState(HeaterState state, float heaterEsr) static HeaterState state = HeaterState::Preheat; -// Nominal battery voltage (running engine) is 14v -static float batteryVoltage = 14; static THD_WORKING_AREA(waHeaterThread, 256); static void HeaterThread(void*) @@ -145,8 +146,16 @@ static void HeaterThread(void*) // Read sensor state float heaterEsr = GetSensorInternalResistance(); + auto heaterAllowState = GetHeaterAllowed(); + + // If we haven't heard from rusEFI, use the internally sensed + // battery voltage instead of voltage over CAN. + float batteryVoltage = heaterAllowState == HeaterAllow::Unknown + ? GetInternalBatteryVoltage() + : GetRemoteBatteryVoltage(); + // Run the state machine - state = GetNextState(state, heaterEsr); + state = GetNextState(state, heaterAllowState, batteryVoltage, heaterEsr); float heaterVoltage = GetVoltageForState(state, heaterEsr); // Limit to 11 volts @@ -187,24 +196,6 @@ bool IsRunningClosedLoop() return state == HeaterState::ClosedLoop; } -void SetBatteryVoltage(float vbatt) -{ - if (vbatt < 5) - { - // provided vbatt is bogus, default to 14v nominal - batteryVoltage = 14; - } - else - { - batteryVoltage = vbatt; - } -} - -void SetHeaterAllowed(bool allowed) -{ - heaterAllowed = allowed; -} - float GetHeaterDuty() { return heaterPwm.GetLastDuty(); diff --git a/firmware/heater_control.h b/firmware/heater_control.h index 7f4e680..b150095 100644 --- a/firmware/heater_control.h +++ b/firmware/heater_control.h @@ -4,6 +4,4 @@ void StartHeaterControl(); bool IsRunningClosedLoop(); -void SetBatteryVoltage(float vbatt); -void SetHeaterAllowed(bool allowed); float GetHeaterDuty();