ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【Windows/Android】AndroidをWindowsのサブモニターにする

 最近ネットでの打合せの際に複数画面があると便利なのでモバイルモニターを使う機会が増えてきました。

 その他の用途で「モバイルモニターほどの大きさはなくていいけど、ちょっとしたサイズのサブモニターが欲しい」という場面も出てきたので調べてみると、WindowsAndroidであれば無料ソフトを使ってAndroidをサブモニター化することができるとわかりました。

 今回はその備忘録になります。基本的には参考資料に挙げているページ様の内容そのままなので、詳しくはそちらを参照してください。


 では、始めます。


1:Windows用spacedeskをインストールする
 まずはWindows側の準備として「spacedesk」をインストールします。

 以下の公式ページを開きます。

 ページを開くと左下あたりに「DOWNLOAD」ボタンがあるのでクリックします。
f:id:rikoubou:20220401150444p:plain

 対象のOSを選択してクリックするとインストーラがダウンロードされます。自分の場合はWindows10の64bitなのでそれを選びました。
f:id:rikoubou:20220401150709p:plain

 ダウンロードしたインストーラを起動させます。
f:id:rikoubou:20220401150902p:plain

 インストーラを起動させると以下のような画面が表示されるので「Next」をクリックします。
f:id:rikoubou:20220401151024p:plain

 ライセンスの同意のところにチェックを入れて「Next」をクリックします。
f:id:rikoubou:20220401151119p:plain

 インストール先を指定して「Next」をクリックします。特に変える必要はなくデフォルトのままでOKです。
f:id:rikoubou:20220401151227p:plain

 ファイアウォール除外の設定についての画面になりますが、ここでチェックが入っていることを確認して「Next」をクリックします。ここでチェックが入っていないとファイアウォールによって動かない場合があるようです。
f:id:rikoubou:20220401151406p:plain

 あとは次の画面で「Install」ボタンをクリックするとインストールが開始されます。

 spacedeskを起動させて以下のような画面が出てくればインストール完了です。
f:id:rikoubou:20220401151556p:plain


2:Android用spacedeskアプリをインストールする
 Windows側の準備ができたので、次はAndroid側の準備をしていきます。

 こちらは簡単で「Google Playストア」を立ち上げて「spacedesk」と入力して出てきたアプリをインストールするだけです。

 spacedeskアプリを立ち上げて以下のような画面が出てくればインストール完了です。
f:id:rikoubou:20220401152722j:plain


3:Androidをサブモニター化する
 1、2の準備が出来たらWindows機とAndroid端末の両方を同じLAN内になるようネットワークに接続します。

 その状態でWindows側のspacedeskを起動させてspacedesk Statusを「ON」にします。
f:id:rikoubou:20220401153102p:plain

 次にAndroid側のspacedeskを起動させると同じLAN内で端末を自動検索してくれるので、対象の端末を選択します。
f:id:rikoubou:20220401153402j:plain

 これでAndroid端末をサブモニター化することができます。あとの操作はWindows側で他のディスプレイを接続した時と同じように操作して表示することができます。

 ただし画面解像度についてはAndroid端末依存になるため、スマホなどの場合はかなり横長や縦長のサイズになるので注意してください。

 サブモニター化をやめたい場合はWindows側のspacedesk Statusを「OFF」にします。
f:id:rikoubou:20220401153709p:plain

 また未検証ですが、スマホ側でアプリを強制終了させるとフリーズしてしまうようなのでWindows側でStatusを「OFF」にして切断するようにした方が良いらしいです。
 

 以上がAndroidWindowsのサブモニターにする方法になります。

 スマホではなくタブレットAndroidであればそれなりの画面サイズになるので、それを相手に見せつつ画面操作をして情報を共有するみたいな使い方もできて割と便利だと思います。


・参考資料

