天井にネジを使わずペット見守りカメラを設置する

猫のための見守りカメラを設置したい

以下の記事で書いたように、猫を飼い始めました。 moyashipan.hatenablog.com

自分が不在の際に猫の様子を確認できたら安心度が上がるなと思い、以下のカメラを買いました。
中国のOEM製品らしいので似たようなのがAmazonにたくさん出品されています。

専用アプリから上下左右の操作ができて、暗視モードも備えているのでとても便利です。
これで部屋全体を見回そうと思ったら、できれば天井付近に設置したいですよね。

天井にどう設置するか

カメラには「壁・天井に設置する用の簡単な土台パーツ」と「ネジ」が同梱されています。でも賃貸の部屋に穴は開けたくないので少し工夫が必要です。

僕の部屋の天井には、以下の記事で紹介したようにシーリングライト用のプラグから拡張したダクトレールが設置してあるので、それを活用することにしました。 moyashipan.hatenablog.com

電源供給のために、ダクトレール用の抜け止めコンセントも購入。

カメラ底面のネジ穴とダクトレールをどうつなぐか

カメラの底面には1/4インチねじ(カメラねじ)の穴が空いています。
それを利用して「ダクトレールに固定できて、カメラねじに対応している物」を探したところ以下を見つけました。
主にバイクのハンドル部分などにカメラを固定するために使われているようですね。

設置できた

それらを利用して全体を設置してみた様子が以下です。

f:id:moyashipan:20191019142253j:plain
ダクトレールに設置された見守りカメラ

こんな画が撮れる

動画はカメラに挿したmicroSDカードに保存され、ドライブレコーダーのように古いものから消えていくようにできます。
そのため、外出先から遠隔で閲覧するだけではなく、自分の在宅中に猫の可愛い動きがあった時にそれを確認・保存できます。

まとめ

既製品を組み合わせれば、天井に穴を開けずにペットの見守りカメラを設置できます。
見守りだけでなく、日々のペットの可愛い瞬間を逃さず記録しておけるのでオススメです。

エビオス錠をちょうど10粒取り出すスプーンを作る

f:id:moyashipan:20190816024202j:plain

はじめに

みなさん「エビオス錠」飲んでますか?
エビオス錠は1回に飲む量が10粒と指定されています。

【指定医薬部外品】エビオス錠 2000錠

【指定医薬部外品】エビオス錠 2000錠

ですが、毎回10粒を数えて取り出すのはけっこう手間です。
そのために以下のように錠剤を10粒取り出せるスプーンというドンピシャな製品があるようです。 すぐにその面倒を解決したい人はそれを買えば良さそうです。

ですが、せっかくなら自分用にカスタマイズしたスプーンを作って、創作欲も同時に満たしたいと思い、作ってみました。
この記事はその過程を振り返るものです。

木工版

まず木に穴を開けて試作

ドリルビットを付けた電動ドライバーで大雑把に穴を開けて、彫刻刀で微調整して丁度いい大きさを探りました。
ビンにザクッと突っ込んで少し振ると上手くハマって取り出せたので良さそうです。

木工版 完成

3粒でいけたので、10粒に増やしました。

便利。これだけでとても便利。

さらにフタに付けると便利だと気づく

使っていて、以下の2点に気づきました。

  • スプーンの置き場所に困る
  • 「錠剤の無い上の空間からだとビンにスプーンを突っ込みやすく、そこから穴の上に錠剤を乗せる」ためには、回転させる動作が必要

どちらもフタに付けることで解決するのでそうしました。
フタを開ける時に必然的に回転させるので、その動作のついでに錠剤が穴にセットされるわけです。

ただし、フタを閉じる時にスプーンをまっすぐ刺さないといけなくなりましたが、それは動画中で行っているようにビン全体を上下に振りながら行うことで解決しました。

なお、金属のフタへの接着は難しいかと思われましたが、紫外線で硬化する接着剤を試したらうまいこといけました。
一般的な瞬間接着剤よりも位置調整などのコントロールがしやすく、透明でそこそこ頑丈なので1本持っておくと便利!

柳瀬 グルーイット UV硬化 液体プラスチック接着剤 4mg GLIT

柳瀬 グルーイット UV硬化 液体プラスチック接着剤 4mg GLIT

3Dプリンター

以前から欲しいと思っていた3DプリンターAmazonプライムデーで安くなっていたのでこのタイミングで買いました。

