今回は、ボタンを押したら、
地元の天気予報を喋ってもらおうと思います。
楽しそうだったら作ってみて♪
この記事では以下が学べます。
- ボタン制御
- スピーカー出力
- Python
- WebAPI(外部情報取得)
- 音声合成(発話)
やりたいこと
・ボタンを押したら、
・地元の天気予報をスピーカーから喋らせる
システム構成図
![](https://canmakewakuwaku.com/wp-content/uploads/2021/03/image-4-1024x571.png)
やることリスト
上記の「やりたいこと」をみて、
どんな作業が必要か、自分で項目を考えてみてください。
これを考えることで、「プログラミング的思考」が身に付いていきます。
作業項目 | 備考 |
部品の準備 | |
ボタンが押されたことを判断する | |
天気予報の情報(文字列)の取得 | WebAPI |
文字列を音声に変換し、スピーカーから音声出力 | 音声合成 |
部品の準備
今回のシステムに必要な部品です。
不足している部品があれば購入下さい。
部品名 | 備考 |
Raspberry Pi | 別途、電源・SDカード・HDMIケーブルが必要です。 |
ブレッドボード(※1) | |
ジャンパー線(※1) | オスーメス:2本 |
ボタン(※1) | タクトスイッチ:1個 |
スピーカー | ダイソーのUSBミニスピーカー(300円)がお薦めです。 |
購入に必要な部品を、
Raspberry Pi 関連に記載しています。
※1)「電子工作キット」内に全て含まれています。
ラズパイは、電源を入れただけでは起動しません。
ラズパイの起動手順の記事を参照ください。
ボタンが押されたことを判断する
回路
回路図
![](https://canmakewakuwaku.com/wp-content/uploads/2021/03/image-7.png)
回路図の説明をします。
ボタンが押されていない時は、
ラズパイ内部のプルダウン(端子とグランドの間に抵抗を入れて接続)を使うことで、
電圧0Vが GPIO 24の端子に入り、GPIO 24の端子は “Low”と判断します。
ボタンが押された時は、
電圧3.3Vが GPIO 24の端子に入り、GPIO 24の端子は “High”と判断します。
配線図
![](https://canmakewakuwaku.com/wp-content/uploads/2021/03/image-8-1024x630.png)
部品の説明
ブレッドボード
ブレッドボードは、ソケット(穴)に部品を挿し込むだけで簡単に電子回路が作れる便利なものです。
各ソケットは、薄い緑色の線の方向に内部で繋がっています。
なので、部品とジャンパー線、部品と部品が繋がっていなくても、電気が流れます。
タクトスイッチ
スイッチを押すと、同じ側面に付いた足どうしが内部で繋がり、電流が流れます。
反対の側面に付いた足どうしは、常に内部で繋がっているので、電流は流れっ放しになります。
ソフト
ピンの制御にRPi.GPIOパッケージを使用する為、以下コマンドでインストールする。
sudo pip3 install rpi.gpio
プログラム
以下ディレクトリ通り、ディレクトリとファイルを作成する。
この章では、以下赤字のファイルを修正する。
/home/pi/work/weather/
└app.py
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import sys
# LED_GPIO 変数に 24をセット
SW_GPIO = 24
# GPIO.BCMを設定することで、GPIO番号で制御出来るようになります。
GPIO.setmode(GPIO.BCM)
# GPIO.INを設定することで、入力モードになります。
# pull_up_down=GPIO.PUD_DOWNにすることで、内部プルダウンになります。
GPIO.setup(SW_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
# ボタン押し / 離し 動作確認用コード
while True:
try:
# GPIO24の値を読み込み、その値を出力します。
# ボタンを押すと"1"(High)、離すと"0"(Low)が表示されます。
print(f'button: {GPIO.input(SW_GPIO)}')
time.sleep(1) # 1秒間待つ
# Ctrl+Cキーを押すと処理を停止
except KeyboardInterrupt:
# ピンの設定を初期化
# この処理をしないと、次回 プログラムを実行した時に「ピンが使用中」のエラーになります。
GPIO.cleanup()
sys.exit()
実行
コマンドラインから、先程作成した app.py のディレクトリに移動し、
以下コマンドでプログラムを実行する。
python3 app.py
ボタンを押していないと、
1秒周期で
“button: 0”
が表示され、
ボタンを押すと、
“button: 1”
が表示されます。
プログラムを終了する場合は、
Ctrl+Cキー を押すと終了します。
天気予報の取得
今回は、インターネットから天気予報の情報を取得するサービスとして、
OpenWeatherMap を使用します。
無料プランの特徴
・5日後までの3時間毎の天気予報を取得可能
・1分間に天気予報を取得出来るのは60回
API keyの取得
OpenWeatherMapのAPIを使用する為には、API key を取得する必要があります。
API keyとは、APIを利用する為の認可証だと思ってください。
API keyを取得するには、
以下OpenWeatherMapの「Create New Account」URLにアクセスし、
アカウントを作成します。
https://home.openweathermap.org/users/sign_up
![](https://canmakewakuwaku.com/wp-content/uploads/2021/04/weather_account.png)
アカウント作成後、
●「How and where will you use our API?」というダイアログが出ます。
記入してもしなくても(cancelでも)大丈夫です。
●先程登録したメールアドレス宛に
表題:「OpenWeatherMap Account confirmation」のメールが届きます。
メールの中ほどの、「Verify your email」ボタンを押すと、メールでの認証が完了します。
上記のメール認証までが完了後、
以下画面の「API keys」タブを押すと、API keyが表示されます。
![](https://canmakewakuwaku.com/wp-content/uploads/2021/04/weather_apikey.png)
このAPI keyは、プログラムで使用するので、メモしておいてください。
プログラム
以下ディレクトリ通り、ディレクトリとファイルを作成する。
この章では、以下赤字のファイルを修正する。
/home/pi/work/weather/
└weather.py
以下コマンドでラズパイにrequestsをインストールする。
pip install requests
weather.py
# -*- coding: utf-8 -*-
import requests
WEATHER_API_KEY = '{上記で取得した API key を入力}'
# 地元の都市名を入れる
WEATHER_CITY_NAME = 'Tokyo'
def get_weather():
base_url = 'http://api.openweathermap.org/data/2.5/weather'
url = f'{base_url}?q={WEATHER_CITY_NAME}&appid={WEATHER_API_KEY}'
# HTTP通信用ライブラリを使って、openweatherサーバから情報を取得する。
response = requests.get(url)
if response.status_code != requests.codes.ok:
return None
# json文字列を辞書に変換
data = response.json()
temp = round(data["main"]["temp"] - 273.15, 1)
weather = {
'city_name': WEATHER_CITY_NAME,
'weather': f'{data["weather"][0]["main"]}',
'temperature': f'{temp}度',
}
return weather
if __name__ == '__main__':
weather = get_weather()
if weather != None:
print(f'都市名: {weather["city_name"]}')
print(f'天気: {weather["weather"]}')
print(f'温度: {weather["temperature"]}')
実行
コマンドラインから、先程作成した weather.py のディレクトリに移動し、
以下コマンドでプログラムを実行する。
python3 weather.py
結果として、以下のような値が表示されます。
都市名: Tokyo 天気: Clouds 温度: 15.5度
参考
地元の都市名を探す
OpenWeatherMapで天気予報が取得出来る都市は、
以下URLの「city.list.json.gz」ファイルから探すことが出来ます。
http://bulk.openweathermap.org/sample/
プログラム中の WEATHER_CITY_NAME = ‘Tokyo’
の右側の都市名を変更すると、その都市の天気情報が取得出来ます。
OepnWeather API仕様
本プログラム中で使用しているOpenWeather APIの仕様は、
以下URLから知ることが出来ます。
https://openweathermap.org/current
本APIで取得出来る情報は、
天気や温度以外にも、
湿度、気圧、風速なども取得出来ますので、
色々試してみてください。
文字列を音声に変換し、スピーカーから音声出力
今回は、無料の音声合成ソフトウェアである、
「Open JTalk」を使って、文字列を音声データに変換します。
スピーカーから音を出す方法が分からなければ、以下記事を参照ください。
Open JTalkのインストール
sudo apt install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
プログラム
以下ディレクトリ通り、ディレクトリとファイルを作成する。
この章では、以下赤字のファイルを修正する。
/home/pi/work/weather/
└talk.py
talk.py
# -*- coding: utf-8 -*-
import subprocess
DICT_PATH = '/var/lib/mecab/dic/open-jtalk/naist-jdic/'
VOICE_PATH = '/usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice'
def talk(text: str):
with open('talk.txt', 'w') as f:
f.write(text)
subprocess.run(['open_jtalk', '-x', DICT_PATH, '-m', VOICE_PATH, '-ow', 'talk.wav', 'talk.txt'])
subprocess.run(['aplay', 'talk.wav'])
if __name__ == '__main__':
talk('布団が吹っ飛んだ')
実行
コマンドラインから、先程作成した talk.py のディレクトリに移動し、
以下コマンドでプログラムを実行する。
python3 talk.py
結果として、
talk()に入力した
‘布団が吹っ飛んだ’
がスピーカーから音声出力されます。
音声出力する内容を変えたければ、
‘布団が吹っ飛んだ’ の所に、好きな言葉を入れて試してみてください♪
音声を女性の声に変える
Open JTalkをインストールしても、男性の声しか入っていません。
でも安心してください。
女性の声(メイちゃん)にも変更できます。
音響モデルのダウンロード
以下URLから、音声ファイル「MMDAgent_Example-1.8.zip」をダウンロードします。
https://ja.osdn.net/projects/sfnet_mmdagent/releases/
以下コマンドで、ラズパイ内の音響モデルを格納ているディレクトリにコピーします。
unzip MMDAgent_Example-1.8.zip sudo cp -r MMDAgent_Example-1.8/Voice/mei /usr/share/hts-voice/
プログラム変更
上記、talk.py プログラムファイル中の、
VOICE_PATH = ‘*’
の値を、以下のように変更します。
上記の実行の章を行い、女性の声が出たら成功です。
VOICE_PATH = '/usr/share/hts-voice/mei/mei_happy.htsvoice'
蛇足ですが、メイちゃんの音響モデルには、
5つの感情が用意されています。
上記の例では、mei_happy を使っています。
- mei_normal
- mei_angry
- mei_bashful
- mei_happy
- mei_sad
しゃべる内容に応じて、音響モデルを変えるとよりリアルな会話が楽しめそうですね。
まとめ
まとめです。
これまで作成した上記機能を組み合わせて、
ボタンを押して、【天気予報】を喋らせる
を実現します。
プログラム
この章では、以下赤字のファイルを修正します。
/home/pi/work/weather/
├app.py
├talk.py
└weather.py
app.py
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import sys
import weather
import talk
# LED_GPIO 変数に 24をセット
SW_GPIO = 24
# GPIO.BCMを設定することで、GPIO番号で制御出来るようになります。
GPIO.setmode(GPIO.BCM)
# GPIO.INを設定することで、入力モードになります。
# pull_up_down=GPIO.PUD_DOWNにすることで、内部プルダウンになります。
GPIO.setup(SW_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
while True:
try:
# ボタン押しで発話
if GPIO.input(SW_GPIO) == 1:
weather = weather.get_weather()
if weather:
talk.talk(f'東京の天気は、{weather["weather"]}です。気温は、{weather["temperature"]}です。')
time.sleep(0.5) # 0.5秒間待つ
# Ctrl+Cキーを押すと処理を停止
except KeyboardInterrupt:
# ピンの設定を初期化
# この処理をしないと、次回 プログラムを実行した時に「ピンが使用中」のエラーになります。
GPIO.cleanup()
sys.exit()
実行
コマンドラインから、app.py のディレクトリに移動し、
以下コマンドでプログラムを実行する。
python3 app.py
ボタンを押すと、
天気予報がスピーカーから音声出力されます!
プログラムを終了する場合は、
Ctrl+Cキー を押すと終了します。
最後に
如何だったでしょうか?
ボタンを押したか判断出来た時、
ネット上から天気予報の情報が取れた時、
天気予報を喋った時、
ワクワクしましたよね♪
作ったものが動くって楽しいですよね♪
今後も、Raspberry Pi と Python を使ってワクワクするモノを作って行きます。
楽しみにしていてくださいね。
不明な点があればページTOPの「お問い合わせ」にてご連絡下さい。