Raspberry Pi 5で家の電気代を見える化してみた
「電気代が先月より高いけど、何が原因かわからない」——そんな経験はありませんか? Raspberry Pi 5 と CT センサーを使えば、家庭の消費電力をリアルタイムで「見える化」できます。
この記事では、消費電力の計測からグラフでの可視化まで、電力モニタリングシステムの作り方を解説します。
完成イメージ
- 家庭の消費電力をリアルタイムで計測
- 1分ごとにデータを記録
- ブラウザでグラフを確認
- 時間帯別・日別の消費電力を比較
必要なもの
| パーツ | 目安価格 | |--------|----------| | Raspberry Pi 5(4GB 以上) | 約10,000円 | | microSD カード(32GB 以上) | 約1,000円 | | USB-C 電源アダプター | 約2,000円 | | CT センサー(SCT-013-030 / 30A対応) | 約1,000円 | | MCP3008(AD コンバーター) | 約500円 | | 分圧抵抗 10kΩ × 2 | 約20円 | | バーデン抵抗 33Ω | 約10円 | | 電解コンデンサ 10μF | 約20円 | | ブレッドボード+ジャンパーワイヤー | 約500円 |
安全に関する重要な注意: CT センサーはケーブルの外側にクランプするだけで電流を計測できるため、配線に直接触れる必要はありません。ただし分電盤の作業を行う場合は、感電に十分注意してください。不安な場合は電気工事士に相談することをおすすめします。
STEP 1: CT センサーの仕組みを理解する
CT(Current Transformer)センサーは、ケーブルを流れる電流が作る磁場を検知して、電流値に比例した小さな電流を出力するセンサーです。
[分電盤のケーブル] → (磁場) → [CTセンサー] → 微小な交流電流 → [計測回路] → [Raspberry Pi]
SCT-013-030 の場合、30A の電流が流れると 1V の出力が得られます。
STEP 2: SPI を有効にする
MCP3008 を使用するため、SPI を有効にします。
sudo raspi-config
Interface Options → SPI → Yes → Finish → 再起動
sudo reboot
STEP 3: 計測回路を組む
回路の概要
Raspberry Pi の GPIO はマイナス電圧を受け付けないため、CT センサーの交流出力にバイアス電圧を加えて、0V 〜 3.3V の範囲に収める必要があります。
回路図
3.3V ─── [10kΩ] ──┬── MCP3008 CH0
│
GND ──── [10kΩ] ──┘
│
CTセンサー出力 ─ [33Ω] ─┘
│
[10μF コンデンサ]
│
GND
各部品の役割
| 部品 | 役割 | |------|------| | 10kΩ × 2(分圧) | 1.65V のバイアス電圧を作る | | 33Ω(バーデン抵抗) | CT センサーの電流出力を電圧に変換 | | 10μF コンデンサ | ノイズの除去 |
MCP3008 の配線
| MCP3008 ピン | 接続先 | |-------------|--------| | VDD (Pin 16) | 3.3V | | VREF (Pin 15) | 3.3V | | AGND (Pin 14) | GND | | CLK (Pin 13) | GPIO 11 (SCLK) | | DOUT (Pin 12) | GPIO 9 (MISO) | | DIN (Pin 11) | GPIO 10 (MOSI) | | CS (Pin 10) | GPIO 8 (CE0) | | DGND (Pin 9) | GND | | CH0 (Pin 1) | 計測回路の出力 |
STEP 4: Python 環境を構築する
python3 -m venv ~/power-monitor
source ~/power-monitor/bin/activate
pip install spidev flask matplotlib
STEP 5: 電力計測スクリプトを作る
キャリブレーション用スクリプト
まず、センサーの出力値を確認して補正係数を調整します。
# calibrate.py
import spidev
import time
import math
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1350000
def read_adc(channel=0):
"""MCP3008 から値を読み取る"""
adc = spi.xfer2([1, (8 + channel) << 4, 0])
return ((adc[1] & 3) << 8) + adc[2]
def measure_current(samples=1000):
"""RMS 電流を計算する"""
sum_squared = 0
for _ in range(samples):
raw = read_adc(0)
# 1.65V バイアスを引く(ADC中央値 = 512)
voltage = (raw - 512) * 3.3 / 1024
# バーデン抵抗 33Ω → 電流換算
# SCT-013-030: 30A = 1V → 係数 = 30
current = voltage * 30
sum_squared += current * current
time.sleep(0.001) # 1ms 間隔
rms_current = math.sqrt(sum_squared / samples)
return rms_current
print("電流のキャリブレーション")
print("家電を ON/OFF して値の変化を確認してください")
print("-" * 40)
while True:
current = measure_current()
power = current * 100 # 日本の家庭用: 100V
print(f"電流: {current:.2f}A / 消費電力: {power:.0f}W")
time.sleep(2)
python calibrate.py
家電を ON/OFF して値が変化することを確認します。
本番用 計測・記録スクリプト
# power_monitor.py
import spidev
import time
import math
import csv
import os
from datetime import datetime
# === 設定 ===
INTERVAL = 60 # 記録間隔(秒)
CSV_FILE = "power_log.csv"
VOLTAGE = 100 # 家庭用電圧(日本: 100V)
CT_RATIO = 30 # CTセンサーの変換比
BURDEN_RESISTANCE = 33 # バーデン抵抗(Ω)
# === SPI 初期化 ===
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1350000
def read_adc(channel=0):
adc = spi.xfer2([1, (8 + channel) << 4, 0])
return ((adc[1] & 3) << 8) + adc[2]
def measure_power(samples=2000):
"""RMS電流を計測し、消費電力を算出する"""
sum_squared = 0
for _ in range(samples):
raw = read_adc(0)
voltage = (raw - 512) * 3.3 / 1024
current = voltage * CT_RATIO
sum_squared += current * current
time.sleep(0.0005)
rms_current = math.sqrt(sum_squared / samples)
power_watts = rms_current * VOLTAGE
return round(rms_current, 3), round(power_watts, 1)
def log_data(timestamp, current, power):
"""CSV にデータを記録する"""
file_exists = os.path.exists(CSV_FILE)
with open(CSV_FILE, "a", newline="") as f:
writer = csv.writer(f)
if not file_exists:
writer.writerow(["timestamp", "current_A", "power_W"])
writer.writerow([timestamp, current, power])
# === メインループ ===
print("電力モニタリングを開始します")
print(f"記録間隔: {INTERVAL}秒 / 保存先: {CSV_FILE}")
print("-" * 50)
while True:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
current, power = measure_power()
log_data(timestamp, current, power)
print(f"[{timestamp}] {current}A / {power}W")
time.sleep(INTERVAL)
STEP 6: Web ダッシュボードを作る
# power_dashboard.py
from flask import Flask, render_template_string
import csv
import os
from datetime import datetime, timedelta
app = Flask(__name__)
CSV_FILE = "power_log.csv"
ELECTRICITY_RATE = 31 # 電気料金単価(円/kWh)目安
HTML = """
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>電力ダッシュボード</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body { font-family: sans-serif; max-width: 960px; margin: 0 auto; padding: 20px; background: #f5f5f5; }
h1 { color: #1b4332; }
.cards { display: flex; gap: 16px; flex-wrap: wrap; }
.card { background: #fff; border-radius: 12px; padding: 20px; flex: 1; min-width: 200px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08); text-align: center; }
.card .value { font-size: 2.2em; font-weight: bold; color: #2d6a4f; }
.card .label { color: #666; font-size: 0.9em; margin-top: 4px; }
.chart-card { background: #fff; border-radius: 12px; padding: 20px; margin: 16px 0;
box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
</style>
</head>
<body>
<h1>電力モニタリング</h1>
<div class="cards">
<div class="card">
<div class="value">{{ current_power }} W</div>
<div class="label">現在の消費電力</div>
</div>
<div class="card">
<div class="value">{{ today_kwh }} kWh</div>
<div class="label">今日の使用量</div>
</div>
<div class="card">
<div class="value">{{ today_cost }} 円</div>
<div class="label">今日の電気代(目安)</div>
</div>
<div class="card">
<div class="value">{{ month_cost }} 円</div>
<div class="label">今月の電気代(目安)</div>
</div>
</div>
<div class="chart-card">
<h2>24時間の消費電力推移</h2>
<canvas id="powerChart"></canvas>
</div>
<script>
new Chart(document.getElementById("powerChart"), {
type: "line",
data: {
labels: {{ timestamps | tojson }},
datasets: [{
label: "消費電力 (W)",
data: {{ powers | tojson }},
borderColor: "#c1121f",
backgroundColor: "rgba(193, 18, 31, 0.1)",
fill: true,
tension: 0.3,
}]
},
options: { responsive: true, scales: { y: { beginAtZero: true } } }
});
</script>
</body>
</html>
"""
def load_data():
rows = []
if os.path.exists(CSV_FILE):
with open(CSV_FILE) as f:
rows = list(csv.DictReader(f))
return rows
@app.route("/")
def dashboard():
rows = load_data()
# 現在の消費電力
current_power = rows[-1]["power_W"] if rows else "0"
# 今日のデータ
today = datetime.now().strftime("%Y-%m-%d")
today_rows = [r for r in rows if r["timestamp"].startswith(today)]
today_kwh = round(sum(float(r["power_W"]) for r in today_rows) / 60 / 1000, 2) if today_rows else 0
today_cost = round(today_kwh * ELECTRICITY_RATE)
# 今月のデータ
month = datetime.now().strftime("%Y-%m")
month_rows = [r for r in rows if r["timestamp"].startswith(month)]
month_kwh = round(sum(float(r["power_W"]) for r in month_rows) / 60 / 1000, 2)
month_cost = round(month_kwh * ELECTRICITY_RATE)
# 24時間グラフ用データ
recent = rows[-1440:] # 直近24時間(1分間隔)
timestamps = [r["timestamp"][-8:-3] for r in recent] # HH:MM
powers = [float(r["power_W"]) for r in recent]
return render_template_string(
HTML,
current_power=current_power,
today_kwh=today_kwh,
today_cost=today_cost,
month_cost=month_cost,
timestamps=timestamps,
powers=powers,
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
実行
# 2つのターミナルで実行
python power_monitor.py # データ記録
python power_dashboard.py # ダッシュボード
ブラウザで http://raspberrypi.local:8080 にアクセスするとダッシュボードが表示されます。
STEP 7: 自動起動を設定する
sudo nano /etc/systemd/system/power-monitor.service
[Unit]
Description=Power Monitor
After=network.target
[Service]
ExecStart=/home/pi/power-monitor/bin/python /home/pi/power_monitor.py
WorkingDirectory=/home/pi
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
sudo systemctl enable power-monitor
sudo systemctl start power-monitor
ダッシュボード用のサービスも同様に作成します。
sudo nano /etc/systemd/system/power-dashboard.service
[Unit]
Description=Power Dashboard
After=network.target
[Service]
ExecStart=/home/pi/power-monitor/bin/python /home/pi/power_dashboard.py
WorkingDirectory=/home/pi
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
sudo systemctl enable power-dashboard
sudo systemctl start power-dashboard
電気代の節約ポイント
データが溜まってくると、以下のような発見があるはずです。
- 待機電力の大きい家電: 常に 5〜10W 消費している家電は、使わないときコンセントを抜く
- 電力のピーク時間帯: エアコンと電子レンジを同時に使う時間帯を避ける
- エアコンの設定温度: 1度変えると消費電力がどれくらい変わるか実測できる
- 不在時の無駄: 外出中に想定外の電力消費がないか確認する
電力モニタリングを始めた家庭では、意識が変わるだけで月10〜15%の電気代削減に成功しているデータもあります。
トラブルシューティング
| 症状 | 原因と対処 |
|------|-----------|
| 値が常に 0 | CT センサーがケーブルにしっかりクランプされているか確認。SPI が有効か確認 |
| 値が異常に大きい | キャリブレーション係数を調整。バーデン抵抗の値を確認 |
| 値がマイナスになる | バイアス電圧(中央値 512)のずれ。raw - 512 の 512 を実測値に合わせる |
| ノイズが多い | コンデンサの接続を確認。サンプル数を増やす |
「見える化」は節約の第一歩です。実際の数字を見ると、「あの家電、こんなに電気を使っていたのか」という発見が必ずあります。データに基づいた省エネで、家計を守りましょう。