Fusion 360モデリング

前述の木工版の穴の寸法を測り、Fusion 360モデリングしました。
無料 ソフト | Fusion 360 | オートデスク

3Dプリンターで出力

3Dプリンターすげー。
しかし初めての3Dプリンター出力だったため、錠剤が穴に入らないのだけは避けたいと思い穴を少し大きくしすぎました。

穴の大きさを探る

木工の時とは違って3Dプリンターは高い精度で複数のパターンを用意できることにここで気づいたので、8.0mm(錠剤の直径)から0.3mm間隔で10個の穴を用意して出力してみました。
これで適切な大きさがわかりました。

3Dプリンター版 完成

穴の大きさを修正している最中に「錠剤を穴に入れるための振る動作ももっと改善できるのでは」と思い、スプーンの左右に壁を作ってみました。
これにより、穴に入らなかった錠剤が左右へすぐにふるい落とされてしまうのではなく、スプーンの先へ向かって転がって行き、他の穴に入る試行回数が増えて10粒分の成功率がより完璧になったように思います。

まとめ

エビオス錠をちょうど10粒スッと取り出せるの便利!
そのためのプロトタイピングの手間が減る3Dプリンター便利!

なお「売れば?」とか「特許とったら?」みたいに言われたのですが、以下のように特許がすでにあるようなのでどちらも考えてません。「こうするといいぞ」ってのがわかる方がいたら教えて下さい。 astamuse.com

3Dモデルは以下で公開しています。
EBIOS Spoon by moyashipan - Thingiverse

猫用のIoT体重計を作る (ESP32+デジタルスケール+IFTTT)

家にややぽっちゃり猫が来た

2018年12月にタンジロウという黒猫の里親になりました。

黒猫タンジロウ

保護猫カフェ「ネコリパブリック中野店」の皆様、その節はありがとうございました。
エイズのキャリアを持つ猫達、通称「りんご猫」オンリーの保護猫カフェについては以下の記事がわかりやすいです。 petokoto.com

ただ譲渡の際に「タンジロウはぽっちゃり気味なのでエサをあげすぎないように」との注意がありました。
そこで、体重の増減を日々追えるように「猫が体重計に乗ったら自動で記録される仕組み」を作ってみました。

1号機は失敗作

できるだけハードウェアを作らない方針

自分で体重計というハードウェアを作るのは大変そうだと判断して、既存の体重計から値を取得する方法にしようと思いました。
ググってみると、Qiitaで以下の記事を見つけました。

qiita.com

早速、Amazonで同じ体重計を買ってみて設置してみた様子が以下。

この時の自分は「体重計の商品説明文には3kgから測定可能って書いてあったから、猫が5±2kgぐらいだから十分使えるだろう」と信じ切ったまま開発に進んでしまいました…。

前提を確認しないまま進んだ開発

体重計からの赤外線を受信してwebへPOSTするためにESP32の開発ボードを購入しました。

もともと持っていたラズパイ用キットの中にあった赤外線受光モジュールも使用。

赤外線が受信できて喜ぶ様子。

自分の体重で動作確認して、すべてが上手く作れたと思い込んでいる様子。

こうして仕組みができたのですが、実際にタンジロウが体重計に乗っても仕組みが反応しません。
それもそのはず。この体重計は実際には約6kgからしか測定できず、タンジロウの体重はそれ以下だったのです。

自分で作りながら、同じ仕組みをすでに作った以下の記事を見つけたのも運が悪かったです。
以下の記事に出てくる猫は体重が6.4kgあるので、この体重計でギリギリ測定可能だったんですね…。

next.rikunabi.com

ひとまず上記の体重計は「商品説明と食い違う」という理由でAmazonに返品・返金対応してもらえました。

2号機は方針を変えた

体重計の仕組みを知る

1号機は勢いで作ってしまって失敗しましたが、今回の猫用体重計に期待する点・要件をちゃんと洗い出してみました。大きく以下の3つです。

  • なんらかの方法で計測した値を取得できる。(できれば楽に取れると嬉しいけど)
  • 猫の体重を計測できるぐらい測定範囲の下限が小さい。体重計が(親切な機能として)一定以下の体重を無視しないこと。
  • もともと猫が乗るための形がある程度備わっている。ちょっとした工作で猫が乗れるようになる。

