fan control is engine module (#5585)

* fan is engine module

* mockable AC

* mockable AC

* mock AC controller in fan test

* constexpr fan livedata

* isPtr

Co-authored-by: Matthew Kennedy <matthewkennedy@outlook.com>
This commit is contained in:
rusefillc 2023-09-26 07:12:11 -04:00 committed by GitHub
parent 798abfc8e1
commit be35a5eb23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 49 additions and 37 deletions

View File

@ -78,8 +78,8 @@ const fuel_computer_s* getLiveData(size_t) {
template<>
const fan_control_s* getLiveData(size_t idx) {
switch (idx) {
case 0: return &engine->fan1;
case 1: return &engine->fan2;
case 0: return &engine->module<FanControl1>().unmock();
case 1: return &engine->module<FanControl2>().unmock();
default: return nullptr;
}
}

View File

@ -3,11 +3,13 @@
#include "ac_control_generated.h"
#include <rusefi/timer.h>
class AcController final : public ac_control_s, public EngineModule {
class AcController : public ac_control_s, public EngineModule {
public:
using interface_t = AcController;
void onSlowCallback() override;
bool isAcEnabled() const;
virtual bool isAcEnabled() const;
private:
bool getAcState();

View File

@ -44,21 +44,18 @@ bool FanController::getState(bool acActive, bool lastState) {
}
}
void FanController::update(bool acActive) {
auto& pin = getPin();
bool result = getState(acActive, pin.getLogicValue());
pin.setValue(result);
}
void updateFans(bool acActive) {
void FanController::onSlowCallback() {
#if EFI_PROD_CODE
if (isRunningBenchTest()) {
return; // let's not mess with bench testing
}
#endif
engine->fan1.update(acActive);
engine->fan2.update(acActive);
bool acActive = engine->module<AcController>()->isAcEnabled();
auto& pin = getPin();
bool result = getState(acActive, pin.getLogicValue());
pin.setValue(result);
}

View File

@ -2,8 +2,8 @@
#include "fan_control_generated.h"
struct FanController : public fan_control_s {
void update(bool acActive);
struct FanController : public EngineModule, public fan_control_s {
void onSlowCallback() override;
private:
bool getState(bool acActive, bool lastState);
@ -16,8 +16,6 @@ protected:
virtual bool disableWhenStopped() = 0;
};
void updateFans(bool acActive);
struct FanControl1 : public FanController {
OutputPin& getPin() {
return enginePins.fanRelay;

View File

@ -158,8 +158,6 @@ void Engine::periodicSlowCallback() {
engine->engineModules.apply_all([](auto & m) { m.onSlowCallback(); });
updateFans(module<AcController>().unmock().isAcEnabled());
#if (BOARD_TLE8888_COUNT > 0)
tle8888startup();
#endif

View File

@ -145,7 +145,9 @@ public:
FuelPumpController,
MainRelayController,
IgnitionController,
AcController,
Mockable<AcController>,
FanControl1,
FanControl2,
PrimeController,
DfcoController,
Mockable<WallFuelController>,
@ -198,9 +200,6 @@ public:
IgnitionState ignitionState;
void resetLua();
FanControl1 fan1;
FanControl2 fan2;
Timer startStopStateLastPush;
#if EFI_SHAFT_POSITION_INPUT

View File

@ -88,6 +88,8 @@ Usages:
java: FanControl.java
folder: controllers/actuators
output_name: [ "fan1", "fan2" ]
constexpr: "___engine.module<FanControl1>()"
isPtr: true
- name: fuel_pump_control
cppFileName: fuel_pump

View File

@ -2,8 +2,22 @@
#include "fan_control.h"
static void updateFans() {
engine->module<FanControl1>()->onSlowCallback();
}
TEST(Actuators, Fan) {
struct MockAc : public AcController {
bool acState = false;
bool isAcEnabled() const override {
return acState;
}
};
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
MockAc mockAc;
engine->module<AcController>().set(&mockAc);
engineConfiguration->fanOnTemperature = 90;
engineConfiguration->fanOffTemperature = 80;
@ -11,60 +25,62 @@ TEST(Actuators, Fan) {
// Cold, fan should be off
Sensor::setMockValue(SensorType::Clt, 75);
updateFans(false);
updateFans();
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Between thresholds, should still be off
Sensor::setMockValue(SensorType::Clt, 85);
updateFans(false);
updateFans();
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Hot, fan should turn on
Sensor::setMockValue(SensorType::Clt, 95);
updateFans(false);
updateFans();
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Between thresholds, should stay on
Sensor::setMockValue(SensorType::Clt, 85);
updateFans(false);
updateFans();
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Below threshold, should turn off
Sensor::setMockValue(SensorType::Clt, 75);
updateFans(false);
updateFans();
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
engineConfiguration->enableFan1WithAc = true;
// Now AC is on, fan should turn on!
updateFans(true);
mockAc.acState = true;
updateFans();
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Turn off AC, fan should turn off too.
updateFans(false);
mockAc.acState = false;
updateFans();
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Back to hot, fan should turn on
Sensor::setMockValue(SensorType::Clt, 95);
updateFans(false);
updateFans();
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Engine starts cranking, fan should turn off
engine->rpmCalculator.setRpmValue(100);
updateFans(false);
updateFans();
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Engine running, fan should turn back on
engine->rpmCalculator.setRpmValue(1000);
updateFans(false);
updateFans();
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Stop the engine, fan should stay on
engine->rpmCalculator.setRpmValue(0);
updateFans(false);
updateFans();
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Set configuration to inhibit fan while engine is stopped, fan should stop
engineConfiguration->disableFan1WhenStopped = true;
updateFans(false);
updateFans();
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
}