【python/PySide6】PySide6の導入と簡単なGUIを作ってみる

 以前のtkinerを使ってpythonGUIを作る記事を書きました。

 基本的にデフォルトで入っていてちょっとしたGUIならすぐに作れて便利ではあるのですが、自由度というか書いていく内に若干の使い難さを感じるようになっていました。

 この他にも何かいいライブラリはないかと思って探していたところ、PySide6というQtを使ったものが良さそうだと感じたので今回はそのインストール方法と簡単なGUIを作ってみた備忘録になります。
 また今回はWindowsでの方法になるので注意してください。


 では、始めます。


1:PySide6のインストール方法
 インストール方法は簡単で以下のpipコマンドでインストールします。

$ pip install pyside6

 ちゃんとPySide6が使えるかの確認は以下のプログラムをhello.pyとして保存し実行することで確認できます。

・hello.py

#-*- coding:utf-8 -*-
import sys
from PySide6.QtWidgets import QApplication, QLabel

app = QApplication(sys.argv)
label = QLabel("Hello World!")
label.show()
app.exec()

 画面サイズが設定されてないせいなのか自分の場合はかなり小さい画面になっていましたが、以下のようにGUIが表示されればインストール完了です。
f:id:rikoubou:20220218105246p:plain


2:PySide6で簡単なGUI
 では実際に簡単なGUIを作ってみます。今回作ったのは参考資料にあるサイト様の内容をいくつか組み合わせています。

gui_sample.py

#-*- coding:utf-8 -*-
import sys
from PySide6.QtWidgets import *

class Form(QDialog):

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        # Widgetsの設定(タイトル、固定横幅、固定縦幅)
        self.setWindowTitle("Title test")
        self.setFixedWidth(300)
        self.setFixedHeight(100)

        self.edit = QLineEdit("Write here") # テキスト入力
        self.button = QPushButton("Button") # ボタン

        # レイアウトを作成して各要素を配置
        layout = QVBoxLayout()
        layout.addWidget(self.edit)
        layout.addWidget(self.button)

        # レイアウトを画面に設定
        self.setLayout(layout)

        # ボタンを押したときの関数を設定
        self.button.clicked.connect(self.showMessageBox)


    # テキスト入力の内容をメッセージボックスで表示する関数
    def showMessageBox(self):
        QMessageBox.information(self, "Message", self.edit.text())


if __name__ == '__main__':
    # Qtアプリケーションの作成
    app = QApplication(sys.argv)

    # フォームを作成して表示
    form = Form()
    form.show()

    # 画面表示のためのループ
    sys.exit(app.exec())

 上記のプログラムを実行すると、以下のようなGUIが表示されます。
f:id:rikoubou:20220218112436p:plain

 ボタンを押すとテキストに入力された内容がメッセージボックスで表示されます。
f:id:rikoubou:20220218112544p:plain


 以上がPySide6の導入と簡単なGUIを作ってみた内容になります。

 Qt自体あまり触ったことなかったのもあり、まだ何もわかっていない状態ですが印象としてはtkinterよりも自由度は高そうな気がしています。

 tkinterはどうやらMacなどでは非推奨になりつつあるらしいので、多くの環境に合わせたい場合はこのPySide6を使うのもいいかもしれません。


・参考資料

【excel/VBA】シート名をつけるときの注意点

 最近ちょくちょくエクセルを触る時があるのですが、あまりに驚いた仕様を発見してしまったので備忘録として記事にしようと思った次第です。


 では、始めます。


1:同一のシート名は複数存在できない(大文字/小文字関係ない)
 見出しにある通りです。

 エクセルファイルを普通に使っていて同じシート名を複数作ろうとした時にエラーになるのは知っている人は多いかと思いますが、実は「アルファベットの大文字小文字関係なく判定」しています。

 例えば「Sheet1」というシートとは別に「SHEET1」というシートを作ろうとすると以下のようにエラーになります。
