なくなりそうになったら購入時期を教えてくれるスマートスケール【Obniz・RaspberryPi】

使っているときには、そろそろなくなりそうだなと思うのですが、一旦その場を離れてしまうと購入することをつい忘れてしまうことが多くないですか。

それを通知してくれるような仕組みがないかなと思ってobnizで制作してみました。ついつい買い忘れるものをスマートスケールの上を置き場にしておけば常に監視して、購入時期を教えてくれます。購入通知も仕事終わりなどの時間帯で通知するようにしておけば、買い物の忘れもすくなくなるでしょう。プラスして内容をアマゾンの商品購入URLを送るようにしておけば、ワンタッチで購入もできます。Amazonダッシュボタンに似てるな。

youtu.be

システム概要

  • 適応対象:5kg以下の重さがわかるもの。使用により重さが変化するもの(お米、洗濯洗剤、台所洗剤、トイレットペーパー、シャンプー等)
  • 操作方法:センサーに乗せておく。事前に新品時の重さと補充時の重さの設定が必要
  • 拡張性:LINE Notify送信先をグループに設定することで、より購入の忘れを防ぐことができる。重複購入防止策のために、補充されたこともLINE Notifyで送信することも考える(一人暮らしようには不要)

使用した部品

部品 説明 ・備考
obniz Board / obniz Board 1Y obniz
RaspberryPi 3B Node.jsを実行するホスト
HX711センサー 電子スケール ロードセル計量センサ
デジタル・マイクロサーボ SG90 重量をアナログ値で表示

重さを量るセンサーは以下のものを使用

f:id:ueponx:20210714162105p:plain

使用したネットワークサービス

サービス名 備考
LINE Notify 連携したWebサービスからの通知を公式アカウントである「LINE Notify」から受信できるサービス

LINE Notify

f:id:ueponx:20210714162257p:plain

Node.jsライブラリ

ライブラリ名 内容
line-notify-nodejs LINE Notifyライブラリ
node-cron Node.js内でcronのような定時実行を行うライブラリ

システム構成図

構成図

f:id:ueponx:20210714162155p:plain

ソースコード

LINE Notifyを使用した通知は9時と18時に行うように指定しています。node-cronを使用することで、設定もcron同様に行うことができています。このライブラリは非同期で動作するようになっていて、時間設定のタイミングで動作してくれます。

cron.schedule('0 0 9,18 * * *', async function () {
  console.log("計測処理開始!");

ソースコード内の---LINENotifyトークンを入力---に関してはこのエントリーでは触れませんが、サービス登録時に表示されるトークンを入力してください。 同様にOBNIZ_ID_HEREのところにはお持ちのobnizのデバイスIDを入力してください。

また通知のトリガーとなる重さはソースコード内のconst triggerWeight = 40; //gとしているように40グラムを下回ったときに通知が行われます。

ソースコード

var Obniz = require("obniz");
//lineNotifyのトークンを入力する
const lineNotify = require('line-notify-nodejs')('---LINENotifyトークンを入力---');
const cron = require('node-cron');

//ObnizのデバイスIDを入力する 
let obniz = new Obniz("OBNIZ_ID_HERE");

let value = 0;
let weight = 0;
let weightMessage = "";
let sensor;
let servo;

const WeightMAX = 400; //g
const triggerWeight = 40; //g

obniz.onconnect = async function () {
    //hx711 設定
    sensor = obniz.wired("hx711" , {gnd:0, dout:1, sck:2, vcc:3} );
    sensor.setOffset(-8231198); //デバイスごとに調整が必要
    sensor.setScale(480.0); //デバイスごとに調整が必要
    //SG90 サーボ設定
    servo = obniz.wired("ServoMotor", {gnd:4,vcc:5,signal:6});
    servo.angle(0);

    //hx711 計測
    value = await sensor.getValueWait(10);
    weight = numberValueRound(Math.abs(value), 0.01);
    weightMessage = "残りの重さは" + Math.abs(weight) + "gです。";
    console.log(weightMessage);
    
    //SG90 サーボ制御
    servo.on();
    angle = weight / WeightMAX * 180;
    servo.angle(angle); 
    await obniz.wait(1000);
    servo.off();
}

cron.schedule('0 0 9,18 * * *', async function () {
  console.log("計測処理開始!");

  //hx711 計測
  value = await sensor.getValueWait(10);
  weight = numberValueRound(Math.abs(value), 0.01);
  weightMessage = "残りの重さは" + Math.abs(weight) + "gです。";
  console.log(weightMessage);
  
  //SG90 サーボ制御
  servo.on();
  await obniz.wait(1000);
  angle = weight / WeightMAX * 180;
  servo.angle(angle); 
  await obniz.wait(1000);
  servo.off();
  //console.log(angle,weight);

  //送信メッセージの作成
  if(weight < triggerWeight){
    //LineNotify送信
    lineNotify.notify({
      message: "そろそろ無くなりそうですよ。購入しましょう!" + weightMessage
    })
  }
  console.log("計測処理完了!");
});

//指定桁の四捨五入
function numberValueRound(value, base) {
  return Math.round(value * base) / base;
}

実行の様子

コンソールでの実行の様子

f:id:ueponx:20210714162514p:plain

LINE Notifyでのメッセージ通知

f:id:ueponx:20210714162536p:plain

食器洗剤を計測

f:id:ueponx:20210714162608p:plain

おわりに

ロードセルのキャリブレーションが結構大変でしたが、一度経験すれば大した作業ではありません。調整するのであれば1円玉が何枚かある方が調整がしやすいと思います。この程度の歪で重さって計測できるんだなと思ってかなり感心しました。電子ばかりも基本的には似たような構造なんでしょうね。

今回はobnizを使用して作成していますが、RaspberryPiだけでもいけるかな?後日試してみようと思っています。

ちなみにネットを検索すると以下のようなものが出てきた…orz

/* -----codeの行番号----- */