猫用の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体重計が作れる
  • 人間用の体重計でペットの体重を計測するときには計測可能範囲に注意する