From 237ffedcb31f8eb786aceac9b22e5224aed89b61 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Tue, 18 Apr 2023 14:15:06 -0700 Subject: [PATCH] Dos fan fix (#1335) * hitl fan test * enable cooldown on dos as well * small cleanup * get expected RPM from panda class * fix * overshoot test * fix max RPM getting * fix percentage * revert cooldown fix * add cooldown for dos fan as well * remove feedforward from the fan controller to eliminate overshoot * update clip * cleanup * add that back --------- Co-authored-by: Comma Device Co-authored-by: Adeeb Shihadeh --- board/boards/dos.h | 2 +- board/drivers/fan.h | 11 ++++------- python/__init__.py | 6 ++++++ tests/fan_overshoot_test.py | 31 +++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100755 tests/fan_overshoot_test.py diff --git a/board/boards/dos.h b/board/boards/dos.h index b6451bd6..2af19d7c 100644 --- a/board/boards/dos.h +++ b/board/boards/dos.h @@ -217,7 +217,7 @@ const board board_dos = { .fan_max_rpm = 6500U, .adc_scale = 8862U, .fan_stall_recovery = true, - .fan_enable_cooldown_time = 0U, + .fan_enable_cooldown_time = 3U, .init = dos_init, .enable_can_transceiver = dos_enable_can_transceiver, .enable_can_transceivers = dos_enable_can_transceivers, diff --git a/board/drivers/fan.h b/board/drivers/fan.h index cf4faa09..bd3b59d1 100644 --- a/board/drivers/fan.h +++ b/board/drivers/fan.h @@ -48,7 +48,7 @@ void fan_tick(void){ current_board->set_fan_enabled(false); // clip integral, can't fully reset otherwise we may always be stuck in stall detection - fan_state.error_integral = MIN(50.0f, MAX(0.0f, fan_state.error_integral)); + fan_state.error_integral = MIN(0.0f, fan_state.error_integral); } } else { fan_state.stall_counter = 0U; @@ -57,13 +57,10 @@ void fan_tick(void){ } // Update controller - float feedforward = (fan_state.target_rpm * 100.0f) / current_board->fan_max_rpm; - float error = fan_state.target_rpm - fan_rpm_fast; + fan_state.error_integral += FAN_I * (fan_state.target_rpm - fan_rpm_fast); + fan_state.error_integral = MIN(100.0f, MAX(0.0f, fan_state.error_integral)); - fan_state.error_integral += FAN_I * error; - fan_state.error_integral = MIN(70.0f, MAX(-70.0f, fan_state.error_integral)); - - fan_state.power = MIN(100U, MAX(0U, feedforward + fan_state.error_integral)); + fan_state.power = MIN(100U, MAX(0U, fan_state.error_integral)); pwm_set(TIM3, 3, fan_state.power); // Cooldown counter diff --git a/python/__init__.py b/python/__init__.py index dd135c4e..eca478db 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -194,6 +194,12 @@ class Panda: INTERNAL_DEVICES = (HW_TYPE_UNO, HW_TYPE_DOS, HW_TYPE_TRES) HAS_OBD = (HW_TYPE_BLACK_PANDA, HW_TYPE_UNO, HW_TYPE_DOS, HW_TYPE_RED_PANDA, HW_TYPE_RED_PANDA_V2, HW_TYPE_TRES) + MAX_FAN_RPMs = { + HW_TYPE_UNO: 5100, + HW_TYPE_DOS: 6500, + HW_TYPE_TRES: 6600, + } + # first byte is for EPS scaling factor FLAG_TOYOTA_ALT_BRAKE = (1 << 8) FLAG_TOYOTA_STOCK_LONGITUDINAL = (2 << 8) diff --git a/tests/fan_overshoot_test.py b/tests/fan_overshoot_test.py new file mode 100755 index 00000000..56fd7650 --- /dev/null +++ b/tests/fan_overshoot_test.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import time +from panda import Panda + +def get_overshoot_rpm(p, power): + # make sure the fan is stopped completely + p.set_fan_power(0) + while p.get_fan_rpm() > 100: + time.sleep(0.1) + time.sleep(1) + + # set it to 30% power to mimic going onroad + p.set_fan_power(power) + max_rpm = 0 + for _ in range(70): + max_rpm = max(max_rpm, p.get_fan_rpm()) + time.sleep(0.1) + + # tolerate 10% overshoot + expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * power / 100 + overshoot = (max_rpm / expected_rpm) - 1 + + return overshoot, max_rpm + +if __name__ == "__main__": + p = Panda() + + for power in range(10, 101, 10): + overshoot, max_rpm = get_overshoot_rpm(p, power) + print(f"Fan power {power}% overshoot: {overshoot:.2f} Max RPM: {max_rpm}")