Help us understand the problem. What is going on with this article?

飼い猫が抱っこ嫌がって体重が量れないからネコベッドに24時間秒単位で体重を計測できる体重計を作ったら、猫の睡眠時間と「睡眠時の水分発散量」っぽい物が計測できた。

動機

うちの猫はかわいい:relaxed:。1歳、しろきじ、前の飼い主が飼えなくなって最近来た。

今回の主人公
Image from iOS (3).jpg

Image from iOS (1).jpg

とにかく抱っこが大っ嫌いだ。なのでよほどのことがなければ抱っこなんてしない。
だから体重が量れない!
爪が切れない!!(寝ているときにそっと切らせてもらう)

抱っこがダメな猫のために、良い体重の測り方はないものか??

市販の体重計は使えないのか?

普通に乗ることがない:joy:
餌を置いても、体重計をONにすると逃げる。
遠くにいると体重が見えない:sob:
オートオフ機能:sob:
WIFIでとばす体重計があるらしいが、いつ乗るかわからんしね:sob:

体重量るのがめんどくさくなってしまう。:sob::sob:

かわいい猫よ!!!人類の英知をなめるなよ!!抱っこしなくても体重くらい量ってやる!

ってことで、産業用、研究用なら24時間重さを計測するなにか変な物があるはずや!!
それが・・・意外とないんですよね。。
「上皿自動秤」「ばねばかり」が一番それに近いんです。アナログだし24時間量ってるようなもんだし・・・
カメラ仕込めば24時間量れるなぁ・・っと
でもこれブニョブニョして猫がいそうなところに仕込めないんですよ。そもそも小さいし・・
物理的に負荷が延々かかっている状態って校正必要になるしなぁ・・・

重量センサーってないんですかね?って検索するとあるわ!。

image.png

こんな感じの金属

これから出る電圧をプリアンプ通してPCのオーディオインプットに入れたらいけるんじゃね??
96Khz24bitという無駄なサンプリングレートで体重を計測しまくるんや!!
(そもそもローカットされて入力されないじゃん!)

ってことでADコンバータにつなげる何かを・・・・そしたら
「ロードセル専用のA-DコンバータHX711」ってすげーー便利なもんがあるんですよ。
そうよね。。。あるよね。。センサーだもん。
AMAZONで早速購入!
「デジタルロードセル重量センサ20KGポータブル電子キッチンスケール HX711計量センサーモジュールArduinoと互換」

image.png

組み立て

Image from iOS (2).jpg
いろいろ準備とかすっ飛ばしてこんな感じです。
20年ぶりくらいの電子工作ですよ!

ひさしぶりの半田付け・・・おっさんには・・こまかいっす。

余っていたRaspberryPiを使います。

AMAZONクオリティーなので配線図?とかデータシートとか一切なし。基盤透かして確認しました。

秋月電子でちゃんとしたの買ってください。安いし。。

