🐈

市販のロードセル4つの体重計をIoT化する(ネコ様用)

2021/05/23に公開

ネコ様のトイレのタイミングを監視したい

というのが当初の目的。
体重もはかれば、日々の健康管理にもいいかなと。

トレッタとか使えば正確で楽なんですけどね^^;
プログラミングの勉強も兼ねて。

重量センサーHX711を買ってきて・・・、というのが王道かと思いますが
バランスとか強度考えたり、試行錯誤が結構大変でした。

ヒト用の体重計の流用

で、最終的に行き着いたのが、ヒト用の体重計の流用です。

ベースはタニタのHD-660/661がいいですね。
https://www.amazon.co.jp/dp/B0052BPUCA/
私の方法だと天板が不要になるので、捨てやすいプラスチック製なのがいいです。
天板使うにしても、穴あけ加工とかしやすいですしね。
2000円くらいで重量センサー4つと150㎏まで耐える土台ももついてきます。
お得ですね^^

配線・加工

中開けるとこんな感じ。(表示板とか取り去った後で申し訳ない)
4隅の足それぞれがロードセル(重量センサー)になっています。

これを・・・こうして!

こうじゃ!完成!

雑・・・
要するに2つにぶった切り、いい大きさの板にねじ止めするだけですね^^;
手持ちのノコギリで切断しましたが、いい道具あるのかな。

4つのセンサーを統合する

赤いパーツは4つのセンサーをひとまとめにするロードセンサーコンビネーションというものです。
https://www.switch-science.com/catalog/2847/

センサーが4つついてるのでどう配線するのか苦労しました。
とくにこの赤いパーツについて日本語で説明しているところが見当たらなかったので配線してはテスト、を繰り返しようやく動作しました。
リンク先に組み立て例が書いてますけど、白と緑線の役割がよくわからなかった・・・

Cが緑、+が赤、-が白が正解でした

HX711とラズベリーパイの接続はこちらを参考にさせていただきました。
https://qiita.com/KZ2/items/5492e15cc15f766ca9bd

VCC - Raspberry Pi3 5V  Pin 2
GND - Raspberry Pi3 GND Pin 6 
DT  - Raspberry Pi3 GPIO#5 Pin#29
SCK - Raspberry Pi3 GPIO#6 Pin#31 

運用

ラズベリーパイをつないで、トイレの下に敷きます。
ネコがトイレに入ったら、体重と写真がSlackに通知されるという仕組みで運用しています。

このような感じで通知されます。

コード部分

使わせてもらったライブラリです。
https://github.com/tatobari/hx711py
ずいぶん前に作成したので当時はPython2しか使えませんでしたが、現在はPython3にも対応してますね。
example.pyをいじって作りました。

本職ではないため見苦しいコードかと思いますが、アドバイスあればお願いします。
特に下記の動作についてもっといい方法があるのでは・・・と思っています。

2秒ごとに測定したvaluesが、3回とも±200gだったら安定したとみなし、差分通知(カメラ撮
影指示、Slackとスプレッドシートへの投稿)と風袋引きを行う。

neko_scale.py
#! /usr/bin/python2
# -*- coding: utf-8 -*-

import time, sys, datetime, json
import requests
from slacker import Slacker

token = 'Slackのトークン'
c_name = 'neko_weight' # チャンネル名
slacker = Slacker(token)

post_url = 'スプレッドシートに書き込むためのURL(GAS使用)'
camera_url = 'ここにアクセスするとカメラが起動し、撮影画像をSlackへ送る'

# ネコ判定部分(もみじ以外の体重が横並びになってしまった・・・)
def neko():
    neko = 'unknown'
    if diff > 2900 and diff < 3500:
        neko = 'もみじ'
    # elif diff > 4200 and diff < 4700:
    #     neko = 'なつめ'
    # elif diff > 3700 and diff < 4200:
    #     neko = 'すだち'
    elif diff > 4700 and diff < 5200:
        neko = 'なつめすだちれもん'
    return neko


EMULATE_HX711=False
# ここで重さ補正
referenceUnit = 22.60

if not EMULATE_HX711:
    import RPi.GPIO as GPIO
    from hx711 import HX711
else:
    from emulated_hx711 import HX711

def cleanAndExit():
    print("Cleaning...")
    if not EMULATE_HX711:
        GPIO.cleanup()
    print("Bye!")
    sys.exit()

hx = HX711(5, 6)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit(referenceUnit)
hx.reset()
hx.tare()
print("Tare done! Add weight now...")

# ここからオリジナルの部分
values = [0,0,0]
tared = 0
idx = 0

while True:
    try:
        values[idx] = int(round(hx.get_weight(5)))
        hx.power_down()
        hx.power_up()
        time.sleep(2)

        print idx, values[idx], tared

        if idx > 0:
            if abs(values[idx] - values[idx-1]) > 200:
                idx = 0
                continue

        if idx == 2:
            diff = values[idx] - tared
            if abs(diff) > 200:
                tared += diff
                try: slacker.chat.post_message(c_name, str(diff)+'g')
                except: time.sleep(10)
                    
                post_data = {'time': str(datetime.datetime.now()),
                                'value': diff,
                                'neko': neko()}
                try:
                    requests.post(post_url, json.dumps(post_data))
                    requests.get(camera_url)
                except:
                    pass

                idx = 0
                continue

            else:
                idx = 0
                continue

        idx += 1
            
    except (KeyboardInterrupt, SystemExit):
        cleanAndExit()

Discussion