tests for heater output

This commit is contained in:
Matthew Kennedy 2023-11-13 13:56:03 -08:00
parent 5c128f4034
commit 7f5b7097e3
3 changed files with 55 additions and 13 deletions

View File

@ -31,7 +31,7 @@ HeaterState HeaterControllerBase::GetHeaterState() const
return heaterState; return heaterState;
} }
HeaterState HeaterControllerBase::GetNextState(HeaterAllow heaterAllowState, float batteryVoltage, float sensorTemp) HeaterState HeaterControllerBase::GetNextState(HeaterState currentState, HeaterAllow heaterAllowState, float batteryVoltage, float sensorTemp)
{ {
bool heaterAllowed = heaterAllowState == HeaterAllow::Allowed; bool heaterAllowed = heaterAllowState == HeaterAllow::Allowed;
@ -62,7 +62,7 @@ HeaterState HeaterControllerBase::GetNextState(HeaterAllow heaterAllowState, flo
float closedLoopTemp = m_targetTempC - 50; float closedLoopTemp = m_targetTempC - 50;
float underheatTemp = m_targetTempC - 100; float underheatTemp = m_targetTempC - 100;
switch (heaterState) switch (currentState)
{ {
case HeaterState::Preheat: case HeaterState::Preheat:
timeCounter--; timeCounter--;
@ -119,9 +119,9 @@ HeaterState HeaterControllerBase::GetNextState(HeaterAllow heaterAllowState, flo
return heaterState; return heaterState;
} }
float HeaterControllerBase::GetVoltageForState(float heaterEsr) float HeaterControllerBase::GetVoltageForState(HeaterState state, float sensorEsr)
{ {
switch (heaterState) switch (state)
{ {
case HeaterState::Preheat: case HeaterState::Preheat:
// Max allowed during condensation phase (preheat) is 2v // Max allowed during condensation phase (preheat) is 2v
@ -141,7 +141,7 @@ float HeaterControllerBase::GetVoltageForState(float heaterEsr)
// Negated because lower resistance -> hotter // Negated because lower resistance -> hotter
// TODO: heater PID should operate on temperature, not ESR // TODO: heater PID should operate on temperature, not ESR
return 7.5f - heaterPid.GetOutput(m_targetEsr, heaterEsr); return 7.5f - heaterPid.GetOutput(m_targetEsr, sensorEsr);
case HeaterState::Stopped: case HeaterState::Stopped:
case HeaterState::NoHeaterSupply: case HeaterState::NoHeaterSupply:
// Something has gone wrong, turn off the heater. // Something has gone wrong, turn off the heater.
@ -155,7 +155,7 @@ float HeaterControllerBase::GetVoltageForState(float heaterEsr)
void HeaterControllerBase::Update(const ISampler& sampler, HeaterAllow heaterAllowState) void HeaterControllerBase::Update(const ISampler& sampler, HeaterAllow heaterAllowState)
{ {
// Read sensor state // Read sensor state
float heaterEsr = sampler.GetSensorInternalResistance(); float sensorEsr = sampler.GetSensorInternalResistance();
float sensorTemperature = sampler.GetSensorTemperature(); float sensorTemperature = sampler.GetSensorTemperature();
// If we haven't heard from the ECU, use the internally sensed // If we haven't heard from the ECU, use the internally sensed
@ -165,8 +165,8 @@ void HeaterControllerBase::Update(const ISampler& sampler, HeaterAllow heaterAll
: GetRemoteBatteryVoltage(); : GetRemoteBatteryVoltage();
// Run the state machine // Run the state machine
heaterState = GetNextState(heaterAllowState, batteryVoltage, sensorTemperature); heaterState = GetNextState(heaterState, heaterAllowState, batteryVoltage, sensorTemperature);
float heaterVoltage = GetVoltageForState(heaterEsr); float heaterVoltage = GetVoltageForState(heaterState, sensorEsr);
// Limit to 11 volts // Limit to 11 volts
if (heaterVoltage > 11) { if (heaterVoltage > 11) {

View File

@ -39,9 +39,8 @@ public:
virtual void SetDuty(float duty) const = 0; virtual void SetDuty(float duty) const = 0;
protected: HeaterState GetNextState(HeaterState currentState, HeaterAllow haeterAllowState, float batteryVoltage, float sensorTemp);
HeaterState GetNextState(HeaterAllow haeterAllowState, float batteryVoltage, float sensorTemp); float GetVoltageForState(HeaterState state, float sensorEsr);
float GetVoltageForState(float heaterEsr);
private: private:
Pid heaterPid = Pid heaterPid =

View File

@ -3,13 +3,56 @@
#include "heater_control.h" #include "heater_control.h"
struct MockHeater : public HeaterControllerBase { struct MockHeater : public HeaterControllerBase
{
MockHeater() : HeaterControllerBase(0) { } MockHeater() : HeaterControllerBase(0) { }
MOCK_METHOD(void, SetDuty, (float), (const, override)); MOCK_METHOD(void, SetDuty, (float), (const, override));
}; };
TEST(Heater, Basic) TEST(HeaterStateOutput, Preheat)
{
MockHeater dut;
// Shouldn't depend upon sensor ESR
EXPECT_EQ(1.5f, dut.GetVoltageForState(HeaterState::Preheat, 0));
EXPECT_EQ(1.5f, dut.GetVoltageForState(HeaterState::Preheat, 300));
EXPECT_EQ(1.5f, dut.GetVoltageForState(HeaterState::Preheat, 1000));
}
TEST(HeaterStateOutput, WarmupRamp)
{
MockHeater dut;
EXPECT_EQ(1.5f, dut.GetVoltageForState(HeaterState::Preheat, 0));
EXPECT_EQ(1.5f, dut.GetVoltageForState(HeaterState::Preheat, 300));
EXPECT_EQ(1.5f, dut.GetVoltageForState(HeaterState::Preheat, 1000));
}
TEST(HeaterStateOutput, ClosedLoop)
{
MockHeater dut;
dut.Configure(780, 300);
// At target -> zero output but with 7.5v offset
EXPECT_EQ(dut.GetVoltageForState(HeaterState::ClosedLoop, 300), 7.5f);
// Below target -> more voltage
EXPECT_GT(dut.GetVoltageForState(HeaterState::ClosedLoop, 400), 7.5f);
// Above target -> less voltage
EXPECT_LT(dut.GetVoltageForState(HeaterState::ClosedLoop, 200), 7.5f);
}
TEST(HeaterStateOutput, Cases)
{
MockHeater dut;
EXPECT_EQ(0, dut.GetVoltageForState(HeaterState::Stopped, 0));
EXPECT_EQ(0, dut.GetVoltageForState(HeaterState::NoHeaterSupply, 0));
}
TEST(HeaterStateMachine, x)
{ {
MockHeater dut; MockHeater dut;
} }