From 46a06214a220056cd4a2fb25f384a7e74695d543 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 4 Oct 2022 00:26:57 +0200 Subject: [PATCH] Fix severe bug, improve logging, handle fan stops Conversion from power percentage to PWM value didn't take into floating point arithmetic into account Make log messages more helpful, add handling for fan stopping completely --- app/include/fan/Fan.h | 11 +++++++---- app/include/fan/HwmonFan.h | 11 +++++++---- app/src/App.cxx | 2 +- app/src/Serializer.cxx | 2 ++ app/src/fan/FanCurve.cxx | 15 ++++++++++----- app/src/fan/HwmonFan.cxx | 38 ++++++++++++++++++++++++++++++-------- app/src/pwm/PWMControl.cxx | 11 ++++++----- 7 files changed, 63 insertions(+), 27 deletions(-) diff --git a/app/include/fan/Fan.h b/app/include/fan/Fan.h index 9b81fc1..8096d79 100644 --- a/app/include/fan/Fan.h +++ b/app/include/fan/Fan.h @@ -10,11 +10,14 @@ public: virtual int RPM() = 0; virtual void Label(std::string label) = 0; - virtual void MinPWM(int value) = 0; - virtual void StartPWM(int value) = 0; - virtual void FindMinPWM() = 0; - virtual void FindStartPWM() = 0; + virtual void MinPWM(int value) = 0; + virtual int MinPWM() = 0; + + virtual void StartPWM(int value) = 0; + virtual int StartPWM() = 0; + + virtual void FindPWMLimits() = 0; }; #endif // FAN_H_ diff --git a/app/include/fan/HwmonFan.h b/app/include/fan/HwmonFan.h index 6e54900..3d3e8fb 100644 --- a/app/include/fan/HwmonFan.h +++ b/app/include/fan/HwmonFan.h @@ -17,11 +17,14 @@ public: int RPM() override; void Label(std::string label) override; - void MinPWM(int value) override; - void StartPWM(int value) override; - void FindMinPWM() override; - void FindStartPWM() override; + void MinPWM(int value) override; + int MinPWM() override; + + void StartPWM(int value) override; + int StartPWM() override; + + void FindPWMLimits() override; json toJson() const override; diff --git a/app/src/App.cxx b/app/src/App.cxx index dfdd308..e08bbe9 100644 --- a/app/src/App.cxx +++ b/app/src/App.cxx @@ -18,7 +18,7 @@ void App::InitialSetup() { mPWMControlFacade.PWMControls()); std::for_each(std::execution::par, std::begin(fans), std::end(fans), - [](auto &&fan) { fan->FindMinPWM(); }); + [](auto &&fan) { fan->FindPWMLimits(); }); mFanLabeler.RunFanLabelInteraction(fans); diff --git a/app/src/Serializer.cxx b/app/src/Serializer.cxx index ca6c36a..e0d0437 100644 --- a/app/src/Serializer.cxx +++ b/app/src/Serializer.cxx @@ -47,10 +47,12 @@ Serializer::DeserializeFans(vector> availableSensors) { auto rpmSensor = sensorMap[el.value()["LMSensor"]]; int minPWM = el.value()["MinPWM"]; + int startPWM = el.value()["StartPWM"]; string label = el.value()["Label"]; auto fan = make_shared(pwmControl, rpmSensor); fan->MinPWM(minPWM); + fan->StartPWM(startPWM); fan->Label(label); fans.push_back(fan); diff --git a/app/src/fan/FanCurve.cxx b/app/src/fan/FanCurve.cxx index 43b9b19..1fcf61c 100644 --- a/app/src/fan/FanCurve.cxx +++ b/app/src/fan/FanCurve.cxx @@ -15,15 +15,16 @@ FanCurve::FanCurve(std::vector steps, } void FanCurve::DoFanControl() { + BOOST_LOG_FUNCTION(); int temp = AggregateTemperature(); int t0, t1, p0, p1; - int targetFanSpeed; + int targetFanPower; if (temp <= mSteps[0].Temp) { - targetFanSpeed = mSteps[0].Percent; + targetFanPower = mSteps[0].Percent; } else if (temp > mSteps[mSteps.size() - 1].Temp) { - targetFanSpeed = mSteps[mSteps.size() - 1].Percent; + targetFanPower = mSteps[mSteps.size() - 1].Percent; } else { for (int i = 0; i < mSteps.size(); i++) { if (temp > mSteps[i].Temp) { @@ -35,11 +36,15 @@ void FanCurve::DoFanControl() { } } - targetFanSpeed = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0); + targetFanPower = p0 + ((p1 - p0) / (t1 - t0)) * (temp - t0); } for (auto f : mFans) { - f->PWM(targetFanSpeed); + if (f->RPM() <= 0) { + BOOST_LOG_TRIVIAL(warning) << "Fan stopped completely!"; + f->PWM(f->StartPWM()); + } + f->PWM(targetFanPower); } } diff --git a/app/src/fan/HwmonFan.cxx b/app/src/fan/HwmonFan.cxx index 22a56fc..eb46866 100644 --- a/app/src/fan/HwmonFan.cxx +++ b/app/src/fan/HwmonFan.cxx @@ -7,7 +7,7 @@ #include #include -#define TIMEOUT 5 +#define TIMEOUT 10 using namespace std; @@ -31,12 +31,17 @@ void HwmonFan::Label(std::string label) { mLabel = label; } void HwmonFan::MinPWM(int value) { mMinPWM = value; } +int HwmonFan::MinPWM() { return mMinPWM; } + +int HwmonFan::StartPWM() { return mStartPWM; } + void HwmonFan::StartPWM(int value) { mStartPWM = value; } -void HwmonFan::FindMinPWM() { +void HwmonFan::FindPWMLimits() { cout << "Looking for minimal PWM" << endl; int minPWM = 0; mMinPWM = 0; + mStartPWM = 0; for (int curPWM = 100; curPWM > 0; curPWM -= 5) { PWM(curPWM); @@ -50,22 +55,39 @@ void HwmonFan::FindMinPWM() { } } + cout << "Setting minimal PWM: " << minPWM << endl; + mMinPWM = minPWM; + if (minPWM == 0) { cout << "Fan never stopped. "; + } else { + int startPWM = 0; + + cout << "Looking for start PWM!" << endl; + for (int curPWM = minPWM - 5; curPWM < 100; curPWM += 5) { + PWM(curPWM); + this_thread::sleep_for(chrono::seconds(TIMEOUT)); + + int curRPM = RPM(); + + if (curRPM > 0) { + cout << "Setting start PWM: " << startPWM << endl; + startPWM = curPWM; + break; + } + } + + mStartPWM = startPWM; } - cout << "Setting minimal PWM: " << minPWM << endl; - - mMinPWM = minPWM; } -void HwmonFan::FindStartPWM() {} - json HwmonFan::toJson() const { json obj; obj = {mPWMControl->toJson(), mRpmSensor->toJson(), {"Label", mLabel}, - {"MinPWM", mMinPWM}}; + {"MinPWM", mMinPWM}, + {"StartPWM", mStartPWM}}; return obj; } diff --git a/app/src/pwm/PWMControl.cxx b/app/src/pwm/PWMControl.cxx index 11f40aa..dea443b 100644 --- a/app/src/pwm/PWMControl.cxx +++ b/app/src/pwm/PWMControl.cxx @@ -36,6 +36,8 @@ PWMControl::PWMControl(string controlPath) : mControlPath(controlPath) { } PWMControl::~PWMControl() { + BOOST_LOG_FUNCTION(); + BOOST_LOG_TRIVIAL(trace) << "Cleanup"; Reset(); } @@ -43,17 +45,16 @@ PWMControl::~PWMControl() { void PWMControl::Power(int percent) { BOOST_LOG_FUNCTION(); - int pwmValue = PWM_MAX_VALUE * (percent / 100); + int pwmValue = (PWM_MAX_VALUE * percent) / 100; if (percent != mCurrentValue) { - BOOST_LOG_TRIVIAL(trace) << "Updating control value to " << percent; + BOOST_LOG_TRIVIAL(trace) + << "Updating control value to " << percent << "% (" << pwmValue << ")"; ofstream ostrm(mControlPath, ios::trunc); ostrm << pwmValue; ostrm.close(); mCurrentValue = percent; - } else { - BOOST_LOG_TRIVIAL(trace) << "Value unchanged, do nothing"; } } @@ -64,7 +65,7 @@ int PWMControl::Power() { istrm.open(mControlPath); istrm >> value; - return (value / PWM_MAX_VALUE) * 100; + return (value * 100) / PWM_MAX_VALUE; } void PWMControl::EnableManualControl() {