HX711と歪ゲージで作ったはかりの安定性を調べているのですが、異常値が結構な頻度で測定されます。
はかりに何も物をおかない状態で重さを測定し、測定値をクラウドサービスのAmbientに送信して、長期の安定性をモニターしているのですが、異常値が頻発しています。
大きな異常値
これは、測定開始から1日経過したときの、重さの測定値の変化です。青が測定された重さの値。赤はバッテリー電圧です。
はかりには何も置いていないので、0gとなるのが正しいのですが、1日のうちでも結構変動しているのがわかります。
はかりは、日光の当たる場所に放置してあるので、日が当たったり陰ったりして温度が変化し、測定される重さも変化していると思われます。
そういったゆったりとした重さの変化の中に、たまに、-15g以上の大きな異常値が測定されていることがわかります。これでは、数gの郵便物のあり、なしを判断する際に大きな障害となります。
そこで、HX711の測定値の異常値やノイズをどうにかして消す方法を模索しました。
ダミーの計測処理を入れる
これまでの処理の流れは以下のようになっています。
- DeepSleepからの目覚め
- 初期化
- 重量測定
- 値のAbientへの送信
- DeepSleep
HX711は、重量を測定し結果をリードする時に、次の測定のパラメータを送信する仕組みになっています。今回使っているHX711のライブラリを見ると、初期化時にはパラメータの送信が行われていませんでした。そのため、HX711のパラメータが正しくセットされていない可能性があります。
そこで、プログラムを
long value = scale.get_units(1); //dummy measurement value = scale.get_units(20);
と、メインの測定の前に、1回だけダミーで測定するようにしてみました。
すると...
大きな異常値が測定されることがなくなりました。HX711の初期化が正しくされていなかったために、正しい値が測れない場合があったようです。
しかしながら、今度は12:00あたりに小さなノイズがしばらく続いているのがわかります。
今度は、この小さなノイズを対策してみます。
測定回数を増やす
HX711は10Hzで測定するモードと80Hzで測定するモードがあります。そこで、測定周期を短くして、たくさん測定して平均回数を増やすことで、ノイズが減るかを調べてみます。
モジュールの右上に10Hzと書いてあるところに0Ωが実装されており、その左に80Hzと書いてあり未実装のパッドがあります。この0Ωの抵抗を、10Hzから80Hzへ引っ越すことで、測定周波数を80Hzに変更することができます。
80Hzモードにしました。
80Hzモードにしましたが、測定周期は4倍程度に速くなるだけでした。HX711との通信の時間は短縮されないためでしょうか。そこで、平均する回数を5回から4倍の20回に増やして、1日データをとってみました。
上のグラフが、改造前を後のグラフです。小さなノイズは以前に比べて小さくなりましたが、消えることはありませんでした。どうやら平均の回数を多くしても、小さな異常値は消えきれないようです
異常値を排除する
平均の回数を増やしてもノイズが消えないので、異常値を除去する方法を考えました。
以下のように仮定します。
- 3回測定して少なくとも2回は正常値が得られる
- 異常値は正常値よりも大きいか小さい
そこで、プログラムは以下のようにします。
- 3回重さを測定する
- 3回の結果を、重い順に並び替える
- 一番重い値と、一番軽い値には異常値が入っている可能性があるので除外する
(3つのうち真ん中の重さを採用する)
実際のプログラムはこちらです。
//Measurment Weight long value = scale.get_units(1); //dummy measurment double weightTemp[3]; value = scale.get_units(8); weightTemp[0] = (double)(value) * 0.1; value = scale.get_units(8); weightTemp[1] = (double)(value) * 0.1; value = scale.get_units(8); weightTemp[2] = (double)(value) * 0.1; //sort double weight; if( weightTemp[0] < weightTemp[1] ) { weight = weightTemp[0]; weightTemp[0] = weightTemp[1]; weightTemp[1] = weight; } if( weightTemp[1] < weightTemp[2] ) { weight = weightTemp[1]; weightTemp[1] = weightTemp[2]; weightTemp[2] = weight; } if( weightTemp[0] < weightTemp[1] ) { weight = weightTemp[0]; weightTemp[0] = weightTemp[1]; weightTemp[1] = weight; } weight = weightTemp[1]; //select a center value
このプログラムに変更してからの測定結果はこちらです。
小さなノイズがなくなり、綺麗な波形になりました。
12:00くらいにやはり小さな小さなノイズはありますが、測定誤差は1gくらいにはなったのではないでしょうか。
2021.4.4 追加
さらに2日間データを取ってみました。
どうしても、小さいノイズは残ってしまいました。単発のノイズは取り除きにくいようです。
追加 終わり
長期測定して分かったこと
7日間通して連続して測定して分かったことは、日や時間によって重さが変化してしまうということです。1日のうちに12gも変化する日もありました。このため、重さが何gになったから郵便物が届いたと判断するということができません。一つ前の測定値から、何g増えたというような、差分を比較して郵便物が届いたと判断する必要がありそうです。
2020.4.5 追加 つづきはこちら

追加終わり
コメント