113 lines
3.2 KiB
Arduino
113 lines
3.2 KiB
Arduino
// GPU Fan Controller — Delta QFR1212GHE (4-pin PWM, 12V)
|
|
// 6 режимов: 1=STOP, 2=STANDBY, 3=LOW, 4=MED, 5=HIGH, 6=FULL(2 мин)
|
|
// RPM читается через тахометр (жёлтый → D2), PWM на синий → D9
|
|
// PWM инвертирован: 0 = стоп, 99 = полная (Delta QFR1212GHE)
|
|
// Фан не гаснет полностью — минимум 1000 (10%)
|
|
|
|
const int FAN_PIN = 9;
|
|
const int TACH_PIN = 2;
|
|
|
|
volatile unsigned long tachPulses = 0;
|
|
unsigned long lastRpm = 0;
|
|
unsigned long lastDataTime = 0;
|
|
|
|
const int MODE_STOP = 10000;
|
|
const int MODE_STANDBY = 8000;
|
|
const int MODE_LOW = 5000;
|
|
const int MODE_MED = 3000;
|
|
const int MODE_HIGH = 2500;
|
|
const int MODE_FULL = 0;
|
|
const int MODE_FULL_TIME = 60000;
|
|
|
|
int currentPWM = MODE_STANDBY;
|
|
unsigned long modeFullStart = 0;
|
|
bool inModeFull = false;
|
|
|
|
char buf[16];
|
|
|
|
void setup() {
|
|
pinMode(FAN_PIN, OUTPUT);
|
|
pinMode(TACH_PIN, INPUT_PULLUP);
|
|
attachInterrupt(digitalPinToInterrupt(TACH_PIN), tachISR, FALLING);
|
|
Serial.begin(115200);
|
|
|
|
// Timer1: Fast PWM, ICR1=10000, prescaler 64 → 10Hz
|
|
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11);
|
|
TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS12);
|
|
ICR1 = 10000;
|
|
OCR1A = MODE_STANDBY;
|
|
lastDataTime = millis();
|
|
lastRpm = millis();
|
|
Serial.println("FAN CONTROLLER READY - modes 1-6 + RPM");
|
|
}
|
|
|
|
void tachISR() { tachPulses++; }
|
|
|
|
void applyPWM(int pwm) {
|
|
if (pwm < MODE_FULL) pwm = MODE_FULL;
|
|
if (pwm > MODE_STOP) pwm = MODE_STOP;
|
|
OCR1A = pwm;
|
|
currentPWM = pwm;
|
|
}
|
|
|
|
void loop() {
|
|
unsigned long now = millis();
|
|
|
|
if (Serial.available()) {
|
|
int n = Serial.readBytesUntil('\n', buf, 15);
|
|
if (n > 0) {
|
|
buf[n] = '\0';
|
|
char c = buf[0];
|
|
|
|
if (c >= '1' && c <= '6') {
|
|
lastDataTime = now;
|
|
inModeFull = false;
|
|
modeFullStart = 0;
|
|
|
|
switch (c) {
|
|
case '1': applyPWM(MODE_STOP); Serial.println("MODE: 1 STOP"); break;
|
|
case '2': applyPWM(MODE_STANDBY); Serial.println("MODE: 2 STANDBY"); break;
|
|
case '3': applyPWM(MODE_LOW); Serial.println("MODE: 3 LOW"); break;
|
|
case '4': applyPWM(MODE_MED); Serial.println("MODE: 4 MED"); break;
|
|
case '5': applyPWM(MODE_HIGH); Serial.println("MODE: 5 HIGH"); break;
|
|
case '6':
|
|
applyPWM(MODE_FULL);
|
|
inModeFull = true;
|
|
modeFullStart = now;
|
|
Serial.println("MODE: 6 FULL (60s)");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (c == 'R' || c == 'r') {
|
|
noInterrupts();
|
|
unsigned long p = tachPulses;
|
|
tachPulses = 0;
|
|
interrupts();
|
|
Serial.print("RPM:"); Serial.println(p * 60);
|
|
}
|
|
|
|
if (c == 's' || c == 'S') {
|
|
Serial.print("PWM:"); Serial.println(currentPWM);
|
|
if (inModeFull) Serial.print("FULL:"); Serial.println((now - modeFullStart) / 1000);
|
|
Serial.print("DATA:"); Serial.println((now - lastDataTime) / 1000);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (inModeFull && (now - modeFullStart >= MODE_FULL_TIME)) {
|
|
applyPWM(MODE_MED);
|
|
inModeFull = false;
|
|
Serial.println("FULL TIMEOUT -> MODE_MED");
|
|
}
|
|
|
|
if (now - lastRpm >= 1000) {
|
|
noInterrupts();
|
|
unsigned long p = tachPulses;
|
|
tachPulses = 0;
|
|
interrupts();
|
|
Serial.print("RPM:"); Serial.println(p * 60);
|
|
lastRpm = now;
|
|
}
|
|
}
|