2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

UM690に空冷機能を追加して実質UM690S化する

Last updated at Posted at 2023-11-14

前置き

久々の投稿がこれになったけど、仕方ないんや。
MinisforumのUM690に後継機(というか機能改善)のUM690Sが出たのが悪いんや

Minisforumは、割と性能の良いミニPCをお手頃価格で出している会社です。
で、前々からセカンドPCほしいなーと思ってて、数ヶ月前にUM690という製品を購入したのですが、この製品 M.2(SSD)が裏面にあるため、CPUファンの恩恵を受けれないんですよ。
ちゃんとヒートシンクはあるんで普段遣いでは困らないんですが、ちょっと負荷の高いゲームなどを実行すると熱暴走でPCが落ちたりします(CPU側冷却は問題なくて、M.2側の冷却が能力不足な感じです)

なので、物理的にDCファンつければ直るだろうけどちょっとめんどくさいなーと思って今まで放置していました。
でも、公式から空冷対応版がでちゃって悔しい(悲しい)ので自力でUM690に空冷機能を追加して、ついでにoLEDで温度表示もつけちゃおうというのをやりました。

出来たのがこちら。
2023-11-14 14.45.41.jpg

作り方

Fusion360で下につけるケースをデザインする。

stlファイルはこちら

Amazonで良さげなDCファンを探しつつ、裏面取付のSSDもそのまま使えるようにしつつ、ちょこちょとっとデザインを修正しつつ
DCファンは、Amazonのブロアファン2個入りを使用。

image.png

あと、温度も取得したかったので、サーミスタもAmazonでポチっておきました。
DCファンの回転数制御と温度管理はいえに転がってた Seeed XIAO nRF52840を使用(arduinoで小さくて収まればなんでもいいと思う)

書き忘れてた。
OLED液晶はamazonで こちらのを使ってます。
サーミスタもamazonで こちらを使ってます(100Kの方)

で、3Dプリンタで召喚して、その間に制御回路づくり(というほどのものでもないけど)

KiCADで回路図をカキカキ。
ショットキーとか各種抵抗やコンデンサなどはざっくり適当です。(ネットから情報拾って書き直しただけなので保証できません)
BSS138とかは秋月で25個パックとかで売ってるので入手しやすいと思うけど、リミット300mAなので、もうちょい余裕あったほうがいいのかもです(DCファンが0.1Aを2台なのでいけるっちゃいける?)
image.png

で、あとはユニバーサル基板を適当に切ってハンダして回路作ったら3Dプリンタで作ったガワに組み込み。

2023-11-14 14.50.07.jpg

あとは、蓋をして制御プログラムの作成。

Arduino IDEでコードカキカキ(設定などは割愛。ぐぐってくだせぇ)

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16

const int fanPin = A0;
const int tempPin = A1;

const float Vref = 3.3; // 基準電圧 (3.3V と仮定)
const float Rfixed = 100000; // 分圧抵抗の値 (100KΩ)
const float B = 3950; // B 定数
const float Tnominal = 298.15; // ノミナル温度 25℃ をケルビンで表したもの
const float Rnominal = 100000; // ノミナル抵抗値 (100KΩ)

const int fanSpeedMin = 190;
const int fanSpeedMax = 255;
const float tempMin = 35.0;
const float tempMax = 55.0;
const float tempThresholdOn = tempMin + 8; // ファンがオンになる温度
const float tempThresholdOff = tempMin; // ファンがオフになる温度
bool fanOn = false; // ファンの状態を追跡するフラグ

int fanSpeed = fanSpeedMin;


void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  // Clear the buffer
  display.clearDisplay();
  display.display();

  pinMode(fanPin, OUTPUT);
  pinMode(tempPin, INPUT);
  analogWrite(fanPin, fanSpeedMax);

  delay(2000); // Pause for 2 seconds
}

void loop() {
  float temperature = readTemperature(); // 温度を読み取る

  fanSpeed = calculateFanSpeed(temperature);
  analogWrite(fanPin, fanSpeed);

  drawOLED(temperature, fanSpeed);  
  delay(1000);
}

float readTemperature() {
  int analogValue = analogRead(tempPin); // アナログピンから値を読み取る
  float Vout = (analogValue / 1023.0) * Vref; // 電圧へ変換
  float Rthermistor = Rfixed * (Vref / Vout - 1); // サーミスタの抵抗値を計算
  float lnR = log(Rthermistor / Rnominal); // サーミスタの抵抗値の自然対数を計算
  float T = (1 / (1/Tnominal + lnR/B)); // 温度を計算 (ケルビン単位)
  float temperature = T - 273.15; // ケルビンを摂氏に変換
  return temperature;
}



void drawOLED(float temperature, int fanSpeed) {
  display.clearDisplay();

  display.setTextSize(2);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  display.print(F("Temp:"));
  display.print(temperature, 1);
  display.println(F("C"));
  display.print(F("Fan :"));
  if (fanSpeed == 0) {
    display.println(F("OFF"));
  }else{
    int fanPersent = map(fanSpeed, 190, 255, 10, 100);
    display.print(fanPersent);
    display.println(F("%"));
  }
  display.display();
}

// 温度に基づいてファンスピードを指数関数的に計算する
int calculateFanSpeed(int temperature) {
  if (temperature >= tempThresholdOn) {
    fanOn = true;
  } else if (temperature <= tempThresholdOff) {
    fanOn = false;
  }

  if (fanOn) {
    // 温度が55度以上の場合は255を返す
    if (temperature > tempMax) {
      return fanSpeedMax;
    }
    // 温度が40度から55度の間の場合、指数関数的な増加を計算する
    float normalizedTemp = float(temperature - tempMin) / (tempMax - tempMin);
    return fanSpeedMin + (fanSpeedMax - fanSpeedMin) * pow(normalizedTemp, 2); // 2乗で指数的に増加
  }else{
    return 0;
  }
}

で、XIAOに書き込みして動作チェックして完成!

完成したのがこちら

2023-11-14 14.45.41.jpg
2023-11-14 14.46.45.jpg
2023-11-14 14.46.57.jpg
2023-11-14 14.48.55-1.jpg

うん、満足!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?