f:id:rikoubou:20220208171144p:plain

 もちろんアルファベットのみではなく、全角文字が含まれている場合でも同様にエラーになります。
f:id:rikoubou:20220208171559p:plain


2:シート名は31文字まで
 シート名には文字数制限があり、32文字以上になると31文字になるように自動的に切り捨てられます。
f:id:rikoubou:20220208171912p:plain

 ちなみにVBAで以下のようなマクロで32文字以上を設定しようとすると、エラーになります。

Option Explicit

Sub InsertLongSheetName()
    Dim ws As Worksheet
    
    Set ws = ThisWorkbook.ActiveSheet
    
    ws.Name = "1234567890123456789012345678901234567890" ' 40文字
'    ws.Name = "1"
    
    Set ws = Nothing
End Sub


f:id:rikoubou:20220208173206p:plain

 なので、VBAで自動的にシート名をつける場合は「アルファベットの大文字小文字」と「文字数」に気を付ける必要があります。


 以上がエクセルでシート名をつける時の注意点になります。


 VBAなどで自動的にシートを作成したりリネームしたりする時に、この仕様を知ってないと引っかかってしまう場合がある(実際に自分が引っかかって悩んでいた)ので気をつけましょう……。


・参考資料

【python/tkinter/pyinstaller】pyinstallerでのexe化時にGUIとexeファイルのicon画像を設定する

 以前の記事でpyinstallerを使ってexe化を行いました。

 今回はexe化する際にアイコン画像も含める方法についての備忘録です。


 では、始めます。


0:デフォルト状態の場合
 バージョンなど環境によって変わるかもしれませんが、特にアイコン画像を指定せずにpyinstallerを使ってexe化した場合は以下のようになっています。
f:id:rikoubou:20220121153043p:plain

 機能としては問題ないですが、デフォルトのままだと色々と困る場合が多いと思うので実際にアイコンを作成しつつその画像を設定していきます。


1:アイコン画像の準備
 まずは設定したいアイコン画像を作成します。適当なペイントソフトで正方形の適当な画像を作成します。

 今回は例として以下のような100×100pxのpng画像を作りました。必要であればダウンロードして使ってください。
f:id:rikoubou:20220121154344p:plain

 アイコン画像の拡張子は「.ico」なので変換する必要がありますが、以下の便利な「Faviconジェネレーター」様があるので利用させていただきました。

 使い方は書いてある通りですが、以下のような手順でアイコンを作成してダウンロードします。
f:id:rikoubou:20220121174430p:plain

 これでアイコン画像が準備できました。

 以降このアイコン画像は「icon.ico」というファイル名という前提で進めます。


2:GUIのアイコン画像を設定する
 GUIのアイコン設定はpython側で設定します。

 今回はアイコン画像を以下のようにexe化したいpythonファイルと同じ階層に配置したという前提で進めます。
f:id:rikoubou:20220121160344p:plain

 この場合のGUIのアイコン設定の方法は以下のように「root.iconbitmap」で指定します。

import tkinter as tk

root = tk.Tk()
root.iconbitmap(default='icon.ico')

 この時設定するアイコン画像のファイルパスですが「pythonを実行している階層からのパス」になっているため注意が必要です。
 なので絶対パスを指定するか、相対パスの場合は実行している階層を気にする必要があります。

 またさらに厄介なのがpyinstallerによってexe化した場合、この「pythonを実行している階層」が不確定になります。
 というのも、詳しくは参考ページ様を参照していただきたいのですが、pyinstallerでexe化したファイルを実行した際、一度その中身が「一時フォルダ」に展開されてそこでpythonが実行されるという形になっています。一時フォルダは毎回exeが起動される度に違う名前で作成されるため、固定のパスというわけではありません。

 つまりpythonが実行される階層やexe化されることを考えるとこのままの記述ではまずいので、以下のように「get_icon_path」関数からアイコン画像のパスを取得するようにします。

import sys, os