それらを考慮すると、体重計から都合よく発信される値を期待するのではなく、体重計に使われている「ロードセル」という部品に近い部分を自分で扱わなければならない・自分で扱ったほうが自由がきくように思われました。
そこで以下の3つを買い足しました。

最終的な仕組みには組み込まれませんが「ロードセルを使って重さを取得する」というのを実際に試しておきたかったのと、配線のお手本にしたかったのでキットを用意しました。

他のキッチンスケールは5kgまでの物が多かったですが、10kgまで計測できるらしいこれを選びました。 [asin:B079DJPLFX:detail]

(2022/09/09 追記)
その後の改良版では、A4サイズで広さがちょうど良く、2000円しない値段で買えるこちらの製品に置き換えました。
ただし、つなげ方やプログラムは本記事に書かれた内容から変える必要があるのでご注意ください。

そのキッチンスケールに含まれているロードセルからのアナログ信号を変換して取り出すためのAD変換モジュール。1つ目のキットの構成を見ていたおかげでこれが必要なこともわかりました。

キットで基本的な動作確認を行う

まずArduinoでHX711を使用する際のサンプルソースを以下からダウンロード。
HX711使用 ロードセル用ADコンバータ モジュール基板: 半導体(モジュール) 秋月電子通商-電子部品・ネット通販

キットと開発ボードを接続し、キットのロードセルの仕様に合わせた定格出力と定格容量をソースに記述し、プログラムを動かして正しい重さが取得できるのを確認できました。
正しい接続の仕方と、設定すべき項目があることを学べたので買っておいてよかったです。
(5VとGNDをうっかり逆に接続するとAD変換モジュールのチップが熱々になることも学べました)

また、サンプルソースがとても親切で、起動時に一定時間計測を行って、最初からはかりの上に乗せられている「風袋」分の重さを offset という変数に保持しておいてくれるコードがとても役に立ちました。
風袋とは - コトバンク

キッチンスケールをバラして利用する

購入したキッチンスケールは操作盤部分が外しやすく、ロードセルからの線も取りやすく、それぞれの線がどの役目かもわかりやすくなっていたのでとても助かりました。
ロードセルから基盤に繋がっていた線をニッパーで切り、AD変換モジュールに接続し、開発ボードに接続した様子が以下です。

キッチンスケール内のロードセルの仕様に合わせて、以下の値でプログラムを動作させたところ、正しく重さが計測できました!

定格出力 [V]: 0.001f
定格容量 [g]: 10000.0f

完成

できました。(キッチンスケールの上に接着剤で板を接着し、その上にタイルカーペットを接着しています)
これによりタンジロウの体重が約5.3kgだというのがわかりました。

以下には工夫した点を書きます。

猫のふるまいに対処する

人間でも書いてある注意書きを読まないなんてことがあったりしますが、猫の場合は動物なのでそもそもこちらの意図が伝わりません。彼らのふるまいを考慮・制御してあげる必要があります。
そこで以下のような工夫をしました。

  • そもそも毎日体重計に乗ってほしいので、エサを食べに来るのをきっかけに計測できるようにする。(毎日必ず来る)
  • 体重計に乗らずに横から食べてしまうのを防ぐための板(手前にある白い板)を設置
  • 外に足が出ている状態で食べて軽く計測されてしまうのを防ぐために、一定時間同じ値が検出され、かつ軽すぎなければ確定するようにした
  • 質感や温度が周囲の物と比べて明らかに違うと警戒する可能性があるので、周りに敷いてあるのと同じタイルカーペットを切って貼った

WiFiに再接続するためのコードを追加

ESP32を使っていて困ったこととして、起動してWiFiに接続してから一定時間は正しくHTTPリクエストが行えるのですが、だいぶ経ってからまたリクエストを行うためにWiFiの接続を試みると、延々と接続されずに接続確認のループが走るというものがありました。
Arduino関連のサンプルだと WiFi.status() をチェックするループしか無かったのですが、以下のように「失敗し続ける場合には一旦再接続させる」ようにしたところ解決しました。

WiFi.disconnect(true); // まず切断するほうが確実っぽい
WiFi.begin(SSID, PASSWORD);
Serial.print("WiFi connecting");

