diff --git a/firmware/controllers/algo/idle_controller.cpp b/firmware/controllers/algo/idle_controller.cpp index f9b0c5333a..44a20ed6a8 100644 --- a/firmware/controllers/algo/idle_controller.cpp +++ b/firmware/controllers/algo/idle_controller.cpp @@ -24,10 +24,13 @@ static int lastGoodValue = DEFAULT_IDLE_DUTY; EXTERN_ENGINE ; -void idleInit(IdleValveState *idle DECLARE_ENGINE_PARAMETER_S) { - idle->value = DEFAULT_IDLE_DUTY; - setIdleRpm(idle, engineConfiguration->targetIdleRpm); - idle->timeOfLastIdleChange = 0; +IdleValveState::IdleValveState() { + value = DEFAULT_IDLE_DUTY; + timeOfLastIdleChange = 0; +} + +void IdleValveState::init(DECLARE_ENGINE_PARAMETER_F) { + setIdleRpm(this, engineConfiguration->targetIdleRpm); } void setIdleRpm(IdleValveState *idle, int targetRpm) { @@ -38,9 +41,9 @@ void setIdleRpm(IdleValveState *idle, int targetRpm) { /** * @brief sets new idle valve duty cycle: checks the bounds and reports new value */ -static int setNewValue(IdleValveState *idle, int currentRpm, efitimems_t now, const char * msg, int newValue) { - newValue = maxI(newValue, MIN_IDLE); - newValue = minI(newValue, MAX_IDLE); +static percent_t setNewValue(IdleValveState *idle, int currentRpm, efitimems_t now, const char * msg, percent_t newValue) { + newValue = maxF(newValue, MIN_IDLE); + newValue = minF(newValue, MAX_IDLE); if (idle->value != newValue) { idleDebug(msg, currentRpm); @@ -51,53 +54,49 @@ static int setNewValue(IdleValveState *idle, int currentRpm, efitimems_t now, co return newValue; } -static int changeValue(IdleValveState *idle, int currentRpm, int now, const char * msg, int delta DECLARE_ENGINE_PARAMETER_S) { +static percent_t changeValue(IdleValveState *idle, int currentRpm, int now, const char * msg, percent_t delta DECLARE_ENGINE_PARAMETER_S) { if (getTPS(PASS_ENGINE_PARAMETER_F) > 5.0) { // We are not supposed to be in idle mode. Don't touch anything idleDebug("TPS Lockout, TPS=", getTPS(PASS_ENGINE_PARAMETER_F)); return idle->value; } - int newValue = idle->value + delta; + percent_t newValue = idle->value + delta; return setNewValue(idle, currentRpm, now, msg, newValue); } /** * now - current time in milliseconds */ -int getIdle(IdleValveState *idle, int currentRpm, efitimems_t now DECLARE_ENGINE_PARAMETER_S) { +percent_t IdleValveState::getIdle(int currentRpm, efitimems_t now DECLARE_ENGINE_PARAMETER_S) { if (currentRpm == 0 || isCranking()) { - return setNewValue(idle, currentRpm, now, "cranking value: ", DEFAULT_IDLE_DUTY); + return setNewValue(this, currentRpm, now, "cranking value: ", DEFAULT_IDLE_DUTY); } - if (currentRpm < 0.7 * idle->targetRpmRangeLeft) { - return setNewValue(idle, currentRpm, now, "RPMs are seriously low: ", lastGoodValue); + if (currentRpm < 0.7 * targetRpmRangeLeft) { + return setNewValue(this, currentRpm, now, "RPMs are seriously low: ", lastGoodValue); } - if (now - idle->timeOfLastIdleChange < IDLE_PERIOD) { + if (now - timeOfLastIdleChange < IDLE_PERIOD) { // too soon to adjust anything - exiting - return idle->value; + return value; } - if (currentRpm > idle->targetRpmRangeLeft && currentRpm < idle->targetRpmRangeRight) { + if (currentRpm > targetRpmRangeLeft && currentRpm < targetRpmRangeRight) { // current RPM is good enough // todo: need idle signal input //lastGoodValue = idle->value; - return idle->value; + return value; } - if (currentRpm >= idle->targetRpmRangeRight + 100) - return changeValue(idle, currentRpm, now, "idle control: rpm is too high: ", -IDLE_DECREASE_STEP PASS_ENGINE_PARAMETER); + if (currentRpm >= targetRpmRangeRight + 100) + return changeValue(this, currentRpm, now, "idle control: rpm is too high: ", -IDLE_DECREASE_STEP PASS_ENGINE_PARAMETER); - if (currentRpm >= idle->targetRpmRangeRight) - return changeValue(idle, currentRpm, now, "idle control: rpm is a bit too high: ", -1 PASS_ENGINE_PARAMETER); + if (currentRpm >= targetRpmRangeRight) + return changeValue(this, currentRpm, now, "idle control: rpm is a bit too high: ", -IDLE_DECREASE_SMALL_STEP PASS_ENGINE_PARAMETER); // we are here if RPM is low, let's see how low -// if (currentRpm < 0.7 * idle->targetRpmRangeLeft) { -// // todo: act faster in case of really low RPM? -// return setNewValue(idle, currentRpm, now, "RPMs are seriously low: ", 15 * IDLE_INCREASE_STEP); -// } else - if (currentRpm < idle->targetRpmRangeLeft - 100) { - return changeValue(idle, currentRpm, now, "idle control: RPMs are low: ", IDLE_INCREASE_STEP PASS_ENGINE_PARAMETER); + if (currentRpm < targetRpmRangeLeft - 100) { + return changeValue(this, currentRpm, now, "idle control: RPMs are low: ", IDLE_INCREASE_STEP PASS_ENGINE_PARAMETER); } - return changeValue(idle, currentRpm, now, "idle control: RPMs are a bit low: ", 1 PASS_ENGINE_PARAMETER); + return changeValue(this, currentRpm, now, "idle control: RPMs are a bit low: ", IDLE_INCREASE_SMALL_STEP PASS_ENGINE_PARAMETER); } diff --git a/firmware/controllers/algo/idle_controller.h b/firmware/controllers/algo/idle_controller.h index d64ec1334c..474f95b9fb 100644 --- a/firmware/controllers/algo/idle_controller.h +++ b/firmware/controllers/algo/idle_controller.h @@ -10,41 +10,35 @@ #ifndef IDLE_CONTROLLER_H_ #define IDLE_CONTROLLER_H_ -// 600‰ duty cycle by default -#define DEFAULT_IDLE_DUTY 600 +// 60% duty cycle by default +#define DEFAULT_IDLE_DUTY 60 #define IDLE_PERIOD 1000 -// Per mil (1/1000) values -#define MIN_IDLE 100 -#define MAX_IDLE 900 -#define IDLE_INCREASE_STEP 5 -#define IDLE_DECREASE_STEP 5 +// Percent values +#define MIN_IDLE 10.0f +#define MAX_IDLE 90.0f +#define IDLE_INCREASE_STEP 0.5f +#define IDLE_DECREASE_STEP 0.5f +#define IDLE_INCREASE_SMALL_STEP 0.1F +#define IDLE_DECREASE_SMALL_STEP 0.1F class IdleValveState { public: + IdleValveState(); + void init(DECLARE_ENGINE_PARAMETER_F); + percent_t getIdle(int currentRpm, efitimems_t now DECLARE_ENGINE_PARAMETER_S); + int time; int targetRpmRangeLeft, targetRpmRangeRight; - int value; + percent_t value; efitimems_t timeOfLastIdleChange; }; -void idleInit(IdleValveState *idle DECLARE_ENGINE_PARAMETER_S); -int getIdle(IdleValveState *idle, int currentRpm, efitimems_t now DECLARE_ENGINE_PARAMETER_S); void setIdleRpm(IdleValveState *idle, int targetRpm); -void idleDebug(const char *msg, int value); - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +void idleDebug(const char *msg, percent_t value); #endif /* IDLE_CONTROLLER_H_ */ diff --git a/firmware/controllers/idle_thread.cpp b/firmware/controllers/idle_thread.cpp index 4e20c5907f..381442f9d0 100644 --- a/firmware/controllers/idle_thread.cpp +++ b/firmware/controllers/idle_thread.cpp @@ -56,8 +56,8 @@ int getIdleSwitch() { return idleSwitchState; } -void idleDebug(const char *msg, int value) { - printMsg(&logger, "%s%d", msg, value); +void idleDebug(const char *msg, percent_t value) { + printMsg(&logger, "%s%f", msg, value); scheduleLogging(&logger); } @@ -72,16 +72,15 @@ static void setIdleControlEnabled(int value) { showIdleInfo(); } -static void setIdleValvePwm(int value) { - // todo: change parameter type, maybe change parameter validation? - if (value < 1 || value > 999) +static void setIdleValvePwm(percent_t value) { + if (value < 0.01 || value > 99.9) return; - scheduleMsg(&logger, "setting idle valve PWM %d", value); - float f = 0.001 * value; + scheduleMsg(&logger, "setting idle valve PWM %f", value); + float f = 0.01 * value; boardConfiguration->idleSolenoidPwm = f; showIdleInfo(); /** - * currently idle level is an integer per mil (0-1000 range), and PWM takes a float in the 0..1 range + * currently idle level is an percent value (0-100 range), and PWM takes a float in the 0..1 range * todo: unify? */ idleValvePwm.setSimplePwmDutyCycle(f); @@ -91,7 +90,7 @@ static msg_t ivThread(int param) { (void) param; chRegSetThreadName("IdleValve"); - int currentIdleValve = -1; + percent_t currentIdleValve = -1; while (true) { chThdSleepMilliseconds(boardConfiguration->idleThreadPeriod); @@ -104,7 +103,7 @@ static msg_t ivThread(int param) { efitimems_t now = currentTimeMillis(); - int newValue = getIdle(&idle, getRpm(), now PASS_ENGINE_PARAMETER); + percent_t newValue = idle.getIdle(getRpm(), now PASS_ENGINE_PARAMETER); if (currentIdleValve != newValue) { currentIdleValve = newValue; @@ -140,7 +139,7 @@ void startIdleThread(Engine *engine) { startSimplePwmExt(&idleValvePwm, "Idle Valve", boardConfiguration->idleValvePin, IDLE_VALVE, boardConfiguration->idleSolenoidFrequency, boardConfiguration->idleSolenoidPwm, applyIdleSolenoidPinState); - idleInit(&idle); + idle.init(); scheduleMsg(&logger, "initial idle %d", idle.value); chThdCreateStatic(ivThreadStack, sizeof(ivThreadStack), NORMALPRIO, (tfunc_t) ivThread, NULL); @@ -151,7 +150,7 @@ void startIdleThread(Engine *engine) { addConsoleAction("idleinfo", showIdleInfo); addConsoleActionI("set_idle_rpm", setIdleRpmAction); - addConsoleActionI("set_idle_pwm", setIdleValvePwm); + addConsoleActionF("set_idle_pwm", setIdleValvePwm); addConsoleActionI("set_idle_enabled", (VoidInt) setIdleControlEnabled); } diff --git a/firmware/controllers/math/efitime.h b/firmware/controllers/math/efitime.h index 76c4f9cd9f..1285b29b94 100644 --- a/firmware/controllers/math/efitime.h +++ b/firmware/controllers/math/efitime.h @@ -20,6 +20,11 @@ */ typedef uint32_t efitimems_t; +/** + * numeric value from 0 to 100 + */ +typedef float percent_t; + #ifdef __cplusplus extern "C" { diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp index 80b0118578..d059dfe383 100644 --- a/firmware/rusefi.cpp +++ b/firmware/rusefi.cpp @@ -265,5 +265,5 @@ int getRusEfiVersion(void) { return 1; // this is here to make the compiler happy about the unused array if (UNUSED_CCM_SIZE == 0) return 1; // this is here to make the compiler happy about the unused array - return 20141231; + return 20150101; } diff --git a/unit_tests/main.cpp b/unit_tests/main.cpp index e37934aac1..3d880f6076 100644 --- a/unit_tests/main.cpp +++ b/unit_tests/main.cpp @@ -24,10 +24,11 @@ #include "test_logic_expression.h" #include "engine_configuration.h" +#include "test_idle_controller.h" + extern "C" { #include "map_resize.h" -#include "test_idle_controller.h" #include "test_event_registry.h" #include "test_signal_executor.h" #include "test_util.h" @@ -137,8 +138,10 @@ int main(void) { testFLStack(); + testIdleController(); + // resizeMap(); - printf("Success 20131216\r\n"); + printf("Success 20150101\r\n"); return EXIT_SUCCESS; } diff --git a/unit_tests/test_idle_controller.cpp b/unit_tests/test_idle_controller.cpp index baf27d0b06..e1e46e073d 100644 --- a/unit_tests/test_idle_controller.cpp +++ b/unit_tests/test_idle_controller.cpp @@ -6,7 +6,32 @@ */ #include +#include "idle_controller.h" +#include "efitime.h" +#include "engine_test_helper.h" -void idleDebug(const char *msg, int value) { +void idleDebug(const char *msg, percent_t value) { printf("%s\r\n", msg); } + +static IdleValveState is; + +void testIdleController(void) { + EngineTestHelper eth(FORD_INLINE_6_1995); + Engine *engine = ð.engine; + engine_configuration_s *engineConfiguration = engine->engineConfiguration; + + engineConfiguration->targetIdleRpm = 1200; + + is.init(PASS_ENGINE_PARAMETER_F); + + efitimems_t time = 0; + + assertEquals(60, is.getIdle(900, time PASS_ENGINE_PARAMETER)); + + time += 2000; + assertEquals(60.5, is.getIdle(900, time PASS_ENGINE_PARAMETER)); + + time += 2000; + assertEquals(60.6, is.getIdle(1050, time PASS_ENGINE_PARAMETER)); +} diff --git a/unit_tests/test_idle_controller.h b/unit_tests/test_idle_controller.h index d44f5b0c58..9736c08151 100644 --- a/unit_tests/test_idle_controller.h +++ b/unit_tests/test_idle_controller.h @@ -1,6 +1,7 @@ #ifndef TEST_IDLE_CONTROLLER_H #define TEST_IDLE_CONTROLLER_H +void testIdleController(void); void idleDebug(char *msg, int value); //bool_t isCranking(void); diff --git a/win32_functional_tests/simulator/rusEfiFunctionalTest.cpp b/win32_functional_tests/simulator/rusEfiFunctionalTest.cpp index e441ad126b..b64950b070 100644 --- a/win32_functional_tests/simulator/rusEfiFunctionalTest.cpp +++ b/win32_functional_tests/simulator/rusEfiFunctionalTest.cpp @@ -57,7 +57,7 @@ int getRemainingStack(Thread *otp) { return 99999; } -void idleDebug(const char *msg, int value) { +void idleDebug(const char *msg, percent_t value) { } float getMap(void) {