Power Supply Unit (PSU) คืออะไร
Power Supply Unit (PSU) หรือแหล่งจ่ายไฟ เป็นอุปกรณ์ที่แปลงไฟฟ้ากระแสสลับ (AC) จากเต้าเสียบเป็นไฟฟ้ากระแสตรง (DC) ที่คอมพิวเตอร์ใช้งาน PSU จ่ายแรงดันไฟหลายระดับ ได้แก่ +3.3V สำหรับ RAM และ chipset, +5V สำหรับ USB และ peripherals, +12V สำหรับ CPU, GPU และ drives, -12V สำหรับ legacy devices และ +5V Standby สำหรับ wake-on-LAN
PSU เป็นอุปกรณ์สำคัญที่สุดตัวหนึ่งในคอมพิวเตอร์ PSU คุณภาพต่ำอาจทำให้ระบบ crash, data corruption, component damage หรือในกรณีร้ายแรงอาจเกิดไฟไหม้ การเลือก PSU ที่ดีช่วยให้ระบบเสถียร อายุการใช้งานยาวนาน ประหยัดไฟ และลดเสียงรบกวน
มาตรฐาน 80 PLUS Certification วัด efficiency ของ PSU ได้แก่ 80 PLUS (80% efficiency), 80 PLUS Bronze (82-85%), 80 PLUS Silver (85-88%), 80 PLUS Gold (87-90%), 80 PLUS Platinum (89-92%) และ 80 PLUS Titanium (90-94%) efficiency สูงหมายถึงสูญเสียพลังงานเป็นความร้อนน้อยกว่า ประหยัดค่าไฟมากกว่า
สำหรับ Server และ Data Center PSU ยิ่งสำคัญมากขึ้น ต้องการ redundant PSU (N+1), hot-swappable, high efficiency (Platinum/Titanium) และ remote monitoring ผ่าน IPMI/BMC
ประเภทของ Power Supply และวิธีเลือก
ประเภท PSU และแนวทางเลือกซื้อ
# === Power Supply Types and Selection Guide ===
# 1. Form Factors
# ===================================
# ATX — Standard desktop, 150x86x140mm
# SFX — Small Form Factor, 125x63.5x100mm
# SFX-L — Extended SFX, 125x63.5x130mm
# TFX — Thin Form Factor, slimline cases
# Server — Redundant, hot-swap, various sizes
# 2. Modular Types
# ===================================
# Non-modular — ทุกสายติดตายกับ PSU (ถูกที่สุด)
# Semi-modular — สาย 24-pin และ CPU ติดตาย สายอื่นถอดได้
# Full-modular — ทุกสายถอดได้ (สะอาด จัดสายง่าย)
# 3. Efficiency Rating vs Annual Cost Savings
# ===================================
# ตัวอย่าง: ระบบใช้ไฟ 500W, ไฟฟ้า 5 THB/kWh, ใช้งาน 24/7
#
# Rating Efficiency AC Draw Annual Cost
# 80 PLUS 80% 625W 27,375 THB
# Bronze 85% 588W 25,756 THB
# Gold 90% 556W 24,354 THB
# Platinum 92% 543W 23,784 THB
# Titanium 94% 532W 23,302 THB
#
# Gold vs Bronze saves ~1,400 THB/year per server
# For 10 servers = 14,000 THB/year savings
# 4. Selection Criteria
# ===================================
# Desktop Gaming PC:
# - 650W-850W for mid-range GPU
# - 850W-1000W for high-end GPU (RTX 4090)
# - 80 PLUS Gold minimum
# - Fully modular preferred
#
# Workstation (ML/AI):
# - 1000W-1600W for multi-GPU
# - 80 PLUS Platinum
# - Multiple 12V rails or single strong rail
#
# Server:
# - Redundant PSU (1+1 or 2+1)
# - 80 PLUS Platinum/Titanium
# - Hot-swappable
# - IPMI/BMC monitoring
# - 80% load = sweet spot for efficiency
# 5. Connector Types (ATX 3.0 / PCIe 5.0)
# ===================================
# 24-pin ATX — Motherboard main power
# 8-pin EPS (4+4) — CPU power (1-2 connectors)
# 16-pin 12VHPWR — New GPU connector (up to 600W)
# 8-pin PCIe (6+2) — Legacy GPU power
# SATA power — Storage drives
# Molex 4-pin — Legacy peripherals
# 6. Brand Recommendations (2024-2026)
# ===================================
# Tier A (Best): Corsair RMx/HXi, Seasonic Prime, be quiet! Dark Power
# Tier B (Great): EVGA SuperNOVA, Corsair RM, Seasonic Focus
# Tier C (Good): Thermaltake Toughpower, FSP Hydro
# Avoid: Unknown brands, no certification, very cheap units
echo "PSU selection guide complete"
คำนวณ Wattage ที่ต้องการ
เครื่องมือคำนวณ PSU Wattage
#!/usr/bin/env python3
# psu_calculator.py — Power Supply Wattage Calculator
import json
from dataclasses import dataclass, field
from typing import List, Dict
@dataclass
class Component:
name: str
category: str
tdp_watts: float
quantity: int = 1
class PSUCalculator:
# TDP reference database (approximate watts)
COMPONENTS_DB = {
# CPUs
"i5-13600K": {"category": "cpu", "tdp": 125},
"i7-13700K": {"category": "cpu", "tdp": 125},
"i9-13900K": {"category": "cpu", "tdp": 125},
"i9-14900K": {"category": "cpu", "tdp": 125},
"Ryzen 5 7600X": {"category": "cpu", "tdp": 105},
"Ryzen 7 7800X3D": {"category": "cpu", "tdp": 120},
"Ryzen 9 7950X": {"category": "cpu", "tdp": 170},
"Xeon W-2495X": {"category": "cpu", "tdp": 225},
"EPYC 9654": {"category": "cpu", "tdp": 360},
# GPUs
"RTX 3060": {"category": "gpu", "tdp": 170},
"RTX 3070": {"category": "gpu", "tdp": 220},
"RTX 3080": {"category": "gpu", "tdp": 320},
"RTX 3090": {"category": "gpu", "tdp": 350},
"RTX 4070": {"category": "gpu", "tdp": 200},
"RTX 4080": {"category": "gpu", "tdp": 320},
"RTX 4090": {"category": "gpu", "tdp": 450},
"A100 PCIe": {"category": "gpu", "tdp": 250},
"A100 SXM": {"category": "gpu", "tdp": 400},
"H100 SXM": {"category": "gpu", "tdp": 700},
# Storage
"HDD 3.5": {"category": "storage", "tdp": 8},
"HDD 2.5": {"category": "storage", "tdp": 3},
"SSD SATA": {"category": "storage", "tdp": 3},
"NVMe SSD": {"category": "storage", "tdp": 7},
# Memory
"DDR5 DIMM": {"category": "ram", "tdp": 5},
"DDR4 DIMM": {"category": "ram", "tdp": 4},
# Other
"Case Fans": {"category": "cooling", "tdp": 3},
"AIO 240mm": {"category": "cooling", "tdp": 15},
"AIO 360mm": {"category": "cooling", "tdp": 20},
}
OVERHEAD_PERCENT = 10 # motherboard, USB, etc.
HEADROOM_PERCENT = 20 # recommended headroom
def __init__(self):
self.components: List[Component] = []
def add(self, name: str, quantity: int = 1):
if name in self.COMPONENTS_DB:
info = self.COMPONENTS_DB[name]
self.components.append(Component(
name=name,
category=info["category"],
tdp_watts=info["tdp"],
quantity=quantity,
))
else:
raise ValueError(f"Unknown component: {name}")
return self
def add_custom(self, name: str, category: str, tdp: float, quantity: int = 1):
self.components.append(Component(name, category, tdp, quantity))
return self
def calculate(self):
breakdown = {}
total_tdp = 0
for comp in self.components:
power = comp.tdp_watts * comp.quantity
total_tdp += power
cat = comp.category
breakdown.setdefault(cat, {"components": [], "total_watts": 0})
breakdown[cat]["components"].append({
"name": comp.name,
"quantity": comp.quantity,
"watts": power,
})
breakdown[cat]["total_watts"] += power
overhead = total_tdp * (self.OVERHEAD_PERCENT / 100)
total_with_overhead = total_tdp + overhead
headroom = total_with_overhead * (self.HEADROOM_PERCENT / 100)
recommended = total_with_overhead + headroom
# Round to nearest standard PSU size
standard_sizes = [450, 550, 650, 750, 850, 1000, 1200, 1300, 1600, 2000]
psu_size = next((s for s in standard_sizes if s >= recommended), 2000)
efficiency_at_50 = 0.90 # Gold at 50% load
ac_draw = psu_size * 0.5 / efficiency_at_50 # at 50% load
return {
"component_tdp": round(total_tdp),
"overhead_watts": round(overhead),
"total_estimated": round(total_with_overhead),
"recommended_headroom": round(headroom),
"minimum_psu": round(recommended),
"recommended_psu": psu_size,
"estimated_ac_draw_50pct": round(ac_draw),
"breakdown": breakdown,
}
def print_report(self):
result = self.calculate()
print("=== PSU Wattage Calculator ===\n")
for cat, data in result["breakdown"].items():
print(f"{cat.upper()}: {data['total_watts']}W")
for comp in data["components"]:
print(f" {comp['name']} x{comp['quantity']}: {comp['watts']}W")
print(f"\nComponent TDP Total: {result['component_tdp']}W")
print(f"System Overhead (+{self.OVERHEAD_PERCENT}%): {result['overhead_watts']}W")
print(f"Total Estimated: {result['total_estimated']}W")
print(f"Headroom (+{self.HEADROOM_PERCENT}%): {result['recommended_headroom']}W")
print(f"\nMinimum PSU: {result['minimum_psu']}W")
print(f"Recommended PSU: {result['recommended_psu']}W")
# Gaming PC
calc = PSUCalculator()
calc.add("i7-13700K")
calc.add("RTX 4080")
calc.add("DDR5 DIMM", 2)
calc.add("NVMe SSD", 2)
calc.add("Case Fans", 4)
calc.add("AIO 360mm")
calc.print_report()
# ML Workstation
# calc2 = PSUCalculator()
# calc2.add("Ryzen 9 7950X")
# calc2.add("RTX 4090", 2)
# calc2.add("DDR5 DIMM", 4)
# calc2.add("NVMe SSD", 4)
# calc2.print_report()
ตรวจสอบและ Monitor PSU ด้วย Software
เครื่องมือ monitoring power consumption
#!/usr/bin/env python3
# power_monitor.py — System Power Monitoring
import time
import json
import logging
import subprocess
from datetime import datetime
from pathlib import Path
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("power")
class PowerMonitor:
def __init__(self):
self.readings = []
def get_cpu_power(self):
try:
# Linux: Read RAPL (Running Average Power Limit)
rapl_path = Path("/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj")
if rapl_path.exists():
energy1 = int(rapl_path.read_text().strip())
time.sleep(1)
energy2 = int(rapl_path.read_text().strip())
watts = (energy2 - energy1) / 1_000_000
return round(watts, 1)
except Exception:
pass
# Fallback: use lm-sensors
try:
output = subprocess.getoutput("sensors -j 2>/dev/null")
data = json.loads(output)
for chip in data.values():
for key, val in chip.items():
if "power" in key.lower():
for subkey, subval in val.items():
if "input" in subkey.lower():
return round(subval, 1)
except Exception:
pass
return 0
def get_gpu_power(self):
try:
output = subprocess.getoutput(
"nvidia-smi --query-gpu=power.draw --format=csv, noheader, nounits"
)
powers = [float(p.strip()) for p in output.strip().split("\n") if p.strip()]
return round(sum(powers), 1)
except Exception:
return 0
def get_system_power(self):
# Try IPMI (server)
try:
output = subprocess.getoutput(
"ipmitool sensor | grep -i 'psu\\|power\\|watt'"
)
if output:
for line in output.split("\n"):
parts = line.split("|")
if len(parts) > 1 and "watts" in line.lower():
value = parts[1].strip()
if value.replace(".", "").isdigit():
return round(float(value), 1)
except Exception:
pass
# Estimate from CPU + GPU
cpu = self.get_cpu_power()
gpu = self.get_gpu_power()
overhead = (cpu + gpu) * 0.15 # ~15% for RAM, drives, fans
return round(cpu + gpu + overhead, 1)
def collect(self):
reading = {
"timestamp": datetime.utcnow().isoformat(),
"cpu_watts": self.get_cpu_power(),
"gpu_watts": self.get_gpu_power(),
"system_watts": self.get_system_power(),
}
self.readings.append(reading)
return reading
def monitor_loop(self, interval=5, duration=60):
logger.info(f"Monitoring power for {duration}s (interval: {interval}s)")
end_time = time.time() + duration
while time.time() < end_time:
reading = self.collect()
logger.info(
f"CPU: {reading['cpu_watts']}W | "
f"GPU: {reading['gpu_watts']}W | "
f"System: {reading['system_watts']}W"
)
time.sleep(interval)
return self.summary()
def summary(self):
if not self.readings:
return {}
cpu_watts = [r["cpu_watts"] for r in self.readings if r["cpu_watts"] > 0]
gpu_watts = [r["gpu_watts"] for r in self.readings if r["gpu_watts"] > 0]
sys_watts = [r["system_watts"] for r in self.readings if r["system_watts"] > 0]
def stats(values):
if not values:
return {"avg": 0, "min": 0, "max": 0}
return {
"avg": round(sum(values) / len(values), 1),
"min": round(min(values), 1),
"max": round(max(values), 1),
}
return {
"samples": len(self.readings),
"cpu_watts": stats(cpu_watts),
"gpu_watts": stats(gpu_watts),
"system_watts": stats(sys_watts),
}
def estimate_electricity_cost(self, hours_per_day=24, rate_per_kwh=5.0):
summary = self.summary()
avg_watts = summary.get("system_watts", {}).get("avg", 0)
daily_kwh = avg_watts * hours_per_day / 1000
monthly_kwh = daily_kwh * 30
yearly_kwh = daily_kwh * 365
return {
"avg_watts": avg_watts,
"daily_kwh": round(daily_kwh, 2),
"monthly_kwh": round(monthly_kwh, 1),
"yearly_kwh": round(yearly_kwh, 0),
"monthly_cost_thb": round(monthly_kwh * rate_per_kwh, 0),
"yearly_cost_thb": round(yearly_kwh * rate_per_kwh, 0),
}
# monitor = PowerMonitor()
# monitor.monitor_loop(interval=5, duration=60)
# print(json.dumps(monitor.summary(), indent=2))
# print(json.dumps(monitor.estimate_electricity_cost(), indent=2))
UPS และ Power Protection สำหรับ Server
ระบบป้องกันไฟฟ้าสำหรับ server infrastructure
#!/bin/bash
# ups_setup.sh — UPS Configuration with NUT
set -euo pipefail
# === ติดตั้ง Network UPS Tools (NUT) ===
sudo apt update
sudo apt install -y nut nut-client nut-server
# === ตั้งค่า UPS Driver ===
# /etc/nut/ups.conf
cat << 'CONF' | sudo tee /etc/nut/ups.conf
[myups]
driver = usbhid-ups
port = auto
desc = "APC Smart-UPS 1500"
pollinterval = 5
CONF
# === ตั้งค่า NUT Daemon ===
# /etc/nut/upsd.conf
cat << 'CONF' | sudo tee /etc/nut/upsd.conf
LISTEN 0.0.0.0 3493
MAXAGE 15
CONF
# === ตั้งค่า Users ===
# /etc/nut/upsd.users
cat << 'CONF' | sudo tee /etc/nut/upsd.users
[admin]
password = ups_admin_pass
actions = SET
instcmds = ALL
[monitor]
password = ups_monitor_pass
upsmon master
CONF
# === ตั้งค่า UPS Monitor ===
# /etc/nut/upsmon.conf
cat << 'CONF' | sudo tee /etc/nut/upsmon.conf
MONITOR myups@localhost 1 monitor ups_monitor_pass master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 5
POLLFREQALERT 3
HOSTSYNC 15
DEADTIME 15
NOTIFYMSG ONLINE "UPS %s is on line power"
NOTIFYMSG ONBATT "UPS %s is on battery!"
NOTIFYMSG LOWBATT "UPS %s battery is low!"
NOTIFYMSG FSD "UPS %s: forced shutdown in progress"
NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding"
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
CONF
# === ตั้งค่า NUT Mode ===
echo 'MODE=standalone' | sudo tee /etc/nut/nut.conf
# === Start Services ===
sudo systemctl enable nut-server nut-client nut-monitor
sudo systemctl start nut-server nut-client nut-monitor
# === ตรวจสอบ UPS Status ===
upsc myups@localhost
# Output:
# battery.charge: 100
# battery.runtime: 1800
# input.voltage: 220.0
# output.voltage: 220.0
# ups.load: 35
# ups.status: OL (Online)
# === Monitor Script ===
cat << 'SCRIPT' | sudo tee /usr/local/bin/ups_alert.sh
#!/bin/bash
EVENT=$1
MESSAGE=$2
case $EVENT in
ONBATT)
# Send alert via Slack/Email
curl -X POST "$SLACK_WEBHOOK" \
-d "{\"text\":\"⚠️ UPS on battery! $MESSAGE\"}"
;;
LOWBATT)
curl -X POST "$SLACK_WEBHOOK" \
-d "{\"text\":\"🔴 UPS LOW BATTERY! Shutdown imminent. $MESSAGE\"}"
;;
ONLINE)
curl -X POST "$SLACK_WEBHOOK" \
-d "{\"text\":\"✅ UPS back on line power. $MESSAGE\"}"
;;
esac
SCRIPT
sudo chmod +x /usr/local/bin/ups_alert.sh
echo "UPS configuration complete"
Power Management สำหรับ Data Center
จัดการพลังงานสำหรับ server infrastructure
#!/usr/bin/env python3
# power_management.py — Data Center Power Management
import json
import logging
from datetime import datetime
from typing import Dict, List
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("power_mgmt")
class DataCenterPowerManager:
def __init__(self):
self.racks = {}
self.pue_target = 1.4 # Power Usage Effectiveness
def add_rack(self, rack_id, max_kw=10):
self.racks[rack_id] = {
"max_kw": max_kw,
"servers": [],
"current_kw": 0,
}
def add_server(self, rack_id, server_name, power_watts):
if rack_id not in self.racks:
raise ValueError(f"Rack {rack_id} not found")
rack = self.racks[rack_id]
new_total = rack["current_kw"] + power_watts / 1000
if new_total > rack["max_kw"]:
raise ValueError(
f"Rack {rack_id} capacity exceeded: "
f"{new_total:.1f}kW > {rack['max_kw']}kW"
)
rack["servers"].append({
"name": server_name,
"power_watts": power_watts,
})
rack["current_kw"] = new_total
def calculate_pue(self, it_load_kw, total_facility_kw):
if it_load_kw == 0:
return 0
pue = total_facility_kw / it_load_kw
return round(pue, 2)
def capacity_report(self):
total_capacity_kw = sum(r["max_kw"] for r in self.racks.values())
total_used_kw = sum(r["current_kw"] for r in self.racks.values())
report = {
"timestamp": datetime.utcnow().isoformat(),
"total_racks": len(self.racks),
"total_capacity_kw": total_capacity_kw,
"total_used_kw": round(total_used_kw, 1),
"utilization_pct": round(total_used_kw / max(total_capacity_kw, 1) * 100, 1),
"total_servers": sum(len(r["servers"]) for r in self.racks.values()),
"estimated_monthly_kwh": round(total_used_kw * 24 * 30, 0),
"estimated_monthly_cost_thb": round(total_used_kw * 24 * 30 * 5, 0),
"racks": {},
}
for rack_id, rack in self.racks.items():
report["racks"][rack_id] = {
"capacity_kw": rack["max_kw"],
"used_kw": round(rack["current_kw"], 1),
"utilization_pct": round(rack["current_kw"] / rack["max_kw"] * 100, 1),
"servers": len(rack["servers"]),
"available_kw": round(rack["max_kw"] - rack["current_kw"], 1),
}
return report
def optimization_suggestions(self):
suggestions = []
report = self.capacity_report()
for rack_id, rack_info in report["racks"].items():
if rack_info["utilization_pct"] < 30:
suggestions.append({
"rack": rack_id,
"type": "consolidation",
"message": f"Rack {rack_id} at {rack_info['utilization_pct']}% — consider consolidating servers",
})
elif rack_info["utilization_pct"] > 80:
suggestions.append({
"rack": rack_id,
"type": "capacity",
"message": f"Rack {rack_id} at {rack_info['utilization_pct']}% — nearing capacity limit",
})
if report["utilization_pct"] > 70:
suggestions.append({
"type": "expansion",
"message": "Overall utilization above 70% — plan for capacity expansion",
})
return suggestions
# dc = DataCenterPowerManager()
# dc.add_rack("R01", max_kw=10)
# dc.add_rack("R02", max_kw=10)
# dc.add_server("R01", "web-01", 350)
# dc.add_server("R01", "web-02", 350)
# dc.add_server("R01", "db-01", 500)
# dc.add_server("R02", "gpu-01", 1500)
# report = dc.capacity_report()
# print(json.dumps(report, indent=2))
FAQ คำถามที่พบบ่อย
Q: PSU Watt มากเกินไปเปลืองไฟไหม?
A: ไม่เปลืองไฟ PSU จ่ายไฟตามที่ระบบต้องการ ถ้าระบบใช้ 400W PSU 850W ก็จ่ายแค่ 400W แต่ efficiency จะต่ำกว่าเมื่อ load ต่ำมาก (ต่ำกว่า 20% ของ rated wattage) PSU ทำงาน efficient ที่สุดที่ 40-60% load ดังนั้น PSU ควรมี headroom 20-30% แต่ไม่ต้องใหญ่เกินไป (เช่น ใช้ 300W ซื้อ PSU 1600W ไม่จำเป็น)
Q: 80 PLUS Gold คุ้มค่าไหมเทียบกับ Bronze?
A: คุ้มค่าสำหรับระบบที่เปิด 24/7 เช่น servers, workstations Gold ประหยัดไฟกว่า Bronze ประมาณ 3-5% สำหรับ server 500W เปิด 24/7 ประหยัดได้ประมาณ 100-150 THB/เดือน หรือ 1,200-1,800 THB/ปี PSU Gold มักมีคุณภาพชิ้นส่วนดีกว่าด้วย อายุการใช้งานยาวกว่า สำหรับ PC ที่ใช้แค่วันละ 4-6 ชั่วโมง ผลต่างน้อยมาก Bronze เพียงพอ
Q: UPS ต้องมี capacity เท่าไหร?
A: คำนวณจาก total load (watts) * runtime ที่ต้องการ (minutes) UPS capacity วัดเป็น VA (Volt-Ampere) คูณ power factor 0.6-0.9 ได้ watts สำหรับ server ทั่วไป 500W ต้อง UPS ประมาณ 750-1000VA เพื่อ runtime 5-10 นาที (พอสำหรับ graceful shutdown) สำหรับ home lab แนะนำ 1500VA สำหรับ rack servers แนะนำ 3000VA+ แบบ rack-mount
Q: Redundant PSU จำเป็นไหมสำหรับ Home Lab?
A: ไม่จำเป็นสำหรับ home lab ทั่วไป Redundant PSU (N+1) สำคัญสำหรับ production servers ที่ต้องการ uptime สูง ถ้า PSU ตัวหนึ่งเสีย ตัวที่เหลือรับ load ได้เลย สำหรับ home lab ที่ downtime ชั่วคราวรับได้ ใช้ PSU คุณภาพดีตัวเดียว + UPS เพียงพอ ถ้าใช้ server มือสองที่มี redundant PSU อยู่แล้วก็ใส่ทั้งสองตัวไม่เสียหาย