int count = 0;
while (WiFi.status() != WL_CONNECTED) {
  // このループが延々と繰り返される場合がある
  Serial.print(".");
  // LEDをチカチカさせて目でわかるようにする
  digitalWrite(LED_PIN, HIGH);
  delay(10);
  digitalWrite(LED_PIN, LOW);
  delay(90);

  if (++count > 100) {
    // 失敗し続ける場合には一旦再接続させると1,2回で成功する
    WiFi.disconnect(true);
    WiFi.begin(SSID, PASSWORD);

    Serial.println("");
    Serial.print("reconnecting");
    count = 0;
  }
}

Serial.println(" connected");
return true;

IFTTTと連携する

現在は、体重の計測が行われたら、Twitterへの投稿とGoogleSpreadSheetへの記録を行うようにしています。

方法は似たような工作を行った以下の記事を参考にしてください。 moyashipan.hatenablog.com

まとめ

  • キッチンスケールから配線を取り出してESP32に接続するとペット用のIoT体重計が作れる
  • 人間用の体重計でペットの体重を計測するときには計測可能範囲に注意する

(Hueいらず)天井にスマートスピーカーと連携した照明環境を実現する

この記事は以下のような人を対象としています。

必要な物

※2021/02/06追記: 現在は、アプリから制御しやすい以下の電球を使っています。

以上の製品を組み合わせて、こうじゃ!

f:id:moyashipan:20181104202956p:plain

手順

  • 天井にダクトレールを設置する
  • ダクトレールにEcho Dotを設置する
    • ダクトレールに抜け止めコンセントを接続する
    • 抜け止めコンセントにEcho Dot ホルダーを接続する
    • Echo Dot ホルダーにEcho Dotを接続する
  • ダクトレールに照明を設置する
    • ダクトレールにE26ソケットを接続する
    • E26ソケットに赤外線リモコン式電球を接続する
  • 部屋にNature Remoを設置する
  • Nature Remoに、電球のリモコン信号を覚えさせる
    • ON, OFF, 明るく, 暗く ぐらいでOK
  • Nature Remoに、照明を全灯させるシーンを追加する
    • 「点ける、明るく、明るく、明るく、明るく」のような操作をシーンとして登録する
    • シーンの名前は「ただいま」など
  • IFTTTに「もしAlexaに"ただいま"と言ったらRemoの"ただいま"シーンを実行」というAppletを追加する
  • Alexaに向かって「アレクサ、ただいま、トリガー」「アレクサ、ただいまをトリガー」のように呼びかけて、照明が全灯になることを確認する

応用編

"ただいま"で全灯にした後、寝る3,2,1時間前に1段階ずつ暗くして、寝る時間にはすべて消す、とすると自然に眠りへのモードに移行できて良いです。 寝落ちしちゃっても、明かりがついたまま寝なくて済むので、浅い眠りのまま朝をむかえるのを避けられますし。

FeliCaをタイムカードにする装置を自作する

きっかけ: 他社ではFeliCaをタイムカードにしているらしい

友人の話を聞いていたところ、どうやらFeliCaをタイムカードとして使う出退勤システムがあって、それを導入している会社がけっこうあるらしい。
たしかにググるといろいろ出て来る。

felica タイムカード - Google 検索 f:id:moyashipan:20170303000238p:plain

だけどうちの会社の出退勤システムは内製で、FeliCaには対応していない。

しかし、ビルの出入り用に配られているセキュリティーカードがどうやらFeliCa(正確には、なにかしらのNFCタグ)らしい。 (リーダーにかざす時にSuicaなどが近いと上手く動かなかったりすることからわかった)

そして、うちの出退勤システムは特にめんどうな認証などが無く、社内ネットワークからPOSTリクエストを送るだけで良い。

というわけでFeliCaで出勤する装置を作った

材料

Raspberry Pi 3

Raspberry Pi 3の電源とか

Raspberry Piスターターパック (Economy) - Pi3検証済

Raspberry Piスターターパック (Economy) - Pi3検証済

PaSoRi RC-S380

ソニー SONY 非接触ICカードリーダー/ライター PaSoRi RC-S380 : RC-S380

ソニー SONY 非接触ICカードリーダー/ライター PaSoRi RC-S380 : RC-S380

・ピエゾブザー

・ブレッドボードとか

作り方

こちらを参考に、ラズパイをセットアップしたり、nfcpyをインストールしたりします。
Raspberry PiでFelicaのIDmを表示する - Qiita

あとは、タッチした時にカードのIDm(固有ID)からユーザーを判別して、それにあった情報をPOSTするだけ。
FeliCa IDmとは? - 技術者向けNFC(FeliCa,Mifare)開発支援のNFC Developers'サイト

