3 Commits

Author SHA1 Message Date
d65934a278 Update version 2022-10-04 00:29:21 +02:00
46a06214a2 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
2022-10-04 00:26:57 +02:00
1c2067286e Cleanup logging output 2022-10-03 14:39:09 +02:00
9 changed files with 79 additions and 37 deletions

View File

@@ -1,5 +1,5 @@
pkgname=fantasize pkgname=fantasize
pkgver=0.1.1 pkgver=0.1.2
pkgrel=1 pkgrel=1
pkgdesc='C++ fan control for Linux' pkgdesc='C++ fan control for Linux'
url='https://github.com/Tabascl/fantasize.git' url='https://github.com/Tabascl/fantasize.git'

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(fantasize VERSION 0.1.1) project(fantasize VERSION 0.1.2)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

View File

@@ -10,11 +10,14 @@ public:
virtual int RPM() = 0; virtual int RPM() = 0;
virtual void Label(std::string label) = 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 MinPWM(int value) = 0;
virtual void FindStartPWM() = 0; virtual int MinPWM() = 0;
virtual void StartPWM(int value) = 0;
virtual int StartPWM() = 0;
virtual void FindPWMLimits() = 0;
}; };
#endif // FAN_H_ #endif // FAN_H_

View File

@@ -17,11 +17,14 @@ public:
int RPM() override; int RPM() override;
void Label(std::string label) override; void Label(std::string label) override;
void MinPWM(int value) override;
void StartPWM(int value) override;
void FindMinPWM() override; void MinPWM(int value) override;
void FindStartPWM() override; int MinPWM() override;
void StartPWM(int value) override;
int StartPWM() override;
void FindPWMLimits() override;
json toJson() const override; json toJson() const override;

View File

@@ -18,7 +18,7 @@ void App::InitialSetup() {
mPWMControlFacade.PWMControls()); mPWMControlFacade.PWMControls());
std::for_each(std::execution::par, std::begin(fans), std::end(fans), std::for_each(std::execution::par, std::begin(fans), std::end(fans),
[](auto &&fan) { fan->FindMinPWM(); }); [](auto &&fan) { fan->FindPWMLimits(); });
mFanLabeler.RunFanLabelInteraction(fans); mFanLabeler.RunFanLabelInteraction(fans);

View File

