AV 리시버가 너무 뜨거워서 여름 전에 캐비닛 팬을 추가하고 싶었습니다. 리시버 외부에서 전원이 켜질 때만 작동하는 5-12V DC 소스를 찾으려 했으나 내부에서만 몇 군데 찾을 수 있었습니다. 또한 리시버 전원 차단 후에도 팬이 잠시 더 돌게 하고 싶었는데, 콘덴서 크기 계산이 까다로웠습니다.
실온 24℃, 캐비닛 내부 43℃
아마존의 온도 제어 팬들은 30달러 이상으로 비쌌습니다. 팬, 온도 프로브, 릴레이 정도만 들어있는데 말이죠. 부품 상자를 보니 이미 다 있더군요.
중국산 2달러 아두이노 나노로 간단한 스케치를 작성했습니다. DHT11 온도 센서와 5V DC 릴레이를 추가하니 완벽하게 작동했습니다.
오래된 PC 팬 중 5V에서도 충분히 돌고 200mA 이하인 80mm 2개, 120mm 1개를 찾아 몰렉스 커넥터를 잘라 USB로 배선했습니다. 브레드보드에서 잘 작동해 상태 LED와 과열 경보용 피에조 부저를 추가했고, 작은 프로젝트 박스에 깔끔하게 넣었습니다.
상태 LED: 좌상=전원(녹색), 좌하=온도 정상(녹색), 중앙=팬 작동(주황), 우측=과열(적색)
컨트롤러는 시동 시 POST(자체 진단)를 수행해 모든 팬, LED, 피에조 알람이 작동하는지 확인합니다.
아두이노 스케치:
컨트롤러는 30초간 평균 온도를 측정합니다. 35℉(약 1.7℃) 이상이면 팬이 5분간 켜진 후 다시 체크합니다. 49℃(120℉) 이상이면 알람이 울리며 팬이 계속 돕니다. 알람은 온도가 49℃ 아래로 내려올 때까지 30초마다 울립니다.
실제로는 리시버 켠 후 약 2분 뒤 팬이 켜지고 리시버가 켜진 동안 계속 돕니다. 미디어 센터 전원 끄면 팬이 최소 5분간 돌다가 온도가 35℉ 아래로 내려가면 멈춥니다. 아직 과열 알람은 울리지 않았습니다.
다시 한다면 아두이노 나노를 ATtiny85로, 릴레이를 MOSFET로 대체해 더 작게 만들고 PWM으로 팬 속도 제어까지 추가하고 싶습니다.
코드
FanTempController
// A/V 캐비닛 온도 컨트롤러
// 팬은 10A 릴레이로 제어 (12V PC 팬 또는 5V USB 팬)
// 과열 경보용 피에조 알람
int FANTEMP = 95; // 팬 켜지는 온도 (화씨 95도 ≈ 35℃)
int ALARMTEMP = 120; // 과열 알람 온도 (화씨 120도 ≈ 49℃)
int FANLED = 2;
int TEMPOK = 3;
int ALARMLED = 4;
int ALARMPIN = 7;
#define DHTPIN 8
int FANPIN = 9;
#include "DHT.h"
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const int numReadings = 10;
float avetemp = 0;
float temp = 0;
float checkdelay = 0;
void setup() {
Serial.begin(9600);
Serial.println("Temp Monitor Started");
dht.begin();
pinMode(FANPIN, OUTPUT);
pinMode(ALARMPIN, OUTPUT);
pinMode(ALARMLED, OUTPUT);
pinMode(FANLED, OUTPUT);
pinMode(TEMPOK, OUTPUT);
digitalWrite(FANPIN, HIGH);
digitalWrite(FANLED, HIGH);
digitalWrite(ALARMLED, HIGH);
digitalWrite(TEMPOK, HIGH);
for (int x = 0; x < 5; x++) {
tone(ALARMPIN, 220 * x, 75);
delay(100);
}
Serial.print("Fan Test Started (5 Seconds) ");
for (int x = 0; x < 5; x++) { Serial.print("."); delay(1000); }
Serial.println("Done");
digitalWrite(FANPIN, LOW);
digitalWrite(FANLED, LOW);
digitalWrite(ALARMLED, LOW);
digitalWrite(TEMPOK, LOW);
noTone(ALARMPIN);
}
void loop() {
delay(2000);
temp = 0;
Serial.print("Realtime Temp: \t");
for (int x = 0; x < numReadings; x++) {
float f = dht.readTemperature(true);
Serial.print(f); Serial.print("\t");
temp = f + temp;
delay(3000);
}
Serial.println();
avetemp = temp / numReadings;
Serial.print("Average Temp is "); Serial.println(avetemp);
if (isnan(temp)) { Serial.println("Failed to read from DHT sensor!"); return; }
if (avetemp > ALARMTEMP) {
digitalWrite(ALARMLED, HIGH);
Serial.print("Temperature is over "); Serial.print(ALARMTEMP); Serial.println(", Alarm is on");
for (int x = 0; x < 3; x++) {
tone(ALARMPIN, 660, 1000); delay(500);
tone(ALARMPIN, 440, 1000); delay(500);
}
noTone(ALARMPIN);
checkdelay = 30000;
} else {
digitalWrite(ALARMLED, LOW);
Serial.print("Temperature is under "); Serial.print(ALARMTEMP); Serial.println(", Alarm is off");
checkdelay = 300000;
}
if (avetemp > FANTEMP) {
digitalWrite(FANPIN, HIGH);
digitalWrite(FANLED, HIGH);
digitalWrite(TEMPOK, LOW);
Serial.print("Temperature is over "); Serial.print(FANTEMP);
Serial.print(", Fan is on (for "); Serial.print(checkdelay / 1000 / 60); Serial.println(" minutes)");
delay(checkdelay);
} else {
digitalWrite(FANPIN, LOW);
digitalWrite(FANLED, LOW);
digitalWrite(TEMPOK, HIGH);
Serial.print("Temperature is under "); Serial.print(FANTEMP); Serial.println(", Fan is off");
}
Serial.println(); Serial.println();
}