まぁ現状のユーザーは自分だけなんですが…。
コードはだいたいこんな感じ。

# -*- coding: utf-8 -*-

import binascii
import nfc
import time
import json
import requests
import RPi.GPIO as GPIO

class MyCardReader(object):
    # POST先
    trigger_url = 'http://YOUR_TIMECARD_SYSTEM_URL/'
    # カードのIDmとユーザーの対応表
    ids = {
        '0000111122223333' : { 'name': 'moyashipan' }
    }
    # ブザーが接続されたGPIOピン
    pin = 10
    buzzer = None

    def __init__(self):
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.pin, GPIO.OUT)
        self.buzzer = GPIO.PWM(self.pin, 1000)

    def on_connect(self, tag):
        print "touched"
        print tag
        # Type3のタグだけを受け付ける
        if isinstance(tag, nfc.tag.tt3.Type3Tag):
            self.idm = binascii.hexlify(tag.idm)
            self.post(self.idm)
        return True

    def post(self, id):
        if self.ids.has_key(id):
            user = self.ids[id]
            print user['name']
            
            # POSTする
            data = {
                'user_name': user['name']
            }
            res = requests.post(self.trigger_url, json=data)

            print(res)

            # 成功したらピー。失敗したらブーと鳴らす
            tone = 1000 if res.status_code == requests.codes.ok else 300
            self.buzzer.ChangeFrequency(tone)
            self.buzzer.start(10)
            time.sleep(0.2)
            self.buzzer.stop()
        else:
            print '未知のタグです'

    def read_id(self):
        clf = nfc.ContactlessFrontend('usb')
        try:
            clf.connect(rdwr={'on-connect': self.on_connect})
        finally:
            clf.close()

if __name__ == '__main__':
    try:
        cr = MyCardReader()
        while True:
            print "touch card:"
            cr.read_id()
            print "released"
    # ここらへんよくわかってない
    except KeyboardInterrupt:
        pass

出勤できました

ティッシュを消費したらTweetする装置を作った

冬はティッシュの消費量が増える季節です

体調の悪化をなにかしら数値化しておきたい。
鼻をかむ回数が増えるだろうからティッシュの消費量を追えばよさそう。

(あと余談ですが、最近DMM.comの月額動画を契約しました。)

すでにそういう製品があるのでは?

検索してみたけどそういう製品は見当たらない…。
ただ1件、ティッシュとセンサを組み合わせている方を見つけました。

www.jonki.net

そうそう、こういうの。
ここからwebへ何かしらPOSTすればよさそう。

ティッシュの消費量監視システムができました

消費したティッシュの枚数をTwitterにつぶやきます。

後ほどティッシュケースに装着するようにしました。

その結果、こんなTweet↓が流れます。

材料

工作の流れ

  • ティッシュを取り出すと上下するアームをレゴブロックで作る
  • GPIOピンに傾斜スイッチを接続し、傾きによって状態が0,1で変化するのを確認する
  • アームの先端に傾斜スイッチを取り付けて、角度を調整する
  • 取り出し時に、IFTTTのMaker Channel宛てにリクエストを送る
  • IFTTT側でそれをtriggerにして、Twitterへつぶやかせる

それぞれ解説していきます。

ティッシュを取り出すと上下するアームをレゴブロックで作る

試行錯誤しながら、とりあえず動くものを作る時にはレゴブロックが便利。
ギアやプーリーをベースとしたキットが販売されているのでそれを使いました。
http://amzn.to/2kiuv62

デイリーポータルZさんの以下の記事を見ると欲しくなるはず。 portal.nifty.com

今回の工作で作ったパーツは

  • アーム
  • アームを固定するための台座
  • アームが上がりきってしまわないようにするためのつっかえ棒

から成り立っています。

GPIOピンに傾斜スイッチを接続し、傾きによって状態が0,1で変化するのを確認する

以下のようなpythonのコードを書いて「値が0から1に変化したことを検知し、検知後1000ミリ秒間に再度検知しても無視する」ということを実現しています。

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

SWITCH_IO = 26
GPIO.setup(SWITCH_IO, GPIO.IN)

def switch_on(channel):
  # ONに切り替わったので何かする

GPIO.add_event_detect(SWITCH_IO, GPIO.FALLING, switch_on, 1000)

アームの先端に傾斜スイッチを取り付けて、角度を調整する

ティッシュを取り出して十分にアームが持ち上がった時に通電するように、さきほどのアームの先端に角度を調整しつつ傾斜スイッチを設置します。

冒頭の動画を見ると、ティッシュを引き抜いてアームが持ち上がった時にチカッとセンサーのLEDが光っているのがわかるかと思います。

取り出し時に、IFTTTのMaker Channel宛てにリクエストを送る

IFTTTは、各種サービスをtriggerとactionとして扱い、それらを自分好みに組み合わせてタスクの自動化を行えるサービスです。
直接Twitterへ投稿するプログラムをpythonで書いてもよかったのですが、手軽さと柔軟性を考慮してIFTTTを利用することにしました。

IFTTTのMaker Channelを利用することで、webhook URLへのPOSTリクエストをtriggerとして扱えるようになります。 そのための具体的な手順は以下のとおりです。

  1. IFTTTのMaker settingsにアクセス
  2. そこに表示されているURLをコピペしてアクセス
  3. curlで叩く例などが出て来るので、{event}の部分にtrigger名(今回はtissue_takenとしました)を入力して、そのURLをコピー f:id:moyashipan:20170206022114p:plain

そうして得られたURLに対してPOSTリクエストを行うコードを書きます。
こんな感じに↓

import json
import urllib2

data = { 'value1': num_of_tissues, 'value2': first_taken_at.strftime('%Y/%m/%d %H:%M:%S') }
req = urllib2.Request(trigger_url)
req.add_header('Content-Type', 'application/json')

urllib2.urlopen(req, json.dumps(data))

IFTTT側でそれをtriggerにして、Twitterへつぶやかせる

IFTTTに新しいAppletを登録します。
デバッグ中にTwitterに投稿してしまうと迷惑になるので当初は自分にDMを送るようにしました。
If Maker Event "tissue_taken", then send a direct message to @Moyashipan のようなAppletができていて、 ティッシュを取ることで自分にDMが届けば成功です。

そうして全体が上手く連携していることが確認できたら、actionをpost a tweet to @MoyashipanにしたAppletを作り、さきほどのAppletはOFFにします。
そしてティッシュを取ることで自分のアカウントでつぶやきが流れたら完成です。

工夫

複数枚取った後でまとめてtriggerさせる

ティッシュを1枚ずつ取るたびにTwitterへ投稿していては、短時間に複数枚取った場合に迷惑です。
そこで、1枚取ると15秒間のカウントが始まり、その間にさらに取ると15秒プラスされるようにしました。
そしてカウントがゼロになったら、カウント開始時からの枚数をまとめてValue1に格納してtriggerさせています。

こうすることで、たくさん消費する場合には通知までの時間が長引いてしまいますが、 そういう場合にはできるだけまとまった(大きな)数値が投稿されたほうがテンションが上がるだろうということでカウントを追加するようにしました。

問題点

デバッグの後で片付けが必要

水銀スイッチを使っている

傾斜スイッチは、水銀の入ったガラス管が傾き、水銀が導線に触れる事でスイッチがONになるというものです。
人体に有害なため生産されなくなったという物らしいので、他のスイッチを使ったほうが安全そうです。

まとめ

  • ラズパイとスイッチを繋げば、手軽に日常の動作の数値化ができる
  • IFTTTのMaker Channelを使えば、検知した後の動作は全部IFTTTに任せられるのでお手軽

ピエゾブザーで音を出す

ボタンを押した時は以下のような事をしてます。
序盤は「ピ・ピ・ピ…」と鳴って、動画の最後で「ブー」と鳴ったのは、
表示する文字数(cursor)が0の時には、低くて(500hz)長い(0.2秒)音を出しているから。

tone = 500 if cursor == 0 else 1000
delay = 0.2 if cursor == 0 else 0.1
buzzer.ChangeFrequency(tone)

buzzer.start(10)
time.sleep(delay)
buzzer.stop()

音の変化だけでもちょっと生命ある感が出てきてかわいい。

初めの頃、試しに音を流しっぱなしにしながらコードを書いていたら、 音が途切れたり揺れたりしたので「おいおい、そんなに安定した音って出せないもんなのー?」と思ったんですが、
どうやら、ssh接続したラズパイ上のvimでコードを書いていて、カーソルを連続して動かしたような時にそうなるみたい。

CPU負荷とか無線LANとかとの兼ね合いで電圧が変化するんですかね?