# アイコンファイルの絶対パスを取得する関数
def get_icon_path(relative_path):
    try:
        # 一時フォルダのパスを取得
        base_path = sys._MEIPASS
    except Exception:
        # 一時フォルダパスを取得できない場合は実行階層パスを取得
        base_path = os.path.abspath(os.path.dirname(sys.argv[0]))
    
    # アイコンファイルの絶対パスを作成
    return os.path.join(base_path, relative_path)

 これでexe化したものを実行した際は一時フォルダに展開された中からアイコン画像のパスを作成し、pythonファイルを直接実行する際は実行階層からアイコン画像のパスを作成するという形になります。
 この方法はexe化した中にアイコン画像を含める必要があるので、それはpyinstallerでの実行時にオプションとして設定します。

 ちなみにこの関数を追加して修正したソースコードは以下のようになります。

tkinter_sample.py

#-*- coding:utf-8 -*-
import sys, os
import tkinter as tk
import tkinter.ttk as ttk
from functools import partial


def main():
    # rootの作成
    root = tk.Tk()
    root.title("tkinter_sample")
    root.geometry("300x100")
    root.iconbitmap(default=get_icon_path('icon.ico'))

    # frameの作成
    frame = ttk.Frame(root, padding=10)
    frame.grid(row=2, column=0)

    # ラベルの作成
    label = ttk.Label(frame, text="ここに入力したテキストの内容が表示されます")
    label.grid(row=0, column=0)

    # Entry(1行のテキスト入力行)を作成してframeに追加
    entry = ttk.Entry(frame, width=40)
    entry.grid(row=1, column=0, pady=4)

    # Buttonを作成してframeに追加
    button = ttk.Button(frame, text="表示", command=partial(update_label, entry, label))
    button.grid(row=2, column=0, pady=4)

    # 中央揃え
    root.grid_columnconfigure(0, weight=1)
    root.grid_rowconfigure(0, weight=1)

    root.mainloop()


# ラベルを入力されたテキストの内容で更新
def update_label(entry, label):
    label['text'] = entry.get()


# アイコンファイルの絶対パスを取得する関数
def get_icon_path(relative_path):
    try:
        # 一時フォルダのパスを取得
        base_path = sys._MEIPASS
    except Exception:
        # 一時フォルダパスを取得できない場合は実行階層パスを取得
        base_path = os.path.abspath(os.path.dirname(sys.argv[0]))

    # アイコンファイルの絶対パスを作成
    return os.path.join(base_path, relative_path)


if __name__ == "__main__":
    main()


3:exeのアイコン画像の設定と画像ファイルをexeに含める
 exeのアイコン画像を設定するには「--icon」オプションを使います。以前の記事で実行したpyinstallerのコマンドに追記すると以下のようになります。

$ pyinstaller tkinter_sample.py --icon=icon.ico --name tkinter_sample.exe --onefile --noconsole

 上記のように「--icon」とファイルパスを指定するだけでexeファイル自体のアイコンが設定できます。

 また2で記述したGUIで設定するアイコン画像を含めるために、以下のようにさらに「--add-data」オプションを加えます。

$ pyinstaller tkinter_sample.py --add-data "icon.ico;./" --icon=icon.ico --name tkinter_sample.exe --onefile --noconsole

 この「--add-data」オプションを記述することでexeファイルに画像などを含めることができます。

 以下オプションの書き方の簡単なまとめです。

書き方 内容
-i [FILE], --icon [FILE] exeのアイコン画像を設定
--add-data [FILE文字列] exeに含めるバイナリ以外のファイルやフォルダを設定


4:実際に実行してみる
 では実際に2で記述した修正したソースコードの実行とexe化コマンドを実行して確認してみます。

 以下のようにpythonファイルと同じ階層にicon.icoを配置して実行してみます。
f:id:rikoubou:20220121171417p:plain

 実行すると以下のようにGUIにちゃんと画像が設定されています。
