技術

ML110 G7のファンを静かにした

今更感漂うネタですが。

サーバ用として去年ML110 G7を買ったけどなかなか出番が無くてずっと放置してた。
ずっと使ってるPowerEdge SC440がまだまだ快調なので、出番が来たというわけではないけど、購入時から予定していたファンの静音化をやってみた。
(SC440はとても静かだし安定してるし名機だと思う。5年ぐらい使っててファンの異音により電源を一度交換してるけど。)

静音化対象はリアファンとCPUファン。
既存のファンを活かす方向で。

最初、マザボから出力されるPWMをarduino(Da Vinci 32U)で読み取って、それを半分にしてファンに送るスケッチを書いたけど、手持ちの材料ではどうもマザボからarduinoに物理的に配線するのが難しそうだったので、読み取りは無しにして単に30%固定のPWMをファンに送るようにした。

#define PWM_W0 9
#define PWM_W1 6

void setup()
{
  // 30%固定で出力
  analogWrite(PWM_W0, 85);
  analogWrite(PWM_W1, 85);
}

void loop()
{
  
}

PWM_W0のピンにリアファンの青線を、PWM_W1のピンにCPUファンの青線を繋いだ。
ファンが認識可能なPWMの周波数の範囲内にarduinoでanalogWriteしたときの周波数が含まれていたはず(去年確認した記憶が)なので、PWM固定にするだけだったらこれだけで多分大丈夫。
実際に使ってみたけどかなり静かになった。

以下は、最初に書いたバージョン。
PWMを読み取って半分にして出力する。
他のarduinoのPWMを読み取ってデューティ比を求めれたのは確認したけど、G7実機では試してない。
PWM_R0のピンにマザボからのリアファンのPWMを、PWM_R1のピンにマザボからのCPUファンのPWMを入力し、
PWM_W0のピンからリアファンの青線へ、PWM_W1のピンからCPUファンの青線へPWMを出力することを想定している。
PWM出力を定期的にシリアルポートに出力するようになってるので、サーバ側で回転数を監視することも可能。

// PIN 8, 9, 6, 12
#define PWM_R0 8
#define PWM_W0 9
#define PWM_R1 12
#define PWM_W1 6
#define PWM_DENOM0 2
#define PWM_DENOM1 2
#define SUM_STEP 10

int g_step = 0;
int g_read_pins[] = {PWM_R0, PWM_R1};
int g_write_pins[] = {PWM_W0, PWM_W1};
unsigned char g_pwm_denoms[] = {PWM_DENOM0, PWM_DENOM1};
unsigned long g_duties[] = {0, 0};
unsigned long g_sum_counts[] = {0, 0};

void PWMRead(int pinID)
{
  unsigned long us_low, us_high, duty;
  
  int pin = g_read_pins[pinID];
  
  us_low = pulseIn(pin, LOW, 100000);
  us_high = pulseIn(pin, HIGH, 100000);
  us_low = pulseIn(pin, LOW, 100000);
  duty = (us_high * 255) / (us_low + us_high);

  if (duty < 256) {
    g_duties[pinID] += duty;
    g_sum_counts[pinID]++;
  }
}

void PWMWrite(int pinID)
{
  if (g_sum_counts[pinID] > 0) {
    unsigned char pwm = (g_duties[pinID] / g_sum_counts[pinID]) / g_pwm_denoms[pinID];
    analogWrite(g_write_pins[pinID], pwm);
    
    Serial.print("Output: ");
    Serial.print(pinID);
    Serial.print(" ");
    Serial.println(pwm);
  } else {
    Serial.print("Can't calc avg: ");
    Serial.println(pinID);
  }
  g_duties[pinID] = 0;
  g_sum_counts[pinID] = 0;
}

void setup()
{
  Serial.begin(9600);
  // とりあえず最初は50%で出力
  analogWrite(PWM_W0, 127);
  analogWrite(PWM_W1, 127);
}

void loop()
{
  PWMRead(0);
  PWMRead(1);
  
  if (g_step++ > SUM_STEP) {
    PWMWrite(0);
    PWMWrite(1);
    g_step = 0;
  }
  
  delay(100);
}

コメントを残す

メールアドレスが公開されることはありません。



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください