Raspberry Pi 5で天気を読み上げるスマート目覚ましを作ってみた
スマホのアラーム音で無理やり起こされる朝、つらいですよね。Raspberry Pi 5 を使えば、天気予報を声で教えてくれて、LEDの光で自然に目覚めるスマートアラームが作れます。
この記事では、音声合成による読み上げと LED テープライトの調光を組み合わせた、快適な朝を実現するシステムの作り方を解説します。
完成イメージ
- 設定時刻の30分前からLEDが徐々に明るくなる(疑似日の出)
- 設定時刻に天気予報・気温・曜日を音声で読み上げ
- スピーカーから心地よいチャイム音を再生
必要なもの
| パーツ | 目安価格 | |--------|----------| | Raspberry Pi 5(4GB 以上) | 約10,000円 | | microSD カード(32GB 以上) | 約1,000円 | | USB-C 電源アダプター | 約2,000円 | | スピーカー(3.5mm または Bluetooth) | 約1,000円〜 | | NeoPixel LED テープ(WS2812B)1m | 約800円 | | ロジックレベル変換モジュール | 約200円 | | 5V 電源アダプター(LED用・2A以上) | 約1,000円 |
LED テープライトなしで、音声読み上げだけのシンプル版も作れます。まずは音声だけで試して、あとから LED を追加するのもおすすめです。
STEP 1: 音声合成の環境を準備する
日本語の音声合成には Open JTalk を使います。
sudo apt update
sudo apt install -y open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
音声合成のテスト
echo "おはようございます。今日もいい天気ですね。" | \
open_jtalk \
-m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice \
-x /var/lib/mecab/dic/open-jtalk/naist-jdic \
-ow /tmp/test.wav && \
aplay /tmp/test.wav
スピーカーから日本語が聞こえれば成功です。
音が出ない場合は
sudo raspi-config→ System Options → Audio でスピーカーの出力先を設定してください。
STEP 2: 天気予報 API の準備
OpenWeatherMap の無料アカウントを作成
- OpenWeatherMap にアクセス
- 無料アカウントを作成
- API Keys ページで API キーをコピー
無料プランで月60回/分、1,000回/日のリクエストが可能です。朝1回の取得なら十分です。
API の動作確認
curl "http://api.openweathermap.org/data/2.5/weather?q=Tokyo&appid=YOUR_API_KEY&units=metric&lang=ja"
JSON で天気情報が返ってくれば成功です。
STEP 3: Python 環境を構築する
python3 -m venv ~/smart-alarm
source ~/smart-alarm/bin/activate
pip install requests
LED テープライトも使う場合は追加で以下をインストールします。
pip install rpi_ws281x adafruit-circuitpython-neopixel
STEP 4: 音声読み上げスクリプトを作る
# smart_alarm.py
import requests
import subprocess
import os
from datetime import datetime
# === 設定 ===
API_KEY = "YOUR_API_KEY" # OpenWeatherMap の API キー
CITY = "Tokyo" # 都市名
VOICE_MODEL = "/usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice"
DICT_DIR = "/var/lib/mecab/dic/open-jtalk/naist-jdic"
WAV_FILE = "/tmp/alarm_message.wav"
WEEKDAYS = ["月", "火", "水", "木", "金", "土", "日"]
def get_weather():
"""天気予報を取得する"""
url = (
f"http://api.openweathermap.org/data/2.5/weather"
f"?q={CITY}&appid={API_KEY}&units=metric&lang=ja"
)
try:
res = requests.get(url, timeout=10)
data = res.json()
temp = round(data["main"]["temp"])
temp_max = round(data["main"]["temp_max"])
temp_min = round(data["main"]["temp_min"])
desc = data["weather"][0]["description"]
humidity = data["main"]["humidity"]
return {
"temp": temp,
"temp_max": temp_max,
"temp_min": temp_min,
"desc": desc,
"humidity": humidity,
}
except Exception as e:
print(f"天気情報の取得に失敗: {e}")
return None
def build_message(weather):
"""読み上げメッセージを組み立てる"""
now = datetime.now()
month = now.month
day = now.day
weekday = WEEKDAYS[now.weekday()]
greeting = "おはようございます。"
date_str = f"今日は{month}月{day}日、{weekday}曜日です。"
if weather:
weather_str = (
f"現在の天気は{weather['desc']}、"
f"気温は{weather['temp']}度です。"
f"今日の最高気温は{weather['temp_max']}度、"
f"最低気温は{weather['temp_min']}度の予報です。"
)
# 天気に応じたアドバイス
advice = ""
if "雨" in weather["desc"]:
advice = "傘を忘れずにお持ちください。"
elif weather["temp_max"] >= 30:
advice = "暑くなりそうです。水分をこまめに取りましょう。"
elif weather["temp_min"] <= 5:
advice = "冷え込みそうです。暖かい服装でお出かけください。"
else:
weather_str = "天気情報を取得できませんでした。"
advice = ""
closing = "今日も良い一日をお過ごしください。"
return f"{greeting}{date_str}{weather_str}{advice}{closing}"
def speak(text):
"""テキストを音声に変換して再生する"""
# テキストをファイルに書き出し
text_file = "/tmp/alarm_text.txt"
with open(text_file, "w") as f:
f.write(text)
# Open JTalk で音声合成
subprocess.run([
"open_jtalk",
"-m", VOICE_MODEL,
"-x", DICT_DIR,
"-ow", WAV_FILE,
"-r", "0.9", # 話速(少しゆっくり)
"-fm", "2.0", # 抑揚
text_file,
], check=True)
# 再生
subprocess.run(["aplay", WAV_FILE], check=True)
# 一時ファイル削除
os.remove(text_file)
os.remove(WAV_FILE)
# === メイン処理 ===
if __name__ == "__main__":
print("スマートアラームを実行します")
weather = get_weather()
message = build_message(weather)
print(f"読み上げ内容: {message}")
speak(message)
print("完了")
テスト実行
python smart_alarm.py
スピーカーから天気予報が読み上げられれば成功です。
STEP 5: LED 疑似日の出を追加する(任意)
NeoPixel LED テープを使って、アラーム時刻の30分前から徐々にライトを明るくします。
LED テープの配線
| LED テープ | 接続先 | |-----------|--------| | 5V | 5V 外部電源(Piの5Vピンでは電流不足) | | GND | Pi の GND と外部電源の GND を共有 | | DIN | ロジックレベル変換 → GPIO 18 (Pin 12) |
NeoPixel は 5V ロジックで動作しますが、Pi の GPIO は 3.3V です。ロジックレベル変換モジュールを挟むと確実に動作します。
疑似日の出スクリプト
# sunrise.py
import board
import neopixel
import time
# === 設定 ===
LED_PIN = board.D18
LED_COUNT = 30 # LED の数
SUNRISE_DURATION = 1800 # 30分(秒)
pixels = neopixel.NeoPixel(LED_PIN, LED_COUNT, brightness=0.0, auto_write=True)
def sunrise_effect(duration):
"""暖色で徐々に明るくなる疑似日の出"""
steps = 100
interval = duration / steps
for i in range(steps + 1):
progress = i / steps
# 色の変化: 暗い赤 → オレンジ → 暖かい白
if progress < 0.4:
# 暗い赤からオレンジへ
r = int(80 * (progress / 0.4))
g = int(20 * (progress / 0.4))
b = 0
elif progress < 0.7:
# オレンジから明るいオレンジへ
p = (progress - 0.4) / 0.3
r = 80 + int(120 * p)
g = 20 + int(80 * p)
b = int(20 * p)
else:
# 明るいオレンジから暖かい白へ
p = (progress - 0.7) / 0.3
r = 200 + int(55 * p)
g = 100 + int(120 * p)
b = 20 + int(100 * p)
brightness = progress * 0.8 # 最大80%
pixels.brightness = brightness
pixels.fill((r, g, b))
time.sleep(interval)
if __name__ == "__main__":
print("疑似日の出を開始します(30分間)")
sunrise_effect(SUNRISE_DURATION)
print("完了 — LED をそのまま点灯しています")
STEP 6: 統合スクリプトを作る
LED の疑似日の出 → 音声アラームを一連の流れで実行します。
# alarm_main.py
import subprocess
import sys
print("=== スマートアラーム開始 ===")
# STEP 1: 疑似日の出(30分間)
print("LED 疑似日の出を開始...")
subprocess.Popen([sys.executable, "/home/pi/sunrise.py"])
# STEP 2: 30分後に音声読み上げ
import time
time.sleep(1800)
print("音声アラームを実行...")
subprocess.run([sys.executable, "/home/pi/smart_alarm.py"])
print("=== スマートアラーム完了 ===")
STEP 7: cron でスケジュール設定する
毎朝6:30にLED疑似日の出を開始し、7:00に音声アラームが鳴るようにします。
crontab -e
以下を追加します。
# 毎朝6:30にスマートアラームを開始(LED 30分前 + 7:00に音声)
30 6 * * * /home/pi/smart-alarm/bin/python /home/pi/alarm_main.py >> /home/pi/alarm.log 2>&1
LED テープなしのシンプル版は、音声スクリプトだけを cron に登録します。
# 毎朝7:00に天気読み上げ
0 7 * * * /home/pi/smart-alarm/bin/python /home/pi/smart_alarm.py >> /home/pi/alarm.log 2>&1
カスタマイズのヒント
- 都市の変更:
CITY = "Osaka"のように変更すれば、他の都市の天気を取得できます - 読み上げ速度:
-rオプションの値を変更します(0.5=ゆっくり、1.5=速い) - BGM の追加:
aplayの前にお気に入りの音楽ファイルを再生するコードを追加できます - 曜日ごとの変更: 平日と休日でアラーム時刻や内容を変えることも可能です
トラブルシューティング
| 症状 | 原因と対処 |
|------|-----------|
| 音が出ない | raspi-config → Audio で出力先を確認 |
| 天気取得に失敗する | API キーの設定を確認。アカウント作成直後は有効化まで数時間かかる場合あり |
| LED が点灯しない | 外部5V電源の接続を確認。GND がPiと共有されているか確認 |
| LED の色がおかしい | ロジックレベル変換モジュールの接続を確認 |
毎朝「今日の天気は晴れ、最高気温は22度です」と教えてもらえるだけで、朝の準備がぐっとスムーズになります。まずは音声読み上げだけのシンプル版から始めてみてください。