f:id:rikoubou:20220121171539p:plain

 では次に以下のコマンドでexe化してみます。

$ pyinstaller tkinter_sample.py --add-data "icon.ico;./" --icon=icon.ico --name tkinter_sample.exe --onefile --noconsole

 実行すると以下のようにexeアイコンが設定され、実行時のGUIにもアイコンが設定されています。
f:id:rikoubou:20220121173257p:plain
f:id:rikoubou:20220121173406p:plain

 実際に一時フォルダ内を確認してみると、ちゃんとicon画像が含まれています。
f:id:rikoubou:20220121173800p:plain


 以上がpyinstallerでのexe化時にGUIとexeファイルのicon画像を設定する方法になります。

 色々とややこしかったりしますが、一度記述してコマンドを確定してしまえばあとは特に変更することがないので最初少し大変なだけだと思います。

 また別の方法としてアイコン画像をバイナリ文字列の定数としてソースコード内に埋め込むことも考えられますが、画像を変更する度にバイナリ文字列も変更しないといけないのは面倒です。
 なので今回記事にした方法であればファイルを変更するだけで良いので、これが一番楽なのかなと思います。


・参考資料

【python/tkinter/pyinstaller】tkinterで作ったGUIをexe化する

 以前の記事でtkinterを使ってpythonで簡単なGUIを作ってみました。

 作ったGUIは環境構築ができていない人に配布することも考えられるので、最終的にはexe化することになると思います。

 なので今回はtkinterで作ったものをexe化する方法の備忘録になります。


 では、始めます。


1:pyinstallerのインストール
 pythonソースコードをexe化するにはいくつか手段があるようですが、今回はpyinstallerを使います。

 pyinstallerのインストールは簡単で以下のpipコマンドを実行することでインストールできます。

$ pip install pyinstaller

 pyinstallerがちゃんとインストールできているかは、以下のコマンドを実行してエラーなくバージョン情報が表示されるかで確認ができます。

$ pyinstaller -v


2:pyinstallerでexe化
 実際にpyinstallerを使って冒頭の記事にある「tkinter_sample.py」をexe化してみます。

 まず最初にPowerShellなどを立ち上げ「cd」コマンドで対象ソースコードが存在する階層へ移動します。

 その後以下のコマンドを実行します。

$ pyinstaller tkinter_sample.py --name tkinter_sample.exe --onefile --noconsole

 色々な表示が出る中しばらく待って以下のように「completed successfully」と表示されればexe化は完了です。

 INFO: Building EXE from EXE-00.toc completed successfully.

 コマンド実行後、対象のpythonファイルと同じ階層に色々とフォルダやファイルができていますが、「dist」というフォルダの中にexeファイルが作られています。
f:id:rikoubou:20220120162641p:plain
f:id:rikoubou:20220120162751p:plain

 このdistフォルダ内に作られたexeをダブルクリックで起動させれば、pythonファイルを実行した時と同じものが実行されます。


3:pyinstallerのコマンドオプション
 今回使ったpyinstallerのコマンドのオプションについて少し説明します。今回使ったオプションは以下になります。

書き方 内容
-n [NAME], --name [NAME] exe化する時のファイル名を指定する
-F, --onefile 一つのexeファイルにまとめる
-w, --windowed, --noconsole exe起動時にコンソール画面を出さない

 なので2で実行したコマンドは「tkinter_sample.exeという1ファイルにまとめ、起動時にコンソール画面を出さないようにする」という形でビルドしたことになります。
 ちなみに「--onefile」オプションを入れない場合はdist内に無数のファイルが作成され、exeファイルは作成されないので必ず指定するようにしてください。

 この他にも色々とオプションがありますが、とりあえずexe化するというだけであればこれらのオプションを知っていればなんとかなるかと思います。


 以上がtkinterで作ったGUIをexe化する方法になります。

 exe化した時のアイコン画像を設定したい、などまだ色々ありますが、それは調べてから別の記事にでもしようかと思います。


