タイトルめちゃくちゃ端折ってるんですが、猫が排泄をしたらLINEに体重と排泄物の重量を通知するトイレの下に敷く板を作りました。
思い立ち
猫の体重をはかるのって結構面倒なんですよね。自分で体重はかって、猫を抱えて体重はかって、電卓で引き算してアプリに登録って感じです。トイレ乗ってるときにできればなーとずっと思ってたんです。
すでにあった…と思いつつも、1.5万円+サブスクかー、しかも首輪してた方がいいとなると…(うちの子は首輪してない)。というわけで、あれ?これ頑張ったら自作できるのでは??と思って作り始めたのがきっかけです。他にもSHARPのもありますが、こちらもサブスク必須になっています。
構成
今までラズパイ、ESP32は使ったことあって、ラズパイの方がsshで接続できるんでいろいろ楽なんですが電力的なコストも高いので、今回はm5stackのAtom Liteを使ってみることにしました。以前ESP32の素に近いやつを使って温湿度CO2センサーは作ったことがあるのですが、今回はお手軽な感じにしたかったので、押しやすいボタンやRGB LEDも付いてるAtom Liteを選びつつ、UIFlowを使ってGUIプログラミングもしてみることにします。
重量センサー
重量センサーには、m5stack用の重さセンサーユニットと、ロードセルなどと呼ばれるひずみセンサーを組み合わせました。コーナンで買ってきた木板に3Dプリンタでマウントを自作してネジ止めし、そこにセンサーをはめ込んでリード線を半田付けします。1個50kgいけるらしいので、4個で200kgですが、200kgの力士が乗ったら板が割れそうです。マウントの設計をミスってセンサーがキツキツだったんですが、出力に6時間かかるのでもういいやと諦めてとりあえず完成。正直このマウントは3Dプリンタで作るか、なければ木工で頑張るかになる気がします。
すげー雑ですけど、プロトタイプということで、もう1個のトイレ用はちゃんとしたいと思います。ひとまず、リード線の半田付けと熱収縮チューブでの絶縁はしてます。諸事情で尿的な液体がかかる可能性があるのでお店で貼ってたシュリンクラップそのままにしてます。
ちなみに、↑の配線でやったら計測値がマイナスで出てしまうようになりまして…どっかの配線が逆になっている気がしますが面倒くさいから絶対値にすることにして逃げてしまいました。運用でカバーする典型的な良くないやつですが自分用なのでヨシ!としました。
こんな感じの厚さです。木板もうちょっと薄くてもいけるかもですが、たわみで誤差が出るかも…猫的に違和感はなさそうです。
重さセンサーはこれですね
A/D変換
重さセンサーからAtom Liteにデジタルデータを送るのにA/D変換が必要ですが、m5stack用の重さセンサーユニット(真ん中にある白とオレンジの部品)で済ませます。Atom Lite(左の方にある灰色のやつ)とは付属のケーブルで接続できるので楽ちんでした。重さセンサーとは、リード線の先端をはんだで良いあんばいにして端子に接続します。↓これです。
Atom Liteは↓です。
というけで、Atom Lite1,500円、ロードセル3,000円、重さセンサーユニット550円、木板800円で6,000円ぐらいかかります。ロードセルが意外と高いんですよね…あと、電源が必要なのでAC→Type Cに給電できる何かが必要になります。バッテリー給電も試してますが、常時Wi-Fiつなぎっぱの富豪運用をしてると結構モバイルバッテーリの消耗が早いです。必要なときだけ接続するようにそのうち変更しつつ、ACアダプタ運用にしたいです。
スイッチサイエンスさん、いつも発送早いのでありがたいです。
プログラミング
猫のトイレは、重量可変要因がものすごくたくさんあります。
- トイレの掃除のため重量がゼロになったり一気に増えたりする
- 猫が乗る
- 乗るときも一気にではなく片足から突っ込んだりする
- 排泄すると、排泄物の重量が元の重量に加算される
プロダクションレベルのものみたいにいろいろな条件を考慮すると要件が野心的になって確実に実装できないので、まずは簡単なプログラムにすることにしました(一応僕は元来ディレクターであってエンジニアではないのです)。いやー、Catlog Boardの開発の人はすごいな…と思いました。
- トイレの重量を考慮するのが面倒なので、掃除したらAtom Liteのボタンを押してゼロ校正することにする(本当は一定時間の重量変化とかで自動でゼロ校正したかったけど沼になるので後回しにした)
- 重量センサーがたまにものすごいぶっ飛んだ数値を吐いてくるので、異常値を取り除く必要がある
- 排泄が終わったらIFFFT経由でLINEに通知を送る
- 前後の重量差を記録しておくことで排泄した重量も通知に含める
- 最後にリセットして次の排泄に備える
ツッコミどころが色々ありますが、まずはLINE通知と何となくの体重が記録されました。
全体像はこんな感じになってます。とりあえず作ること優先だったのでこれから精度上げたり綺麗にしたりしたいです。デバッグ用にシリアル出力が入ってるのでもうちょっと短くできそう。GUIでポチポチコード書けるの非エンジニアにとって非常にありがたいです。
なお、デバッグ時は閾値を少なくしてペットボトルを乗せたり降ろしたりして試行錯誤しました。
GUIのプログラミングって初めて使ってみて、言葉の壁が越えられたり命令のスペルミスがなくなりますし、すごいなー!と思ったんですが、反面、結局変数の定義や型への気配り、ループからの離脱処理などはコード書くのと一緒なので、「誰でも簡単にできる!」っていう感じではなかったです。これでノーコード!とか言うのは違うかも。でも、非エンジニアにとっては直感的に処理がわかるのと、うっかりミスが減って良かったです。
苦労したポイント
とりあえずセンサーからはgではなくよくわからない数値が飛んでくるので、家のキッチンスケールではかったペットボトルなどを乗せて、よくわからない数値を何倍にしたら正確な重量になるかを計算し、それを変数にセットしておきます。いちいち計算するのはアホらしいので関数化してしまえばOK。
センサーの異常値を取り除く処理ですが、面倒なのでとりあえず100msごとに20回(つまり2秒に20回)測定した数値の中央値を1回分として出力する関数を作って、それを配列にすることにしました。配列を評価して最大値と最小値の差が閾値(とりあえず猫トイレよりも重く、猫より軽い4kgにした。つまり4kg以上のものが乗ったらの条件)を超えたら排泄ループへ移動します。
排泄している最中はより厳格な測定数値にするため、20秒計測した中央値を1回分としてリストに出力するようにしています。ほんとはソートして上下3つのデータ消してとか中央値にするといいんだろうけど、UIFlowでこのやり方が見つからんかったのでとりあえずやっつけでこうしました。手でコード書いたらいけそうです。この配列から最大値(猫の体重)、最小値(猫の排泄物の重量)を計測するようにしました。ただ、20秒だと長すぎて正確に測れてない予感がするので今後変更予定。また、片足突っ込んで後始末したりするので最大値は信頼性高いけど、最小値の信頼性は低そうです。このあたりも改善できればって感じですね。
再び、猫が降りるのを検知するために最大値と最小値の差でループを抜ける処理をします。最大値や引き算で猫の体重と排泄物の重量を割り出しつつ、うちは5.2kgと6.2kgの猫がいるので、体重差の閾値を設定しておくことで猫判別を実装し、最終的に割り出した体重と猫の名前、排泄物の重量をJSONに渡してIFFFT→LINEで通知を出します。最後にいろいろなデータをゼロにして待機用のループに戻ります。猫砂も同時に吹き飛ばされてしまうので排泄物の重量は参考値となります。
どうもほっとくとセンサー値がずれていくようで、猫の体重が減っていきます。良いあんばいにリセットするようにしたいです。
あとそもそも、GUIでプログラミングできてもこういった処理は自分の脳で実装考えないといけないので、そういうハードルはなかなか下げられないんだなとも思いました。
残課題
もうちょっと精度を上げたいので、定期的なゼロリセットと測定ロジックの見直しをしたいです。筐体自体も、Atom Liteを木板にマウントした都合上、リセットボタンを押すときに気をつけないと押下した重量込みでゼロリセットされてしまうので、何とかしたいのですがAtom Liteを別のところにつけるぐらいしか思いつかないので、リセットボタンをあまり押さないで運用できるようにした方が良さそうです。
Atomにカメラを追加して、排泄中の写真を撮ってどっかにアップロードし、URLをLINEに渡すってのは結構簡単にできそうでしたが、そこまでするのも猫に失礼なのでやめとこうかとおもいました。
ESP32で温湿度CO2センサーを作ったときに、自分のサーバにデータをPOSTしてMySQLに貯めるAPIを作ったので、これを応用して猫の体重とウンコの重量をMySQLに貯めてGrafanaで可視化といったことは簡単にできそうです。さらにZabbix使って体重の閾値を超えたらアラートとかもできそうですね。
その後
精度
計測ループ内では10秒の中央値を出すようにしたのですが、ちょっと短すぎて排泄物の重量の精度が低いようです。15秒でもいいかなーとも思いますが、ひとまず10秒のまま。体重計で測った数値と比べていますが、わりと精度は高いです。また1時間に1回、乗ってるもの無視してゼロに校正するようにしました。タイミングが最悪(トイレ掃除中)じゃなければ特に問題ない感じです。
2個目
2個目も作りました。ロードセルのマウントをサイズ調整した以外はめんどくさくてプロトタイプのままですが、両方とも同じ係数でそこそこの精度が出てるみたいです。2個目も同じソースコードを使っており、通知に区別はないです。面倒な運用の手間がないので非常に楽です。
キャリブレーション
やはり、センサーの数値にいくらかけると実際のグラムになるかという係数のキャリブレーションが気になります。現状ハードコーディングしているので、いい感じに自動的にできたら汎用性の高いソースコードになるのでは?というところ。うちで買った2セットのロードセルは同じ係数でもそこそこの精度になっているのでいいのかな?と思いつつ、床材の性質によってもちょっとは変わってきそうなので猫の体重に近い数値でキャリブレーションしてあげると精度もあがるのかなと思ったりしています。
うちはクッションフロアとフローリングの2箇所に置いているのですが、100gぐらい数値が変わってるので、床材にあわせたセンサーのキャリブレーションができると精度が高まりそうです。