ラズパイで作るペットの排泄検知システム

# はじめに
[Raspberry Pi Advent Calendar 2020](https://qiita.com/advent-calendar/2020/raspberry-pi
)の20日目です．

趣味で作ったペットの排泄検知システムについて書いていきます．
私は，フトアゴヒゲトカゲというオーストラリア原産のトカゲを飼っています．（[飼育日記](https://www.exotechblog.com/diy/no_saw_cage_reptiles)）
![image.png](https://www.exotechblog.com/wp-content/uploads/2020/04/IMG_4324-1024x768.jpg)
うんちをすることはそれほど多くなく，月に2〜3回程度です．
ただ，外出中などにうんちをされると，片付けるまでに時間がかかってしまうので，うんちをしたらわかるようなシステムを作ってみようと思いました．

# 実装した機能
目標は，うんちをしたらセンサで検知して，スマホに通知が来ることです．また，センサの出力値はあとで眺めたいので，何処かに保存しておきたいなと思いました，
そのために，ラズパイ上に以下の機能を実装しました．

- においセンサ
- LINEBotによるスマホ通知機能
- GoogleAppsScriptを作成し，センサー出力値をGoogleスプレッドシートに送信

# においセンサ
## 回路基盤
まずは，ラズパイににおいセンサ用の回路基盤を実装しました．実装する回路基盤は，[こちらの記事](https://fabcross.jp/category/make/sorepi/20171019_smell.html)を参考にしました．
使用したものもほとんど同じで，増えたのはラズパイ用ユニバーサル基盤とLEDくらいです．
全部，秋月電子通称で買い揃えました．

- 臭気センサ [TGS2450](https://akizukidenshi.com/catalog/g/gP-00989/) 1個
- ADコンバータ [MCP3002-I/P](https://akizukidenshi.com/catalog/g/gI-02584/) 1個
- トランジスタ [8050SL-D-T92-K](https://akizukidenshi.com/catalog/g/gI-10054/) (20V700mA) ２個
- 抵抗 270Ω 1kΩ 2kΩ 各1個
- [Raspberry Pi Zero用ユニバーサル基盤](https://akizukidenshi.com/catalog/g/gP-14031/) 1枚
- [ピンソケット](https://akizukidenshi.com/catalog/g/gC-00085/) 1個
- 適当なLED 2個
- LEDがいい感じに光る抵抗を何個か

回路基盤のイメージをfritzingで書きました．[参考にした記事](https://fabcross.jp/category/make/sorepi/20171019_smell.html)では，ブレッドボード上に実装していますので，そちらも合わせてご確認ください．
![スクリーンショット 2020-12-20 12.16.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496581/68520634-03e1-a8ea-180d-f011b59c0b49.png)
（左上の四端子の部品がにおいセンサ，右上の三端子の部品2個がトランジスタ，下の二端子部品2個がLEDです．
ピンソケットを使って，直接ラズパイにはんだ付けで固定せず，においセンサ基盤だけモジュール化しました．
LEDは家にあったものを適当につけたので，適宜良さげなものをつけてください．そのための抵抗も大きめの抵抗から抵抗値を少しずつ下げて試して行って，いい感じに光るものをつけました．）

コンパクトに実装できて満足しています．
![S__165576734.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496581/47ec46e4-dcc9-0749-8aca-6147b279f131.jpeg)


## プログラム
プログラムは，pythonで実装しました．ソースコードを[こちら](https://github.com/kumagaimasahito/unko-detector/blob/master/src/unkoDetector/unkoDetectorByLineNotify.py)に置いておきます．

```python
import spidev
# src/unkoDetector/util/spiModule.py
def setup():
    spi = spidev.SpiDev()
    spi.open(0,0)
    spi.max_speed_hz=1000000
    spi.bits_per_word=8
    return spi

# src/unkoDetector/unkoDetectorByLineNotify.py
from measure import measure
from util import spiModule, LINENotifyBot
import RPi.GPIO as GPIO
import time
import os
from tqdm import tqdm
import requests

def main():
    # Execute the following command in advance on the shell.
    # export "LINE_NOTIFY_KEY"=<YOUR_ACCESS_TOKEN>
    access_token = os.environ["LINE_NOTIFY_KEY"]
    bot = LINENotifyBot(access_token=access_token)
    bot.send(message = "においの検出を開始しました")
    
    # Setting up a Google spreadsheet to enter sensor data
    # export "GAS_URL"=<YOUR_GAS_URL>
    gas_url = os.environ["GAS_URL"]

    # Setting of GPIO pins
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17,GPIO.OUT)
    GPIO.setup(22,GPIO.OUT)

    ch0 = 0x00
    spi = spiModule.setup()
    judge = False
    trial = 100
    outlier = 20
    threshold_list = [0]*trial
    scaling = 0.25

    # Warming up to remove outliers．
    print("ウォームアップを開始します")
    for i in tqdm(range(outlier)):
        GPIO.output(22,True)
        time.sleep(0.005)
        GPIO.output(22,False)
        GPIO.output(17,True)
        time.sleep(0.008)
        GPIO.output(17,False)
        time.sleep(0.237)
    print("ウォームアップが終了しました")

    # Trials for Threshold Determination.
    print("基準値の測定を開始します")
    for i in tqdm(range(trial)):
        GPIO.output(22,True)
        time.sleep(0.005)
        ch0_val = measure(spi, ch0)
        GPIO.output(22,False)
        GPIO.output(17,True)
        time.sleep(0.008)
        GPIO.output(17,False)
        time.sleep(0.237)
        val = 1023 - ch0_val
        threshold_list[i] = val
    threshold = sum(threshold_list) / len(threshold_list)
    #bot.send(message = "基準値を" + str(threshold) + "に決定しました．")
    print("基準値を" + str(threshold) + "に決定しました")

    try:
        while 1:
            GPIO.output(22,True)
            time.sleep(0.005)
            ch0_val = measure(spi, ch0)
            val = 1023 - ch0_val
            GPIO.output(22,False)
            GPIO.output(17,True)
            time.sleep(0.008)
            GPIO.output(17,False)
            time.sleep(0.237)
            print(val)
            requests.get(gas_url + "?data=" + str(val))
            if val > threshold*(1.0+scaling) and judge == False:
                judge = True
                bot.send(
                    message = "出たよ！！",
                    image = "/home/pi/Laboratory/unkoDetector/src/unkoDetector/photo/mafuyu.jpeg"
                )
            elif val < threshold*(1.0+scaling) and judge == True:
                judge = False
                bot.send(
                    message = "片付けてくれてありがとう！！",
                    image = "/home/pi/Laboratory/unkoDetector/src/unkoDetector/photo/latte.jpeg"
                )

    except KeyboardInterrupt:
        GPIO.output(22,False)
        GPIO.output(17,False)

    spi.close()

if __name__ == "__main__":
    main()
```

基本的な流れは，
1. においセンサを使うためにGPIOピンのセットアップ
2. においセンサの起動
3. 基準値となる現在のにおいレベルを測定
4. においの測定を繰り返し，全てのセンサ出力値を記録
5. 基準値を大幅に超えたら通知

## LINEBot
LINEBotの通知機能は，[こちらの記事](https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9)で紹介されている，LINENotifyBotのclassをそのまま拝借しました．

## GoogleAppsScript
GoogleAppsScriptによるGoogleスプレッドシートへの記録は，[こちらの記事](https://jellyware.jp/kurage/raspi/google_spreadsheet.html)を参考に実装しました．

# 実際に動かしてみる
今回は，執筆中にフトアゴがうんちをしてくれなかったので，家にあった臭そうなものでテストしました．
実運用ではラズパイZeroを使いますが，テストにはラズパイ4を使いました．

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Qiita Raspberry Pi Advent Calendar 2020のためにペットの排泄検知システムを作った動画です．<br>あとで記事が出たら，ぶら下げます．<a href="https://t.co/d7adqvxUZr">https://t.co/d7adqvxUZr</a> <a href="https://t.co/MFkgc4sNt5">pic.twitter.com/MFkgc4sNt5</a></p>&mdash; Masahito Kumagai (@MasahitoKumagai) <a href="https://twitter.com/MasahitoKumagai/status/1340536143691968514?ref_src=twsrc%5Etfw">December 20, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# おわりに
今回は，ラズパイを使ってフトアゴ用のにおいセンサを作ってみました．
うちの子もクリスマスプレゼントをもらってうれしそうにしています！！
![S__165576728.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496581/3af8766a-b12f-7628-6039-aa648f6804cd.jpeg)