・参考資料

【python/tkinter】tkinterで簡単なGUIをpythonで作る

 pythonを使っていて時々GUIのアプリを作りたくなる場合があります。
 その際tkinterというpythonに同梱されているライブラリを使えば比較的簡単にGUIを作れることがわかったので、今回はそのtkinterを使ってみた備忘録になります。


 では、始めます。


1:tkinterのインストール方法
 先に書きましたがpythonに同梱されているため、基本的にインストールをする必要がありません。

 tkinterが使えるかどうかの確認は、PowerShellなどを立ち上げてpythonを起動させて以下のコードを実行します。

import tkinter
tkinter._test()

 上記を実行すると以下のようにGUItkinterのバージョンを確認できます。
f:id:rikoubou:20220119155924p:plain

 エラーが発生した場合はtkinterがインストールされていないので、以下のpipコマンドでインストールします。

$ pip3 install pytk


2:tkinterの基本的な考え方
 詳しくは参考資料様のページを見ていただきたいのですが、tkinterは基本的には以下のような構造になっています。
f:id:rikoubou:20220119161905p:plain

 最初にROOTという空のGUI画面にFRAMEという領域を作ります。そしてそのFRAME内の領域にLABELやBUTTONなどの具体的な要素を入れていくという形です。
 FRAMEには配置するためにGRID(htmlのtableのようなイメージ)が設定でき、綺麗に並べることもできます。


3:簡単なGUIを作ってみる
 では実際にtkinterを使って簡単なGUIを作ってみます。

tkinter_sample.py

#-*- coding:utf-8 -*-
import tkinter as tk
import tkinter.ttk as ttk
from functools import partial


def main():
    # rootの作成
    root = tk.Tk()
    root.title("tkinter_sample")
    root.geometry("300x100")

    # frameの作成
    frame = ttk.Frame(root, padding=10)
    frame.grid(row=2, column=0)

    # ラベルの作成
    label = ttk.Label(frame, text="ここに入力したテキストの内容が表示されます")
    label.grid(row=0, column=0)

    # Entry(1行のテキスト入力行)を作成してframeに追加
    entry = ttk.Entry(frame, width=40)
    entry.grid(row=1, column=0, pady=4)

    # Buttonを作成してframeに追加
    button = ttk.Button(frame, text="表示", command=partial(update_label, entry, label))
    button.grid(row=2, column=0, pady=4)

    # 中央揃え
    root.grid_columnconfigure(0, weight=1)
    root.grid_rowconfigure(0, weight=1)

    root.mainloop()


# ラベルを入力されたテキストの内容で更新
def update_label(entry, label):
    label['text'] = entry.get()


if __name__ == "__main__":
    main()

 このサンプルコードを実行すると以下のようなGUIが表示されます。テキスト入力部分に何かしらを入力して表示ボタンを押下すると、Label部分にそのテキストが表示されます。
f:id:rikoubou:20220119172057p:plain

 buttonが押下された時の呼び出し関数はttkでbuttonを作成する際の「command」の引数に指定します。引数も渡したい場合は「partial」を使って関数名に続いて渡したい引数を指定します。


 以上がtkinterで簡単なGUIを作ってみた内容になります。

 標準ライブラリとして割と簡単にGUIが作れるのは便利だと思います。次はこの作ったGUIをexe化する方法を調べてみようかと思います。


・参考資料

【M5StickC Plus/Arduino】PIR Hat(人感センサ)に連動して音を出す

 以前の記事で人感センサのサンプルを動かしました。

 その最後で「人が来たら音を鳴らすおもちゃ」ができそうと書いたので今回はそれを作ってみた次第です。


 では、始めます。


