Fix fan curve saving - use flat config structure for WLED compatibility
- Changed from nested JSON array to flat curve-t1/s1, curve-t2/s2, etc. - Added appendConfigData() for config page labels - Reduced max curve points to 5 for simpler config - Added bounds checking for speed values
This commit is contained in:
parent
77a3853a4e
commit
a3cd6bac16
@ -10,7 +10,7 @@
|
||||
* Features:
|
||||
* - Web API for temperature updates from external sources (GPU, etc.)
|
||||
* - Fixed speed mode with configurable percentage
|
||||
* - Temperature curve mode with up to 10 configurable points
|
||||
* - Temperature curve mode with up to 5 configurable points
|
||||
* - Safety fallback to 100% if temperature data times out
|
||||
* - Integration with WLED's web interface
|
||||
*
|
||||
@ -54,19 +54,24 @@ class GPUFanControllerUsermod : public Usermod {
|
||||
ControlMode controlMode = MODE_CURVE;
|
||||
uint8_t fixedSpeedPct = 50; // 0-100%
|
||||
|
||||
// Temperature curve (up to 10 points)
|
||||
static const uint8_t MAX_CURVE_POINTS = 10;
|
||||
// Temperature curve - using flat structure for WLED config compatibility
|
||||
// 5 curve points with separate temp and speed values
|
||||
static const uint8_t MAX_CURVE_POINTS = 5;
|
||||
uint8_t curveCount = 4;
|
||||
struct CurvePoint {
|
||||
float temp;
|
||||
uint8_t speed;
|
||||
};
|
||||
CurvePoint curve[MAX_CURVE_POINTS] = {
|
||||
{30.0f, 30},
|
||||
{50.0f, 50},
|
||||
{70.0f, 75},
|
||||
{85.0f, 100}
|
||||
};
|
||||
|
||||
// Curve point temperatures (°C)
|
||||
int16_t curveTemp1 = 30;
|
||||
int16_t curveTemp2 = 50;
|
||||
int16_t curveTemp3 = 70;
|
||||
int16_t curveTemp4 = 85;
|
||||
int16_t curveTemp5 = 95;
|
||||
|
||||
// Curve point speeds (%)
|
||||
uint8_t curveSpeed1 = 30;
|
||||
uint8_t curveSpeed2 = 50;
|
||||
uint8_t curveSpeed3 = 75;
|
||||
uint8_t curveSpeed4 = 100;
|
||||
uint8_t curveSpeed5 = 100;
|
||||
|
||||
// Runtime state
|
||||
float currentTemp = 25.0f;
|
||||
@ -132,28 +137,57 @@ class GPUFanControllerUsermod : public Usermod {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get curve temperature at index
|
||||
int16_t getCurveTemp(uint8_t idx) {
|
||||
switch(idx) {
|
||||
case 0: return curveTemp1;
|
||||
case 1: return curveTemp2;
|
||||
case 2: return curveTemp3;
|
||||
case 3: return curveTemp4;
|
||||
case 4: return curveTemp5;
|
||||
default: return 50;
|
||||
}
|
||||
}
|
||||
|
||||
// Get curve speed at index
|
||||
uint8_t getCurveSpeed(uint8_t idx) {
|
||||
switch(idx) {
|
||||
case 0: return curveSpeed1;
|
||||
case 1: return curveSpeed2;
|
||||
case 2: return curveSpeed3;
|
||||
case 3: return curveSpeed4;
|
||||
case 4: return curveSpeed5;
|
||||
default: return 50;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate fan speed from temperature curve
|
||||
uint8_t calculateCurveSpeed(float temp) {
|
||||
if (curveCount < 2) return 50; // Fallback
|
||||
|
||||
// Below first point
|
||||
if (temp <= curve[0].temp) {
|
||||
return curve[0].speed;
|
||||
if (temp <= getCurveTemp(0)) {
|
||||
return getCurveSpeed(0);
|
||||
}
|
||||
|
||||
// Above last point
|
||||
if (temp >= curve[curveCount - 1].temp) {
|
||||
return curve[curveCount - 1].speed;
|
||||
if (temp >= getCurveTemp(curveCount - 1)) {
|
||||
return getCurveSpeed(curveCount - 1);
|
||||
}
|
||||
|
||||
// Linear interpolation between points
|
||||
for (uint8_t i = 0; i < curveCount - 1; i++) {
|
||||
if (temp >= curve[i].temp && temp <= curve[i + 1].temp) {
|
||||
float tempRange = curve[i + 1].temp - curve[i].temp;
|
||||
float speedRange = curve[i + 1].speed - curve[i].speed;
|
||||
float tempDiff = temp - curve[i].temp;
|
||||
int16_t t1 = getCurveTemp(i);
|
||||
int16_t t2 = getCurveTemp(i + 1);
|
||||
uint8_t s1 = getCurveSpeed(i);
|
||||
uint8_t s2 = getCurveSpeed(i + 1);
|
||||
|
||||
if (temp >= t1 && temp <= t2) {
|
||||
float tempRange = t2 - t1;
|
||||
float speedRange = s2 - s1;
|
||||
float tempDiff = temp - t1;
|
||||
|
||||
int speed = curve[i].speed + (int)((tempDiff / tempRange) * speedRange);
|
||||
int speed = s1 + (int)((tempDiff / tempRange) * speedRange);
|
||||
return constrain(speed, 0, 100);
|
||||
}
|
||||
}
|
||||
@ -310,16 +344,39 @@ class GPUFanControllerUsermod : public Usermod {
|
||||
top["pwm-pin"] = pwmPin;
|
||||
top["mode"] = (int)controlMode;
|
||||
top["fixed-speed"] = fixedSpeedPct;
|
||||
top["timeout-ms"] = tempTimeoutMs;
|
||||
top["timeout-ms"] = (int)tempTimeoutMs;
|
||||
top["curve-points"] = curveCount;
|
||||
|
||||
// Save curve points
|
||||
top["curve-count"] = curveCount;
|
||||
JsonArray curveArr = top.createNestedArray("curve");
|
||||
for (uint8_t i = 0; i < curveCount; i++) {
|
||||
JsonObject point = curveArr.createNestedObject();
|
||||
point["temp"] = curve[i].temp;
|
||||
point["speed"] = curve[i].speed;
|
||||
}
|
||||
// Save curve points as flat values
|
||||
top["curve-t1"] = curveTemp1;
|
||||
top["curve-t2"] = curveTemp2;
|
||||
top["curve-t3"] = curveTemp3;
|
||||
top["curve-t4"] = curveTemp4;
|
||||
top["curve-t5"] = curveTemp5;
|
||||
top["curve-s1"] = curveSpeed1;
|
||||
top["curve-s2"] = curveSpeed2;
|
||||
top["curve-s3"] = curveSpeed3;
|
||||
top["curve-s4"] = curveSpeed4;
|
||||
top["curve-s5"] = curveSpeed5;
|
||||
}
|
||||
|
||||
// Append config data (labels for config page)
|
||||
void appendConfigData() override {
|
||||
oappend(SET_F("addInfo('GPU-Fan:pwm-pin',1,'GPIO');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:mode',1,'0=Fixed, 1=Curve');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:fixed-speed',1,'%');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:timeout-ms',1,'ms (safety timeout)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-points',1,'2-5 points');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-t1',1,'°C (Point 1 temp)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-s1',1,'% (Point 1 speed)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-t2',1,'°C (Point 2 temp)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-s2',1,'% (Point 2 speed)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-t3',1,'°C (Point 3 temp)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-s3',1,'% (Point 3 speed)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-t4',1,'°C (Point 4 temp)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-s4',1,'% (Point 4 speed)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-t5',1,'°C (Point 5 temp)');"));
|
||||
oappend(SET_F("addInfo('GPU-Fan:curve-s5',1,'% (Point 5 speed)');"));
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
@ -336,23 +393,28 @@ class GPUFanControllerUsermod : public Usermod {
|
||||
newPwmPin = top["pwm-pin"] | newPwmPin;
|
||||
controlMode = (ControlMode)(top["mode"] | (int)controlMode);
|
||||
fixedSpeedPct = top["fixed-speed"] | fixedSpeedPct;
|
||||
tempTimeoutMs = top["timeout-ms"] | tempTimeoutMs;
|
||||
|
||||
// Load curve points
|
||||
curveCount = top["curve-count"] | curveCount;
|
||||
tempTimeoutMs = top["timeout-ms"] | (int)tempTimeoutMs;
|
||||
curveCount = top["curve-points"] | curveCount;
|
||||
curveCount = constrain(curveCount, 2, MAX_CURVE_POINTS);
|
||||
|
||||
JsonArray curveArr = top["curve"];
|
||||
if (!curveArr.isNull()) {
|
||||
uint8_t i = 0;
|
||||
for (JsonObject point : curveArr) {
|
||||
if (i >= MAX_CURVE_POINTS) break;
|
||||
curve[i].temp = point["temp"] | curve[i].temp;
|
||||
curve[i].speed = point["speed"] | curve[i].speed;
|
||||
i++;
|
||||
}
|
||||
curveCount = i;
|
||||
}
|
||||
// Load curve points
|
||||
curveTemp1 = top["curve-t1"] | curveTemp1;
|
||||
curveTemp2 = top["curve-t2"] | curveTemp2;
|
||||
curveTemp3 = top["curve-t3"] | curveTemp3;
|
||||
curveTemp4 = top["curve-t4"] | curveTemp4;
|
||||
curveTemp5 = top["curve-t5"] | curveTemp5;
|
||||
curveSpeed1 = top["curve-s1"] | curveSpeed1;
|
||||
curveSpeed2 = top["curve-s2"] | curveSpeed2;
|
||||
curveSpeed3 = top["curve-s3"] | curveSpeed3;
|
||||
curveSpeed4 = top["curve-s4"] | curveSpeed4;
|
||||
curveSpeed5 = top["curve-s5"] | curveSpeed5;
|
||||
|
||||
// Constrain speed values
|
||||
curveSpeed1 = constrain(curveSpeed1, 0, 100);
|
||||
curveSpeed2 = constrain(curveSpeed2, 0, 100);
|
||||
curveSpeed3 = constrain(curveSpeed3, 0, 100);
|
||||
curveSpeed4 = constrain(curveSpeed4, 0, 100);
|
||||
curveSpeed5 = constrain(curveSpeed5, 0, 100);
|
||||
|
||||
if (!initDone) {
|
||||
pwmPin = newPwmPin;
|
||||
@ -366,7 +428,7 @@ class GPUFanControllerUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
return !top["curve-count"].isNull();
|
||||
return !top["curve-t1"].isNull();
|
||||
}
|
||||
|
||||
uint16_t getId() override {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user