1時間ほどしらべて、チップのどの足がどれにつながっていればいいか、やっとわかりました。。
(こちとら素人なんだよ:sob:

んで・・
Image from iOS (5).jpg

くみたて、なんでグルーガン?ってのは・・・・この板に取り付けたからです。

Image from iOS.jpg

400*350の板に設置したら、ユラユラでかさ上げしないと接地しちゃうんです。
かさ上げにはナットを使ってるんですが、この設置個所だと一度ナットを積み上げないといけないのでグルーガンです。

で・・・・
https://github.com/tatobari/hx711py.git
をcloneして校正して・・・
qiita的にここが重要だろう!!と思いますが他のqiitaの記事にあるのでそこは書きません。:hugging:
今回は「猫と体重計」です!!:relaxed:

取得したデータをElasticsearchへ送ってKibana で確認。

image.png

一秒単位のグラフです。
猫があそんでるときに、たまたま計測した:blush:
世界で一番しょうもないと思われるElasticsearchとKibanaの使い方です。:blush:

なにも重さがかかってないときでも、+-4gほどノイズが乗るんですよ。
さらに最大20グラムの大きな波が30分間隔であるっぽい。

ここからが本題

このままだと、ユラユラでブニョブニョしてロードセルにしっかりと荷重がかからない。
ユラユラ揺れるので猫が乗らないという実用に耐えられない体重計が出来上がってしまいました。

↓無荷重
1234556.jpg

↓荷重あり
Image from iOS (1).jpg
ぐにゃ~:joy::joy::joy:

これじゃぁー人間の体重計にもならん。

工作中にたまたま獣医師さんが見に来て、
「なにやってんすか(笑)」
「だっこできないから・・・人類の英知で・・・:sob:
「ねこの体重そんなに量らなくていいですから!(笑)」
というやりとりをする:sob:

本気出すぜ

もうここまで来たら引き下がれません。4ポイントでささえます。
秋月電子へ発注!

秋月電子のHX711は秒10回のサンプリング固定みたいです。
1枚で2つのロードセルを接続できます。

Image from iOS (4).jpg
このターミナルって部品がね・・よくわからなくて。。ジョイントできるんですよ。
1枚はしらなくて無理やりくっつけた。

Image from iOS (3).jpg
いろいろすっ飛ばしてこんな感じです。
困ったときのダクトテープです!
DIYだ!!

original - コピー.jpg

1234.jpg
RaspberryPiの設置部分がなくて・・・収まりどころが悪くて・・・
ノミで削って・・・ノミの刃が切れなくて苦しかった。
こんな感じです。

プログラム

上記のgithubのソースを変えていきます。

hx = HX711(5, 6)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit_A(104.2003)
hx.set_reference_unit_B(-24.513)

hx.reset()

hx2 = HX711(13, 19)
hx2.set_reading_format("MSB", "MSB")
hx2.set_reference_unit_A(103.3425)
hx2.set_reference_unit_B(-23.62031)
hx2.reset()

hx.tare_A()
hx.tare_B()

hx2.tare_A()
hx2.tare_B()

while True:
    try:

        val_A = hx.get_weight_A(5)
        val_B = hx.get_weight_B(5)


        val_C = hx2.get_weight_A(5)
        val_D = hx2.get_weight_B(5)

        val=val_A+val_B+val_C+val_D
        print(val, val_A, val_B, val_C, val_D)


        hx.power_down()
        hx.power_up()
        hx2.power_down()
        hx2.power_up()

        time.sleep(0.8)

    except (KeyboardInterrupt, SystemExit):
        cleanAndExit()


2枚のHX711を使うので、二つのインスタンスを作ります。
4ポイントあるので合算します。

実際に使ってみてわかったこと

  • hx711のデータシートを見るとBチャンネルはおまけみたいな感じでgain32固定です。
  • 英語の理解が正しいかよくわかりませんがBチャンネルを使うには5Vを入力しろって書いてあります。
  • Bチャンネルの入力は逆相になってる。(だからマイナスが返ってくる)
  • Bチャンネルのgainが小さいからreferenceUnitが小さい

バグ

https://github.com/tatobari/hx711py/blob/master/hx711.py
のコードが間違っているので修正します。

    def get_reference_unit(self):
        return get_reference_unit_A()

selfがないので

    def get_reference_unit(self):
        return self.get_reference_unit_A()

こんな感じで修正。

完成!!

bbb.jpg
黄色バスタオルの下に設置してます。
この時のわが猫の体重↓

image.png

3700グラム付近を指しています。
寝始めから1時間後に20グラムほど軽くなってます。これは水分が抜けているのか??20グラムの波なのか??

猫がこのベッドで寝ている時間が分かるのでスゴイなぁ:blush:
ちょっと前に獣医師のところに行って量ったときは3666グラムでしたので誤差ですね。(餌とか水分とか)

久しぶりに半田つかったので楽しかったです。:relaxed:

追記:設置から48時間ほど経過したデータ

image.png
ねる場所すべてに設置したくなります。:grin:

image.png
10グラム毎のヒストグラム(回数)です。3690グラムが一番多い:grin:
良い分布してる:relaxed:

追記2019-12-14 : 設置から1週間くらいたった

日ごとのデータをヒストグラム化した

image.png

横軸にグラム、縦軸にそのグラムを計測した回数。
計測回数が多いバケットほど正しいと思われる。
これなら猫の体重変動を余すことなく把握できる。

ベッドにいる時間の計測

image.png

簡単に出せるので分単位を日ごとに出してみました。
0の行は3500グラム以下(ノイズだし)を0に変えています。
朝5時30分にはニャーニャーうるさいので、この時間は決まって起きちゃうんでしょう。:blush:

1分でも計測した場合ベッドに居たことにしてベットにいる時間を合計してみます。

  • 2019/12/09,372分,6.2時間
  • 2019/12/10,460分,7.6時間
  • 2019/12/11,646分,10.7時間
  • 2019/12/12,771分,12.8時間
  • 2019/12/13,570分,9.5時間

これは最低でもベッドに居る時間なので、ほかで寝てる時間はわからないが・・
すやすや寝てダラダラと幸せに過ごしてほしい:blush:

2019/12/15 追記:ロードセルの大きな波の原因は・・・

ノイズではなく温度ではないか?。:thinking:

image.png

18:00に暖房をONにしてどんどん重さが上がっていき
19:15あたりの温度が26.5度、熱いので暖房をOFFにした時刻
20:00過ぎの温度が22度、こりゃ温度だな。

2020/01/02 追記:ロードセルに温度計張り付けて誤差を修正する

「Raspberry Pi DS18B20」 で検索するとワラワラでてくるので、ラズベリーパイで計測できるようにする。
DS18B20は1信号線で温度が計測できる。
parasite power modeという電源と信号線を共通で使おうと思ったら85000というエラー値が取れるだけでダメだったのでVDD,DQ,GNDを素直に接続して、プルアップ抵抗4.7KをDQ,VDDの間にいれた。

あとはコマンドをたたいて接続を確認する

#
sudo vi /boot/config.txt
#以下の設定を書き込む
dtoverlay=w1-gpio,gpiopin=4,pullup=no

sudo reboot

#w1の確認
lsmod | grep w1

#DS18B20の確認、28で始まるのがDS18B20
ls /sys/bus/w1/devices/

#温度を確認
cat /sys/bus/w1/devices/28-00000xxxxxx/w1_slave

pullup=noのpullupってのはpullup抵抗のことじゃないみたい。
信号線と電源を共通で使いたい場合に設定するみたい。
たぶん??電源を充電して信号を送り出すのでリアルタイム性がなくなるんだと思う。
今回は素直につないだのでnoにした。

↓DS18B20の足を半田付け&チューブで覆う
金属の菅に入っているのもあるんだけど、ロードセンサーにペッタリつけたいのでこんな感じのやつにした。
Image from iOS (3).jpg

↓ユニバーサル基盤で2個のDS18B20をつなげる。
(VDDとGND逆につなぐと一気に高温になって持ってられないので注意!)
Image from iOS (2).jpg

↓ダクトテープすげぇぇオシャレ。:relaxed:アメリカンスタイル!!!!:relaxed:
123456.jpg

↓センサーの合体!!
Image from iOS (4).jpg
センサーの結合にはインシュロックが一番具合がよかったです。

PYTHONプログラムはこちらの方
https://qiita.com/masato/items/cf5a27af696a27b73b86

の記事をコピペしました。

複数のセンサーに対応するので、ちょっと変えます。
↓どこをどう変えたかわからないので全部!

# -*- coding: utf-8 -*-
import os
import glob
import time
import subprocess

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')


def read_temp_raw(deviceId):
    base_dir = '/sys/bus/w1/devices/'+deviceId
    device_file = base_dir + '/w1_slave'
    catdata = subprocess.Popen(['cat',device_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out,err = catdata.communicate()
    out_decode = out.decode('utf-8')
    lines = out_decode.split('\n')
    return lines

def read_temp(deviceId):
    lines = read_temp_raw(deviceId)
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw(deviceId)
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
        #temp_f = temp_c * 9.0 / 5.0 + 32.0
        return temp_c

w1.pyで保存

温度と重さの関係をしらべる計測

アルミは金属なので温度で歪む。歪むから重さが変わる。
金属の歪って数百グラム載せただけじゃ誤差やろ?(歪パワーすごすぎて)と思い、無負荷でおこなった。
やったことは・・・正月なので・・そとに出して、部屋に入れれば行って来いでなんか取れそうなので・・・
外にだして5度くらいまで冷やす。そのあと部屋の中にいれて25度付近まで温めるという作業をしました。

image.png

↑横が温度。縦がA/Dの生値の散布図

きれいな直線とにフニャフニャした線がみえる:rolling_eyes:
よくわからん。。がなんか傾いてる。。

:expressionless::expressionless::expressionless::expressionless:

全体重さと温度を時系列でだしてみる。
image.png

:rolling_eyes:なるほど・・・ロードセルが温度の影響を受けるのに時間がかかるんだ。。。
だから、温度と重さの相関がいい感じではないんだ。ゆっくり温度が変化していくか、温度を固定させるしかない。:joy:
セル毎にいい感じの部分だけをとりだして・・・・・・とは行かない。
セル毎にやるなら、4セル全部に温度センサーを結合しないとダメなやつなので
温度センサーとこの体重計全体の重さのいい感じの部分だけを散布図に起こす。

image.png

あら・・きれい。
疑似曲線を描いて、数式をだして・・・・2.9613って数字がでました。
ねんのためにSLOPE関数でも確認して1度あたりの重さの傾きは2.96132とでました。

温度の影響を打ち消すプログラム

重さを取る部分と混ぜる

import w1

start_temp = (temp_a+temp_c)/2

while True:
    #重さとる
    val_A = hx.get_weight_A(5)
    val_B = hx.get_weight_B(5)


    val_C = hx2.get_weight_A(5)
    val_D = hx2.get_weight_B(5)

    val=val_A+val_B+val_C+val_D
    print('w',val, val_A, val_B, val_C, val_D)
    #温度とる
    temp_a = w1.read_temp('28-00000a72xxxx')
    temp_b=0.0
    temp_c = w1.read_temp('28-00000a72yyyy')
    temp_d=0.0

    dif_temp=  ((temp_a + temp_c) / 2)-start_temp
    #+方向だと1度あたり2.96132重くなる
    print('補正前,補正後,補正値',val,val-dif_temp*2.96132,dif_temp*2.96132)

やってみてわかったこと

  • 全部のロードセルにつけたかったのですが、DS18B20にリード線付ける半田付けが死ぬほどめんどかったので2個にしました。:joy:
    2個あれば個体差確認できるやろ?くらいな感じでした。
    ちなみに、DS18B20の個体差はわかりませんでしたがロードセルが温度に影響する個体差はあるようで・・・
    ちょっと全部に取り付けないと精密に温度によって変化する重さを吸収できないなぁーという感じです。

  • ロードセル毎に無負荷状態生値がすごい違う。(283000、150000くらい違う)

  • 温度を足したり割ったりしてるのがすごい気持ち悪い:scream::scream::scream:
    けど・・・どうして美しい回帰直線(2.96132)がでるんだろう?温度範囲が狭い?0~80度までとったら、グニャグニャしてるんだろうか?

おまけのうれしいこと

思わぬことで、部屋の温度もKibana で管理できるようになった。:relaxed::relaxed::relaxed:

image.png

正月から何してんだろう。。。

2020/01/05 追記:ロードセルは温度補償されてるらしい

傾きを追い込んでみたら、うまく行かなった。というより悪くならなかった。

image.png

温度が下がっても重さが変わらないポイントがある。

補正がかかってるのかな?
調べてみたら温度補償というらしい。
秋月電子の「ロードセル シングルポイント(ビーム型) SC133 20kg」にそれがあるのかわからないけど・・・上のグラフを見る限り温度補償されてる??

なので、プログラムから温度補正の計算を外したほうがいい結果がでそうだ。

そもそも製品精度のスペックがでてるんだろうか?
秋月電子の説明には、「精度:0.05%(フルスケールに対して)」とあるので、20Kgの0.05%は10グラムになる。
載せている重さが307g、上のグラフでは283.2gが下限なので、誤差23.8gになる。
4ポイントで支えているので5.95gの誤差。
温度影響を受けて5.95gなのでスペックでてるじゃん!:relaxed:

20Kのセルよりもっと小さい重さをはかれるセルにしたほうが良いってことですね。。

mokoenator
(´,,・ω・,,`)AIサービス作ってます AIファッション検索サービス https://funnel-service.com/
https://funnel-service.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした