Skip to content

Commit 5d14716

Browse files
authored
Merge pull request wled#2251 from blazoncek/pwm-fan-usermod
Pwm fan usermod enhancement
2 parents b003ed3 + 75fe1a1 commit 5d14716

File tree

1 file changed

+24
-15
lines changed

1 file changed

+24
-15
lines changed

usermods/PWM_fan/usermod_PWM_fan.h

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ class PWMFanUsermod : public Usermod {
2626

2727
bool initDone = false;
2828
bool enabled = true;
29-
30-
const int numberOfInterrupsInOneSingleRotation = 2; // Number of interrupts ESP32 sees on tacho signal on a single fan rotation. All the fans I've seen trigger two interrups.
31-
const int pwmMinimumValue = 120;
32-
const int pwmStep = 10;
33-
3429
unsigned long msLastTachoMeasurement = 0;
3530
uint16_t last_rpm = 0;
3631
#ifdef ARDUINO_ARCH_ESP32
@@ -46,6 +41,8 @@ class PWMFanUsermod : public Usermod {
4641
int8_t pwmPin = -1;
4742
uint8_t tachoUpdateSec = 30;
4843
float targetTemperature = 25.0;
44+
uint8_t minPWMValuePct = 50;
45+
uint8_t numberOfInterrupsInOneSingleRotation = 2; // Number of interrupts ESP32 sees on tacho signal on a single fan rotation. All the fans I've seen trigger two interrups.
4946

5047
// strings to reduce flash memory usage (used more than twice)
5148
static const char _name[];
@@ -54,6 +51,8 @@ class PWMFanUsermod : public Usermod {
5451
static const char _pwmPin[];
5552
static const char _temperature[];
5653
static const char _tachoUpdateSec[];
54+
static const char _minPWMValuePct[];
55+
static const char _IRQperRotation[];
5756

5857
void initTacho(void) {
5958
if (tachoPin < 0 || !pinManager.allocatePin(tachoPin, false, PinOwner::UM_Unspecified)){
@@ -80,7 +79,7 @@ class PWMFanUsermod : public Usermod {
8079
// detach interrupt while calculating rpm
8180
detachInterrupt(digitalPinToInterrupt(tachoPin));
8281
// calculate rpm
83-
last_rpm = counter_rpm * (60 / numberOfInterrupsInOneSingleRotation);
82+
last_rpm = (counter_rpm * 60) / numberOfInterrupsInOneSingleRotation;
8483
last_rpm /= tachoUpdateSec;
8584
// reset counter
8685
counter_rpm = 0;
@@ -146,24 +145,26 @@ class PWMFanUsermod : public Usermod {
146145
float difftemp = temp - targetTemperature;
147146
// Default to run fan at full speed.
148147
int newPWMvalue = 255;
148+
int pwmStep = ((100 - minPWMValuePct) * newPWMvalue) / (7*100);
149+
int pwmMinimumValue = (minPWMValuePct * newPWMvalue) / 100;
149150

150151
if ((temp == NAN) || (temp <= 0.0)) {
151152
DEBUG_PRINTLN(F("WARNING: no temperature value available. Cannot do temperature control. Will set PWM fan to 255."));
152153
} else if (difftemp <= 0.0) {
153154
// Temperature is below target temperature. Run fan at minimum speed.
154-
newPWMvalue = pwmMinimumValue;
155+
newPWMvalue = pwmMinimumValue;
155156
} else if (difftemp <= 0.5) {
156-
newPWMvalue = 140;
157+
newPWMvalue = pwmMinimumValue + pwmStep;
157158
} else if (difftemp <= 1.0) {
158-
newPWMvalue = 160;
159+
newPWMvalue = pwmMinimumValue + 2*pwmStep;
159160
} else if (difftemp <= 1.5) {
160-
newPWMvalue = 180;
161+
newPWMvalue = pwmMinimumValue + 3*pwmStep;
161162
} else if (difftemp <= 2.0) {
162-
newPWMvalue = 200;
163+
newPWMvalue = pwmMinimumValue + 4*pwmStep;
163164
} else if (difftemp <= 2.5) {
164-
newPWMvalue = 220;
165+
newPWMvalue = pwmMinimumValue + 5*pwmStep;
165166
} else if (difftemp <= 3.0) {
166-
newPWMvalue = 240;
167+
newPWMvalue = pwmMinimumValue + 6*pwmStep;
167168
}
168169
updateFanSpeed(newPWMvalue);
169170
}
@@ -179,7 +180,7 @@ class PWMFanUsermod : public Usermod {
179180
#endif
180181
initTacho();
181182
initPWMfan();
182-
updateFanSpeed(pwmMinimumValue);
183+
updateFanSpeed((minPWMValuePct * 255) / 100); // inital fan speed
183184
initDone = true;
184185
}
185186

@@ -250,6 +251,8 @@ class PWMFanUsermod : public Usermod {
250251
top[FPSTR(_tachoPin)] = tachoPin;
251252
top[FPSTR(_tachoUpdateSec)] = tachoUpdateSec;
252253
top[FPSTR(_temperature)] = targetTemperature;
254+
top[FPSTR(_minPWMValuePct)] = minPWMValuePct;
255+
top[FPSTR(_IRQperRotation)] = numberOfInterrupsInOneSingleRotation;
253256
DEBUG_PRINTLN(F("Autosave config saved."));
254257
}
255258

@@ -280,6 +283,10 @@ class PWMFanUsermod : public Usermod {
280283
tachoUpdateSec = top[FPSTR(_tachoUpdateSec)] | tachoUpdateSec;
281284
tachoUpdateSec = (uint8_t) max(1,(int)tachoUpdateSec); // bounds checking
282285
targetTemperature = top[FPSTR(_temperature)] | targetTemperature;
286+
minPWMValuePct = top[FPSTR(_minPWMValuePct)] | minPWMValuePct;
287+
minPWMValuePct = (uint8_t) min(100,max(0,(int)minPWMValuePct)); // bounds checking
288+
numberOfInterrupsInOneSingleRotation = top[FPSTR(_IRQperRotation)] | numberOfInterrupsInOneSingleRotation;
289+
numberOfInterrupsInOneSingleRotation = (uint8_t) max(1,(int)numberOfInterrupsInOneSingleRotation); // bounds checking
283290

284291
if (!initDone) {
285292
// first run: reading from cfg.json
@@ -302,7 +309,7 @@ class PWMFanUsermod : public Usermod {
302309
}
303310

304311
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
305-
return !top[FPSTR(_enabled)].isNull();
312+
return !top[FPSTR(_IRQperRotation)].isNull();
306313
}
307314

308315
/*
@@ -321,3 +328,5 @@ const char PWMFanUsermod::_tachoPin[] PROGMEM = "tacho-pin";
321328
const char PWMFanUsermod::_pwmPin[] PROGMEM = "PWM-pin";
322329
const char PWMFanUsermod::_temperature[] PROGMEM = "target-temp-C";
323330
const char PWMFanUsermod::_tachoUpdateSec[] PROGMEM = "tacho-update-s";
331+
const char PWMFanUsermod::_minPWMValuePct[] PROGMEM = "min-PWM-percent";
332+
const char PWMFanUsermod::_IRQperRotation[] PROGMEM = "IRQs-per-rotation";

0 commit comments

Comments
 (0)