📢

Raspberry Pi 5 で「人を検知したらファミマの入店音を流す装置」を作る

2024/03/24に公開

はじめに

Rasberry Pi 5 のGPIOを活用した電子工作の練習として、簡単な装置を作りました。

人感センサーで人を検知すると、ファミリーマートの入店音を再生します。

https://x.com/tanny_pm/status/1767905627010208060

この記事では、人感センサー・圧電スピーカーの使い方や、gpiozeroを活用して実装したプログラムについて紹介します。

環境

Raspberry Pi 5で動作を確認しています。

GPIO操作用ライブラリのgpiozeroが必須です。Raspberry Pi 5にラズパイOSをインストールした状態であれば標準で使えるはずです。

OSなど

  • Raspberry Pi 5
  • Raspberry Pi OS (64 bit) 12.5
  • Python 3.11.2

必要な部品は以下のとおりです。人感センサーは型番が違っていても問題ないと思います。

電子部品

  • 赤外線人感センサー HC-SR501
  • 圧電スピーカー(型番不明、3V駆動)
  • ブレッドボード、ジャンパー線

結線方法

人感センサーの信号線をGPIO23に、圧電スピーカーのプラス線をGPIO17に接続してください。


配線イメージ

プログラム

ソースコードの全文は以下のとおりです。

今回は、GPIOの操作用ライブラリ「gpiozero」の機能を活用しました。詳細な使い方はこの後に説明します。

human_sensor_famima.py
from time import sleep

from gpiozero import MotionSensor, TonalBuzzer
from gpiozero.tones import Tone

BPM = 80

motion_sensor = MotionSensor(23)
buzzer = TonalBuzzer(17)


def play_sound(divide: int, tone: str = ""):
    if tone == "":
        buzzer.stop()
    else:
        buzzer.play(Tone(tone))

    sleep((60 / BPM) / (divide / 4))


def play_famima_sound():
    play_sound(8, "F#5")  # ファ
    play_sound(8, "D5")  # レ
    play_sound(8, "A4")  # ラ
    play_sound(8, "D5")  # レ

    play_sound(8, "E5")  # ミ
    play_sound(8, "A5")  # ラ
    play_sound(8)
    play_sound(8, "E4")  # ミ

    play_sound(8, "E5")  # ミ
    play_sound(8, "F#5")  # ファ
    play_sound(8, "E5")  # ミ
    play_sound(8, "A4")  # ラ

    play_sound(4, "D5")  # レ
    play_sound(4)


def main():
    while True:
        motion_sensor.wait_for_active()
        print("Motion!")
        play_famima_sound()


if __name__ == "__main__":
    main()

人感センサー

人感センサーは、人の動きを検知すると信号線がHighになるセンサーです。gpiozeroのMotionSensorクラスを利用すると、この入力判定を楽に記述できます。

以下のように、motion_sensor.wait_for_active()で人感センサーの信号線がHighになるのを待ちます。Highになるとプログラムが次に進み、検知後の処理を実行できます。

human_sensor_famima.py(抜粋)
from time import sleep

from gpiozero import MotionSensor, TonalBuzzer
from gpiozero.tones import Tone

BPM = 80

motion_sensor = MotionSensor(23)
buzzer = TonalBuzzer(17)

# 省略

def main():
    while True:
        motion_sensor.wait_for_active() # 人感センサーがONになるまで待つ
        print("Motion!")
        play_famima_sound()


if __name__ == "__main__":
    main()

検知結果のハンドリング方法は他にもいくつかあります。詳しくはgpiozeroのドキュメントを参照してください。

https://gpiozero.readthedocs.io/en/stable/api_input.html#gpiozero.MotionSensor

圧電スピーカー

圧電スピーカーは、数kHzの信号を入力することで音を鳴らすことができます。これはgpiozeroのTonalBuzzerクラスを利用すると簡単に実装できます。

このクラスでは、Toneで音色(周波数)を指定します。周波数を直接記載するほかに、英語の音階でも指定できます。

サンプルコード
from gpiozero import TonalBuzzer
from gpiozero.tones import Tone
b = TonalBuzzer(17)
b.play(Tone(220.0)) # Hz
b.play(Tone("A4"))

今回は読みやすさを考慮して、音階での表記を採用しました。以下のような表記で書くことができます。「ファ#」も「#」を使って書けます。

音階 表記
C4
D4
E4
ファ F4
ファ F#4
G4
A4
B4
C5

圧電スピーカーの詳しい使い方は公式ドキュメントを参考にしてください。

https://gpiozero.readthedocs.io/en/stable/api_output.html#tonalbuzzer

play_sound関数

与えられた音の長さと音程にしたがって、ブザーから音を出力する関数です。

tone引数に音程を指定すると、その音を鳴らし、引数が空の場合は音を止めます。divide引数は音の長さを表しています。四分音符の場合は4を入力します。

play_sound()
def play_sound(divide: int, tone: str = ""):
    if tone == "":
        buzzer.stop()
    else:
        buzzer.play(Tone(tone))

    sleep((60 / BPM) / (divide / 4))

play_famima_sound関数

play_sound()関数を使って、ファミリーマートの入店音のメロディーを再現しています。それぞれの音程と長さを指定して、play_sound()関数を呼び出しています。

play_famima_sound()
def play_famima_sound():
    play_sound(8, "F#5")  # ファ
    play_sound(8, "D5")  # レ
    play_sound(8, "A4")  # ラ
    play_sound(8, "D5")  # レ

    play_sound(8, "E5")  # ミ
    play_sound(8, "A5")  # ラ
    play_sound(8)
    play_sound(8, "E4")  # ミ

    play_sound(8, "E5")  # ミ
    play_sound(8, "F#5")  # ファ
    play_sound(8, "E5")  # ミ
    play_sound(8, "A4")  # ラ

    play_sound(4, "D5")  # レ
    play_sound(4)

なお、ファミマ入店音の楽譜はこちらのサイトを参考にさせていただきました。短音バージョンを利用しています。

https://piano-gakufu.com/?p=4905

単音で演奏できる楽譜であれば、他にも色々なメロディーを演奏できそうです。

まとめ

Raspberry PiのGPIOを利用して、センサーやブザーを制御するプログラムの基本が理解できました。

gpiozeroライブラリを使えば、ハードウェア制御が簡単になることがわかります。

このライブラリには他にも入出力デバイスのためのクラスが用意されているので、簡単なコーディングで色々な電子工作を楽しむことができます。

公式ドキュメントの「Basic Recipes」には他にもさまざまな実装アイデアが掲載されているので、電子工作のアイデアにお悩みの方は一度読んでみると良いと思います。

https://gpiozero.readthedocs.io/en/stable/recipes.html

参考文献

https://qiita.com/namekuji/items/d90baf0cbc3668e77dbd

https://www.autumn-color.com/archives/28#google_vignette

GitHubで編集を提案

Discussion