1:M5StickC Plusで音を鳴らす
 M5StickC Plusではブザーが内蔵されているのでライブラリを使用することで簡単に音を鳴らすことができます。
 過去の記事でさらっと音を鳴らすコードを書いていたことはありましたが、自分の中でも整理するためにM5StickC Plusで音を出す方法をまとめます。

 音を鳴らす書き方は基本的には以下の通りです。

#include <M5StickCPlus.h>

void setup() {
  M5.begin();
  M5.Beep.setBeep(4000, 1000); // 初期値:音の高さ(Hz), 鳴動時間(ms)
}

void loop() {
  M5.update();
  M5.Beep.update();

  if (M5.BtnA.wasPressed()) {
    // 初期値の音を鳴らす
    M5.Beep.beep();
  } else if (M5.BtnB.wasPressed()) {
    // 一時的に設定した音を鳴らす
    M5.Beep.tone(2136, 500); // 音の高さ(Hz), 鳴動時間(ms)
  }
}

「M5.Beep.setBeep(4000, 1000);」のところでビープ音として鳴らす音の周波数と長さの初期値を設定し「M5.Beep.beep();」で初期値の音を開始します。loop内の「M5.Beep.update();」で音の鳴動時間を検知して音が止まります。
「M5.Beep.tone」で設定した音は一時的にその音と鳴動時間だけ鳴らします。M5.Beep.toneで音を鳴らした後に「M5.Beep.beep();」で音を鳴らすと初期値の音が開始されます。

 また今回は音を開始した後に「M5.Beep.update();」で鳴動時間を管理していますが、例えば関数内で順番に複数の音を鳴らしたい場合は「M5.Beep.update();」で管理できないので、適切にdelayを入れてやる必要があります。

 これで大体M5StickC Plusで音を鳴らす方法がわかったので、実際に人感センサに合わせて音を鳴らしてみます。


2:人感センサに連動して音を出すサンプル
 PIR HATのサンプルコードを少し改造してみたのが以下のものになります。

・M5StickCPlus_pir_buzzer.ino

#include <M5StickCPlus.h>

#define BEAT    150 // 一つの音を鳴らす時間(ms)
#define PIR_PIN 36  // PIR_HATのピン番号

bool pinFlg = false;

void setup() {
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0, 4);
  M5.Lcd.println("PIR STATUS");
  pinMode(PIR_PIN, INPUT_PULLUP);
}

void loop() {
  M5.update();
  M5.Beep.update();

  bool result = digitalRead(PIR_PIN);

  M5.Lcd.setCursor(110, 55, 6);
  M5.Lcd.println(result);

  if (!pinFlg && result) {
    // LOW -> HIGH
    callZeldaSound();
  }

  pinFlg = result;
}

// ゼルダの謎解き音
void callZeldaSound() {
  M5.Beep.tone(3136, BEAT); // ソ
  delay(BEAT);
  M5.Beep.tone(2960, BEAT); // ♯ファ
  delay(BEAT);
  M5.Beep.tone(2489, BEAT); // ♯レ
  delay(BEAT);
  M5.Beep.tone(1760, BEAT); // ラ
  delay(BEAT);
  M5.Beep.tone(1661, BEAT); // ♯ソ
  delay(BEAT);
  M5.Beep.tone(2637, BEAT); // ミ
  delay(BEAT);
  M5.Beep.tone(3322, BEAT); // ♯ソ
  delay(BEAT);
  M5.Beep.tone(4186, BEAT); // ド
  delay(BEAT);
}

 PIR HATを取り付けた状態で書き込むと、PIR STATUSの画面の値が0→1に変化した時だけ音が鳴るようになります。


 以上がM5StickC PlusでPIR Hat(人感センサ)に連動して音を出す方法になります。

 今回は簡単に内蔵のブザーを鳴らしましたが、MP3などのファイルを再生できるようにすれば人が来た時に「コンニチワ」みたいな挨拶をするような何かも作れそうですね。


・参考資料