ラズパイ(Raspberry Pi)と赤外線センサを組み合わせた電子工作の定番といえば、センサライトのような防犯グッズでしょう。近付いてくる人を検出してLEDを点灯する機器は実用的ですが、今回はそれにもう一工夫してみます。
本記事では、人の動きを検出し、誰が近付いたかに応じて音声データを再生できる電子工作を紹介します。
ちょうど、プロレスラーの入場シーンのように、ドアを通った人に合ったテーマ曲が流れるイメージです。そこで今回の電子工作では、ショーン・マイケルズ(アメリカの元プロレスラー)のMP3形式のデータを再生します。もちろん、お好きな曲で構いません。
応用次第で、あらかじめ登録してある人には反応せず、侵入者の場合だけ警報を鳴らす機器も作成できます。
近付いてくる人の検出には汎用的な赤外線センサを、人物の特定には手持ちのスマートフォン(スマホ)を利用します。
音楽の再生とスマホの特定は、PythonからLinuxのコマンドラインの操作で実現します。
目次
- 概要
- 人が近付いたことを検出する
- ラズパイで誰のスマホか判定する
- PythonでLinuxのコマンドラインを制御する
- 準備
- 用意するもの
- 作業ディレクトリの作成
- mpg123のインストール
- 赤外線センサの接続
- スマホのIPアドレスを確保
- Pythonスクリプト
- スクリプト全体
- Pythonでmpg123コマンドを呼び出してMP3を再生
- Pythonでpingコマンドを呼び出してスマホを検出
- 実行
- 調整
- 応用
- まとめ
1. 概要
今回の「近付いた人物を特定して音楽を再生する電子工作」のポイントを説明します。
人が近付いたことを検出する
ラズパイ人が近づいたことを赤外線センサで検出します。赤外線センサはポピュラーなデバイスなので、触ったことがある方も多いと思います。
赤外線センサは、物質が常に発している赤外線を監視することで人間を検出します。
赤外線センサは周囲の熱の変化のみを検出するので、残念ながら「誰が近付いたのか?」までは判定できません。そこで今回は、手持ちのスマホを利用します。
ラズパイは、Linuxを搭載した小型のパソコンなので、ネットワークの接続も簡単です。そこで、ラズパイを家庭用のWi-Fiネットワークに接続しておき、同じネットワークにスマホが接続したことで「誰が近付いたのか」を判定します。
家庭用のWi-Fiネットワークの電波は、数十メートル先まで到達します。ラズパイとWi-Fiネットワークの組み合わせだけでスマホを検出すると範囲が広すぎるので、赤外線センサを加えて「ラズパイの前を誰が通過したのか?」を判定します。
ラズパイで誰のスマホか判定する
電子工作の構成は理解できたと思います。工夫が必要な点は「Wi-Fiネットワークに誰のスマホが接続したか?」の判定です。
これには、スマホに割り当てられたIPアドレスを利用します。
スマホなどのデバイスがネットワークに接続するためには、固有のIPアドレスを割り当てる必要があります。通常は自動的に割り当てられるように設定(「DHCP」と呼びます)されているので、割り当てたIPアドレスを意識する必要はありません。
今回は、このIPアドレスを前もって手動で割り当てておきましょう。あとはラズパイで、このIPアドレスを割り当てたデバイスが、ネットワーク内に存在しているかを検索すれば、誰が近付いたのかを識別できます。
検索には、Linuxに標準的にインストールされているコマンド、pingを使用します。pingは、ネットワーク上にあるサーバーやパソコンなどのデバイスが動作しているかどうかを確認するためのコマンドです。
音楽の再生は、Linuxのコマンド、mpg123を使用します。mpg123はMP3形式の音声ファイルを再生するコマンドです。使用するには前もってインストールが必要です。
PythonでLinuxのコマンドラインを制御する
pingやmpg123コマンドは、もともとLinuxのコマンドライン(ターミナル上でコマンドを入力する行)で使用するように設計されています。
これをプログラムから使用するには、テクニックが必要です。
今回は、Pythonを使用してプログラミングします。Pythonにはsubprocessモジュールと呼ばれる、コマンドラインを制御するためのライブラリーがあらかじめ準備されています。
インストールは不要です。
subprocessモジュールは、一行一行コマンドを入力する作業を、Pythonのコマンドを通して実行するためのものです。コマンドラインでの作業に慣れていれば、このモジュールの使用は簡単でしょう。
2. 準備
それでは、電子工作の準備をします。
用意するもの
次のものを用意してください。
ラズパイ本体
RaspbianがインストールされたSDカード
赤外線センサ
上記以外に、スマホ・Wi-Fiネットワーク・赤外線センサとラズパイを接続する電線・MP3形式の音声データが必要です。
スマホはWi-Fiネットワークに自動的に接続するよう設定しておいてください。また、省電力モードをオフにして、使用していない時にWi-Fiが切断されないようにしておく必要があります。
すでに、赤外線センサとPythonのライブラリーGPIO Zeroの知識がある前提で解説します。
ラズパイはセットアップを完了し、Wi-Fiネットワークに接続しておいてください。
本記事で使用するRaspbian(ラズパイのOS)のバージョンはBusterです。ただし、本記事で使用するコマンドやPythonの機能は以前からあるものなので、古いバージョンのRaspbianでも動作するはずです。
作業ディレクトリの作成
最初に作業用のディレクトリを作成します。ターミナルを起動して、次のコマンドを入力してください。
mkdir ~/entrancemusic cd ~/entrancemusic
1行目は、新しいディレクトリの作成です。ユーザーのホームディレクトリの直下にentrancemusicという名前のディレクトリを作ります。ディレクトリ名はプログラム中で使用します。
2行目は、作成したディレクトリの中に入るコマンドです。以降は、この作成したディレクトリの中で作業を進めます。
MP3形式の音声データも、ここにコピーしておきます。今回は再生するMP3形式のデータとしてSexy Boy (Shawn Michaels).mp3を準備しました。
MP3形式の音声データは皆さんの好きなもので構いません。その場合はファイル名を読み替えてください。
mpg123のインストール
MP3形式の音声データを再生するためのmpg123コマンドをインストールしましょう。以下のコマンドを入力してください。
sudo apt update && sudo apt upgrade -y sudo apt install mpg123
赤外線センサの接続
今回の電子工作は、コンパクトに仕上げるため、ブレッドボードを使用せず直接ラズパイに接続します。不安な方は使用しても構いません。
以降は、ブレッドボードを使用しない手順です。
電線を使い、赤外線センサの3本の端子を、それぞれラズパイのGPIOに接続します。
- 赤外線センサの電源ピンを、ラズパイの5Vピンに接続します。
- 赤外線センサのグランドピンを、ラズパイのGNDピンに接続します。
赤外線センサの出力ピンをGPIOピンに接続します。今回はGPIO24に接続します。空いているGPIOピンであればどこでも構いません。その場合はピン番号を読み替えてください。
これで赤外線センサの配線は完了です。センサの方向に注意してください。通過する人を検出できるようにドア付近に設置します。
スマホのIPアドレスを確保
一般的な家庭用Wi-Fiネットワークは、DHCPと呼ばれる仕組みを利用して、ネットワークに接続する機器に自動的にIPアドレスを割り当てます。
この仕組みを利用すると、Wi-Fiルータがネットワーク上で空いているIPアドレスを探して自動的に割り当てるため、直接IPアドレスを割り当てて管理するより簡単です。また、使用しなくなった機器のIPアドレスは、ほかの機器が接続する際に再利用されるので、少ないIPアドレスを効率的に利用できます。
しかし、これはDHCPで割り当てられたIPアドレスは、意図しないタイミングで変わる可能性があります。
今回の電子工作では、スマホのIPアドレスを使って誰が(どのスマホが)近付いたかを判定するので、IPアドレスが変化してしまうと正しく動作しません。
ただし一般的なWi-FiルータはIPアドレスをすぐに変えないことが多いので、テストする程度であれば、気にする必要はありません。
もし、この電子工作を長期間動作させたい場合は、IPアドレスを固定してください。今回はスマホに192.168.0.5のIPアドレスを割り当てました。
スマホのIPアドレスを固定する方法は、AndroidのIPアドレスを固定、iPhoneのIPアドレスを固定が参考に、または使用しているルータの管理画面から固定IPの割り当てを設定しておきましょう。
3. Pythonスクリプト
スクリプトとは、Pythonのコマンドを一つのファイルにまとめたものです。
最初にPythonのスクリプトの全体を紹介し、そのあとポイントとなる部分を解説します。
スクリプト全体
テキストエディタで新規ファイル、entrancemusic.pyを作成します。以下のコマンドを入力してください。
nano entrancemusic.py
nanoは、ターミナル上で動作するテキストエディタです。[エンターキー]を押すと、ターミナル上にテキストエディタが起動したはずです。
Pythonのコマンドを一行一行、以下のように入力してください。
from time import sleep from signal import pause from subprocess import run, Popen, PIPE from gpiozero import MotionSensor sleep(600) # This gives you 10 minutes to leave your home pir = MotionSensor(24) while True: p1 = Popen(["ping", "-c", "1", "192.168.0.5"], stdout=PIPE) stdout_value = p1.communicate()[0] if b'Destination Host Unreachable' not in stdout_value: break sleep(2) sleep(5) pir.wait_for_motion() run("mpg123 ~/entrancemusic/'Sexy Boy (Shawn Michaels).mp3'", shell=True)
保存して終了します。
Pythonでmpg123コマンドを呼び出してMP3を再生
ターミナル上で、mpg123コマンドを使用してMP3形式の音声データを再生するのは簡単です。以下のように再生したいファイル名を指定するだけです。
mpg123 'Sexy Boy (Shawn Michaels).mp3'
Pythonから、このコマンドを実行するには、subprocessモジュールに含まれるrun()関数を使います。
以下に、ソースコードのその部分を抜粋します。
from subprocess import run run("mpg123 ~/entrancemusic/'Sexy Boy (Shawn Michaels).mp3'", shell=True)
1行目は、run()関数が使用できるようにsubprocessモジュールをインポートしています。
2行目で実際にrun()関数を使用しています。第一引数に起動したいコマンド、第二引数には「shell=True」を指定してください。コマンドは、ターミナル上でMP3を再生するために使用したものです。ただし、ファイル名をフルパスで指定しないと、mpg123がファイルを見付けることができません。
Pythonでpingコマンドを呼び出してスマホを検出
ターミナル上で、pingコマンドを使用するには、以下のように入力します。
ping -c 1 192.168.0.5
192.168.0.5は先ほどスマホに指定したIPアドレスです。実際に割り当てたIPアドレスと読み替えてください。
pingコマンドを実行する際に「-c 1」を指定しないと、pingコマンドは[Ctrl+c]を入力するまで動作し続けます。
指定したIPアドレスを持つデバイスが呼びかけに応答したら(ネットワークに接続されていたら)、pingコマンドは正常終了、応答しない場合はエラーコードと共に終了します。
このエラーコードで「スマホが応答する/しない」を判定できれば理想的ですが、残念ながら多くのスマホはpingコマンドの呼びかけに反応しません。
そのため、スマホが「Wi-Fiネットワークに接続している/いない」にかかわらず、pingコマンドはエラーを返してしまいます。
そこで工夫が必要です。
指定されたIPアドレスを持つスマホがネットワーク上に見つからない場合、pingコマンドのエラーメッセージの中に「Destination Host Unreachable」と記載されるはずです。
このpingコマンドが返してくるエラーメッセージを解析して「スマホがネットワークに接続している/いない」を判定します。
Pythonがpingコマンドからエラーメッセージを受け取る必要があるため、mpg123とは使用するコマンドが異なります。
run()関数に代わって、同じsubprocessモジュールに含まれるPopen()関数とPIPEオブジェクトを使用します。詳細は公式マニュアルで確認してください。
以下に、ソースコードのその部分を抜粋します。
from subprocess import Popen, PIPE p1 = Popen(["ping", "-c", "1", "192.168.0.5"], stdout=PIPE) stdout_value = p1.communicate()[0]
PIPEはOS(Linux)に依存する機能を提供するオブジェクトです。使用方法を理解するためには多くの知識が必要なため、本記事では詳細な説明は省略します。ここでは、pingコマンドの出力が、変数stdout_valueに格納されることが理解できれば十分です。
実際にPopen()関数とPIPEを使用して「pingコマンドの呼び出し・メッセージの受信・メッセージの分析」する部分を抜粋します。
while True: p1 = Popen(["ping", "-c", "1", "192.168.0.5"], stdout=PIPE) stdout_value = p1.communicate()[0] if b'Destination Host Unreachable' not in stdout_value: break sleep(2)
上記は、ループ(繰り返し)文を使用して、pingコマンドが「Destination Host Unreachable」の文字列を含むメッセージを返さなくなるまで(スマホを検出するまで)一連の動作を繰り返します。
4. 実行
作成したスクリプトを実行するには以下のコマンドを入力してください。
python3 entrancemusic.py
スマホを検出するまでプログラムは終了しません。
途中で実行を停止する場合は[Ctrl+c]を入力します。
5. 調整
このスクリプトは、起動を開始してから10分後に動作を開始します。
これは、電源を入れた後にラズパイから離れる時間と、赤外線センサが安定するのを待つ時間です。スクリプトの6行目にあるsleep(600)がその設定です。
また、スマホがWi-Fiネットワークに接続してから、赤外線センサの反応をチェックするまでに5秒間プログラムを停止します。場所はスクリプトの末尾から4行目にあるsleep(5)です。
どちらも、Wi-Fiネットワークや部屋の構造に合わせて調整してください。
6. 応用
改良するヒントを紹介します。
例として、今回の電子工作が9時から22時の間のみ動作するようにします。
Pythonで時間を取得するには、localtime()関数を使用します。これはtimeモジュールに含まれます。
以下のようにインポートして、localtime()関数が使用できるようにします。この行は先頭に追加してください。
from time import sleep, localtime
「現在の時刻は9時から22時の間か?」の判定は以下のようになります。
9 < localtime().tm_hour < 22
これをif文と組み合わせて、mpg123を起動するコマンドを呼び出す部分を変更します。
if 9 < localtime().tm_hour < 22: run("mpg123 ~/entrancemusic/'Sexy Boy (Shawn Michaels).mp3'", shell=True)
利用シーンに応じて時間を変更する場合は、1行目の9と22を好みの時間に変えるだけです。
7. まとめ
今回は「赤外線センサの制御」「スマホの検出」「音楽の再生」などを組み合わせた電子工作のため、説明が少し長くなりました。ただし、それぞれはそれほど難しくなかったと思います。
ラズパイの外観は小型のマイコンボードですが、その機能はLinuxが動作するパソコンと変わりません。これは、Linuxで用意されているコマンドが、ラズパイでほぼ全て使用できるということです。
ネットワークの処理をマイコンボードで実装するのは大変な作業です。今回の電子工作のように簡単に実装できるのは、Linuxが動作するラズパイだからこその利点です。
これを最大限に生かすコマンドラインの操作は強力なテクニックです。ぜひマスターしましょう。