@@ -47,10 +47,12 @@ Serializer::DeserializeFans(vector<shared_ptr<Sensor>> availableSensors) {
auto rpmSensor = sensorMap[el.value()["LMSensor"]]; auto rpmSensor = sensorMap[el.value()["LMSensor"]];
int minPWM = el.value()["MinPWM"]; int minPWM = el.value()["MinPWM"];
int startPWM = el.value()["StartPWM"];
string label = el.value()["Label"]; string label = el.value()["Label"];
auto fan = make_shared<HwmonFan>(pwmControl, rpmSensor); auto fan = make_shared<HwmonFan>(pwmControl, rpmSensor);
fan->MinPWM(minPWM); fan->MinPWM(minPWM);
fan->StartPWM(startPWM);
fan->Label(label); fan->Label(label);
fans.push_back(fan); fans.push_back(fan);

View File

@@ -1,5 +1,8 @@
#include <boost/log/attributes/named_scope.hpp>
#include <iostream> #include <iostream>
#include <boost/log/trivial.hpp>
#include <fan/FanCurve.h> #include <fan/FanCurve.h>
using namespace std; using namespace std;
@@ -8,20 +11,20 @@ FanCurve::FanCurve(std::vector<FanStep> steps,
std::vector<std::shared_ptr<Sensor>> sensors, std::vector<std::shared_ptr<Sensor>> sensors,
std::vector<std::shared_ptr<Fan>> fans) std::vector<std::shared_ptr<Fan>> fans)
: mSteps(steps), mTempSensors(sensors), mFans(fans) { : mSteps(steps), mTempSensors(sensors), mFans(fans) {
cout << "Initialized Fan Curve:" << endl;
PrintInfo(); PrintInfo();
} }
void FanCurve::DoFanControl() { void FanCurve::DoFanControl() {
BOOST_LOG_FUNCTION();
int temp = AggregateTemperature(); int temp = AggregateTemperature();
int t0, t1, p0, p1; int t0, t1, p0, p1;
int targetFanSpeed; int targetFanPower;
if (temp <= mSteps[0].Temp) { if (temp <= mSteps[0].Temp) {
targetFanSpeed = mSteps[0].Percent; targetFanPower = mSteps[0].Percent;
} else if (temp > mSteps[mSteps.size() - 1].Temp) { } else if (temp > mSteps[mSteps.size() - 1].Temp) {
targetFanSpeed = mSteps[mSteps.size() - 1].Percent; targetFanPower = mSteps[mSteps.size() - 1].Percent;
} else { } else {
for (int i = 0; i < mSteps.size(); i++) { for (int i = 0; i < mSteps.size(); i++) {
if (temp > mSteps[i].Temp) { if (temp > mSteps[i].Temp) {
@@ -33,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) { 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);
} }
} }
@@ -52,28 +59,32 @@ int FanCurve::AggregateTemperature() {
} }
void FanCurve::PrintInfo() { void FanCurve::PrintInfo() {
BOOST_LOG_FUNCTION()
BOOST_LOG_TRIVIAL(info) << "### Fan curve:";
stringstream sStream; stringstream sStream;
cout << "Steps: "; sStream << "Steps: ";
for (auto s : mSteps) { for (auto s : mSteps) {
sStream << "[ " << s.Temp << "C, " << s.Percent << "% ] "; sStream << "[ " << s.Temp << "C, " << s.Percent << "% ] ";
} }
cout << sStream.str() << endl; BOOST_LOG_TRIVIAL(info) << sStream.str();
sStream.str(string()); sStream.str(string());
cout << "Sensors: "; sStream << "Sensors: ";
for (auto s : mTempSensors) { for (auto s : mTempSensors) {
sStream << s->toString() << ", "; sStream << s->toString() << ", ";
} }
cout << sStream.str() << endl; BOOST_LOG_TRIVIAL(info) << sStream.str();
sStream.str(string()); sStream.str(string());
cout << "Fans: "; sStream << "Fans: ";
for (auto s : mFans) { for (auto s : mFans) {
sStream << s->toString() << ", "; sStream << s->toString() << ", ";
} }
cout << sStream.str() << endl; BOOST_LOG_TRIVIAL(info) << sStream.str();
} }

View File

@@ -7,7 +7,7 @@
#include <boost/json/object.hpp> #include <boost/json/object.hpp>
#include <fan/HwmonFan.h> #include <fan/HwmonFan.h>
#define TIMEOUT 5 #define TIMEOUT 10
using namespace std; using namespace std;
@@ -31,12 +31,17 @@ void HwmonFan::Label(std::string label) { mLabel = label; }
void HwmonFan::MinPWM(int value) { mMinPWM = value; } 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::StartPWM(int value) { mStartPWM = value; }
void HwmonFan::FindMinPWM() { void HwmonFan::FindPWMLimits() {
cout << "Looking for minimal PWM" << endl; cout << "Looking for minimal PWM" << endl;
int minPWM = 0; int minPWM = 0;
mMinPWM = 0; mMinPWM = 0;
mStartPWM = 0;
for (int curPWM = 100; curPWM > 0; curPWM -= 5) { for (int curPWM = 100; curPWM > 0; curPWM -= 5) {
PWM(curPWM); PWM(curPWM);
@@ -50,22 +55,39 @@ void HwmonFan::FindMinPWM() {
} }
} }
cout << "Setting minimal PWM: " << minPWM << endl;
mMinPWM = minPWM;
if (minPWM == 0) { if (minPWM == 0) {
cout << "Fan never stopped. "; 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;
}
} }
cout << "Setting minimal PWM: " << minPWM << endl;
mMinPWM = minPWM; mStartPWM = startPWM;
}
} }
void HwmonFan::FindStartPWM() {}
json HwmonFan::toJson() const { json HwmonFan::toJson() const {
json obj; json obj;
obj = {mPWMControl->toJson(), obj = {mPWMControl->toJson(),
mRpmSensor->toJson(), mRpmSensor->toJson(),
{"Label", mLabel}, {"Label", mLabel},
{"MinPWM", mMinPWM}}; {"MinPWM", mMinPWM},
{"StartPWM", mStartPWM}};
return obj; return obj;
} }

View File

@@ -36,24 +36,25 @@ PWMControl::PWMControl(string controlPath) : mControlPath(controlPath) {
} }
PWMControl::~PWMControl() { PWMControl::~PWMControl() {
cout << "Cleanup" << endl; BOOST_LOG_FUNCTION();
BOOST_LOG_TRIVIAL(trace) << "Cleanup";
Reset(); Reset();
} }
void PWMControl::Power(int percent) { void PWMControl::Power(int percent) {
BOOST_LOG_FUNCTION(); BOOST_LOG_FUNCTION();
int pwmValue = PWM_MAX_VALUE * (percent / 100); int pwmValue = (PWM_MAX_VALUE * percent) / 100;
if (percent != mCurrentValue) { 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); ofstream ostrm(mControlPath, ios::trunc);
ostrm << pwmValue; ostrm << pwmValue;
ostrm.close(); ostrm.close();
mCurrentValue = percent; mCurrentValue = percent;
} else {
BOOST_LOG_TRIVIAL(trace) << "Value unchanged, do nothing";
} }
} }
@@ -64,7 +65,7 @@ int PWMControl::Power() {
istrm.open(mControlPath); istrm.open(mControlPath);
istrm >> value; istrm >> value;
return (value / PWM_MAX_VALUE) * 100; return (value * 100) / PWM_MAX_VALUE;
} }
void PWMControl::EnableManualControl() { void PWMControl::EnableManualControl() {