diff options
author | Richard Yeh <rcy@google.com> | 2022-11-28 02:02:16 +0000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-12-13 07:14:15 +0000 |
commit | 62c3a651befeb8d9b3ad03994b23b579d92c20d8 (patch) | |
tree | bfb65fa429c7a78fadfa5c968fc84dd351d703e2 /test/fan.c | |
parent | 802a90e2e991129c0d9ff2b4b1d8f6bd36f0a492 (diff) | |
download | chrome-ec-62c3a651befeb8d9b3ad03994b23b579d92c20d8.tar.gz |
fan: Rewrite and test the most common custom fan_percent_to_rpm.
temp_ratio_to_rpm_hysteresis uses a sorted fan_table containing a
mapping of temp_ratio (percent, 0-100) to fan rpm. This clarifies the
relationship of temperature to fan speed, while reducing the number of
static variables. The existing temp_ratio expressing the percentage of
cooling needed (temperature from temp_fan_off to temp_fan_max) suggests
the possibility that a proportional-integral-derivative (PID) feedback
controller might have been considered; but the default implementation
is purely linear (mapping to fan speed from min to max) and this
stepwise one just enables hysteresis --- different speeds when the
board is warming up than when cooling down. The hysteresis attempts to
avoid oscillations in temperature and fan speed.
This refactoring is in preparation for reusing this implementation for
{ambassador, genesis, moonbuggy, scout}.
{kalista, berknip, chronicler, dewatt, endeavour, ezkinil, fizz} define
CONFIG_FAN_RPM_CUSTOM and use this or nearly this implementation of a
fan_percent_to_rpm with hysteresis. {chronicler} also performs boxcar
smoothing of the input.
{osiris}, which has two fans, and {jinlon, redrix, and other boards
with multiple sensors}, use a similar but not exactly the same
implementation, and would need additional abstraction. See:
https://source.chromium.org/search?q=f:ec%2Fb%20fan_step%20-f:board.c
BRANCH=refactor-fan-percent-to-rpm
BUG=b:252966838,b:191187610,chromium:1383859
TEST=make -j run-fan && make -j buildall && make -j runhosttests
Signed-off-by: Richard Yeh <rcy@google.com>
Change-Id: I50ad4d78ac1145f92573a417646c1f57b8945463
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4021951
Reviewed-by: Jeremy Bettis <jbettis@chromium.org>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
Diffstat (limited to 'test/fan.c')
-rw-r--r-- | test/fan.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/test/fan.c b/test/fan.c index 76c3208cc6..48a019382b 100644 --- a/test/fan.c +++ b/test/fan.c @@ -104,9 +104,121 @@ static int test_fan(void) return EC_SUCCESS; } +/* Provide a test driver to make test easier to read. */ +int temp_to_rpm(int temperature_c) +{ + const int temp_fan_off = C_TO_K(35); + const int temp_fan_max = C_TO_K(55); + const struct fan_step_1_1 fan_table[] = { + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(35), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(41), + .rpm = 2500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(37), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(43), + .rpm = 3200 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(42), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(45), + .rpm = 3500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(44), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(47), + .rpm = 3900 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(46), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(49), + .rpm = 4500 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(48), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(52), + .rpm = 5100 }, + { .decreasing_temp_ratio_threshold = TEMP_TO_RATIO(51), + .increasing_temp_ratio_threshold = TEMP_TO_RATIO(55), + .rpm = 5400 }, + }; + const int num_fan_levels = ARRAY_SIZE(fan_table); + int temp_ratio = TEMP_TO_RATIO(temperature_c); + + int rpm = temp_ratio_to_rpm_hysteresis(fan_table, num_fan_levels, 0, + temp_ratio, NULL); + + fan_set_rpm_target(FAN_CH(0), rpm); + return rpm; +} + +static int test_temp_ratio_to_rpm_hysteresis(void) +{ + const int ZERO = 0; + /* set initial value to be different so that a log message appears */ + fan_set_rpm_target(FAN_CH(0), 5400); + /* initial turn-on behavior, ramp up. @ represents fan speed; + temp */ + TEST_ASSERT(temp_to_rpm(30) == ZERO); /* @+. . 40 . 50 .60 */ + TEST_ASSERT(temp_to_rpm(30) == ZERO); /* @+. . . . . . */ + TEST_ASSERT(temp_to_rpm(35) == ZERO); /* @ + . . . . */ + TEST_ASSERT(temp_to_rpm(37) == ZERO); /* @ . + . . . . */ + TEST_ASSERT(temp_to_rpm(39) == ZERO); /* @ . +. . . . */ + TEST_ASSERT(temp_to_rpm(40) == ZERO); /* @ . + . . . */ + TEST_ASSERT(temp_to_rpm(41) == 2500); /* @. .+ . . . */ + TEST_ASSERT(temp_to_rpm(36) == 2500); /* @.+ . . . . */ + TEST_ASSERT(temp_to_rpm(42) == 2500); /* @. . + . . . */ + TEST_ASSERT(temp_to_rpm(43) == 3200); /* @ . + . . . */ + TEST_ASSERT(temp_to_rpm(38) == 3200); /* @ + . . . . */ + TEST_ASSERT(temp_to_rpm(44) == 3200); /* @ . +. . . */ + TEST_ASSERT(temp_to_rpm(45) == 3500); /* .@ . + . . */ + TEST_ASSERT(temp_to_rpm(43) == 3500); /* .@ . + . . . */ + TEST_ASSERT(temp_to_rpm(46) == 3500); /* .@ . .+ . . */ + TEST_ASSERT(temp_to_rpm(47) == 3900); /* . @ . . + . . */ + TEST_ASSERT(temp_to_rpm(45) == 3900); /* . @ . + . . */ + TEST_ASSERT(temp_to_rpm(48) == 3900); /* . @ . . + . . */ + TEST_ASSERT(temp_to_rpm(49) == 4500); /* . @ . . +. . */ + TEST_ASSERT(temp_to_rpm(47) == 4500); /* . @ . . + . . */ + TEST_ASSERT(temp_to_rpm(51) == 4500); /* . @ . . .+ . */ + TEST_ASSERT(temp_to_rpm(52) == 5100); /* . @. . . + . */ + TEST_ASSERT(temp_to_rpm(49) == 5100); /* . @. . +. . */ + TEST_ASSERT(temp_to_rpm(54) == 5100); /* . @. . . +. */ + TEST_ASSERT(temp_to_rpm(55) == 5400); /* . @ . . + */ + TEST_ASSERT(temp_to_rpm(52) == 5400); /* . @ . . + . */ + TEST_ASSERT(temp_to_rpm(60) == 5400); /* . @ . 50 ..+ */ + /* cool-down */ + TEST_ASSERT(temp_to_rpm(55) == 5400); /* . @ . . + */ + TEST_ASSERT(temp_to_rpm(52) == 5400); /* . @ . . + . */ + TEST_ASSERT(temp_to_rpm(51) == 5100); /* . @. . .+ . */ + TEST_ASSERT(temp_to_rpm(54) == 5100); /* . @. . . +. */ + TEST_ASSERT(temp_to_rpm(49) == 5100); /* . @. . +. . */ + TEST_ASSERT(temp_to_rpm(48) == 4500); /* . @ . . + . . */ + TEST_ASSERT(temp_to_rpm(51) == 4500); /* . @ . . .+ . */ + TEST_ASSERT(temp_to_rpm(47) == 4500); /* . @ . . + . . */ + TEST_ASSERT(temp_to_rpm(46) == 3900); /* . @ . .+ . . */ + TEST_ASSERT(temp_to_rpm(48) == 3900); /* . @ . . + . . */ + TEST_ASSERT(temp_to_rpm(45) == 3900); /* . @ . + . . */ + TEST_ASSERT(temp_to_rpm(44) == 3500); /* .@ . +. . . */ + TEST_ASSERT(temp_to_rpm(46) == 3500); /* .@ . .+ . . */ + TEST_ASSERT(temp_to_rpm(43) == 3500); /* .@ . + . . . */ + TEST_ASSERT(temp_to_rpm(42) == 3200); /* @ . + . . . */ + TEST_ASSERT(temp_to_rpm(44) == 3200); /* @ . +. . . */ + TEST_ASSERT(temp_to_rpm(38) == 3200); /* @ + . . . . */ + TEST_ASSERT(temp_to_rpm(37) == 2500); /* @. + . . . . */ + TEST_ASSERT(temp_to_rpm(42) == 2500); /* @. . + . . . */ + TEST_ASSERT(temp_to_rpm(36) == 2500); /* @.+ . . . . */ + TEST_ASSERT(temp_to_rpm(35) == ZERO); /* @ + 40 . 50 . */ + /* warm up again */ + TEST_ASSERT(temp_to_rpm(38) == ZERO); /* @ . + . . . . */ + /* jumping */ + TEST_ASSERT(temp_to_rpm(46) == 3500); /* .@ . .+ . . */ + TEST_ASSERT(temp_to_rpm(36) == 2500); /* @.+ . . . . */ + TEST_ASSERT(temp_to_rpm(35) == ZERO); /* @ + . . . . */ + TEST_ASSERT(temp_to_rpm(37) == ZERO); /* @ . + . . . . */ + TEST_ASSERT(temp_to_rpm(46) == 3500); /* .@ . .+ . . */ + TEST_ASSERT(temp_to_rpm(54) == 5100); /* . @. . . +. */ + TEST_ASSERT(temp_to_rpm(55) == 5400); /* . @ . . + */ + TEST_ASSERT(temp_to_rpm(60) == 5400); /* . @ . . ..+ */ + TEST_ASSERT(temp_to_rpm(53) == 5400); /* . @ . . + . */ + TEST_ASSERT(temp_to_rpm(46) == 3900); /* . @ . .+ . . */ + TEST_ASSERT(temp_to_rpm(30) == ZERO); /* @+. . 40 . 50 . */ + + return EC_SUCCESS; +} + void run_test(int argc, const char **argv) { RUN_TEST(test_fan); + RUN_TEST(test_temp_ratio_to_rpm_hysteresis); test_print_result(); } |