ロードセルで重量測定、Soracom harvestに送る


ロードセルで重量測定、Soracom harvestに送る

  • アマゾンで買ったロードセル(歪みセンサ、重量センサ)のデータをSoracom Harvestに送って、鉢植えの重量を監視してみました。

用意するもの

配線

WIO と AD module の接続

Wio 3GのD38ポートとAD moduleを以下のように接続して下さい。

WIO 3G D38 port AD module
GND GND
3V3 VCC
D39 DT
D38 SCK

AD module と ロードセル の接続

AD moduleとロードセルから出ているリード線を以下のように接続して下さい。

AD module Lord cell
E+ Red
E- Black
A- Green
A+ White

ハードの組み立て

  • 適当な板(硬めのアクリル板など)を用意します。
  • 下の板に3本の足を取り付けます。また、ロードセルの片側をM4ネジで取り付けます。この時、ロードセルの白いシリコンが板に触れないように厚めのワッシャーを噛ませます。
  • 上の板をのせ、M4ネジでロードセルを固定、同じようにワッシャーを噛ませます。
  • 実験ではアクリル3mm厚を使用しましたが、たわんでしまうので、重いものを量る時はもっと頑丈な板の方が良いと思います。
  • 載せる対象物の重心は上板のM4ネジ付近が好ましいですが、わざと隅に重りを置いても余り誤差は出ませんでした。


プログラム

以下の資料を参考にさせていただきました。
- 秋月電子さんのページ

#include <WioCellLibforArduino.h>
#define INTERVAL        (60000)       // 1分に一回送信します。
#define RECEIVE_TIMEOUT (10000)       // 受信タイムアウト
#define DAT WIO_D39                   // WIO 3GのD39ポート
#define CLK WIO_D38                   // WIO 3GのD38ポート
float offset=0;

WioCellular Wio;

void setup() {
  delay(200);
  SerialUSB.begin(9600);            // PCデバッグ用
  SerialUSB.println("start");
  pinMode(CLK, OUTPUT);             // D38を出力に設定
  pinMode(DAT, INPUT);              // D39を入力に設定
  offset = Read();
  SerialUSB.println("### I/O Initialize.");
  Wio.Init();                       // Wioの初期化

  SerialUSB.println("### Power supply ON.");
  Wio.PowerSupplyCellular(true);    
  delay(500);

  SerialUSB.println("### Turn on or reset.");
#ifdef ARDUINO_WIO_LTE_M1NB1_BG96
  Wio.SetAccessTechnology(WioCellular::ACCESS_TECHNOLOGY_LTE_M1);
  Wio.SetSelectNetwork(WioCellular::SELECT_NETWORK_MODE_MANUAL_IMSI);
#endif
  if (!Wio.TurnOnOrReset()) {
    SerialUSB.println("### ERROR! ###");
  return;
  }
    SerialUSB.println("### Connecting to \"soracom.io\".");
  if (!Wio.Activate("soracom.io", "sora", "sora")) {
    SerialUSB.println("### ERROR! ###");
    return;
  }
  SerialUSB.println("### Setup completed.");
}

void loop() { 
    float data;                             // ロードセルデータ
    char data_txt[100];                     // soracom送受信用バッファ
    char str_temp[10];                      // 文字列作成のためのワークエリア 
    data = Read();                          // ロードセルデータ取得                  
    SerialUSB.print(-data,2);SerialUSB.println("g");  // For debug
    dtostrf(-data, 4, 2, str_temp);         // データを文字列に変換して、
    sprintf(data_txt, "{\"weight\":%s}", str_temp);   // Soracom送信用文字列(json)に整形して、
    SerialUSB.println(data_txt);            // For debug
    SerialUSB.println("### Open.");
    int connectId;
    connectId = Wio.SocketOpen("harvest.soracom.io", 8514, WIO_UDP);    // Harvestに接続
    if (connectId < 0) {
      SerialUSB.println("### ERROR! ###");
      goto err;
    }

    SerialUSB.println("### Send.");
    SerialUSB.print("Send:");
    SerialUSB.print(data_txt);
    SerialUSB.println("");
    if (!Wio.SocketSend(connectId, data_txt)) {     // 送信
      SerialUSB.println("### ERROR! ###");
      goto err_close;
    }

    SerialUSB.println("### Receive.");
    int length;
    length = Wio.SocketReceive(connectId, data_txt, sizeof (data_txt), RECEIVE_TIMEOUT);  // 受信
    if (length < 0) {
      SerialUSB.println("### ERROR! ###");
      goto err_close;
    }
    if (length == 0) {
      SerialUSB.println("### RECEIVE TIMEOUT! ###");
      goto err_close;
    }
    SerialUSB.print("Receive:");
    SerialUSB.print(data_txt);
    SerialUSB.println("");

  err_close:
    SerialUSB.println("### Close.");
    if (!Wio.SocketClose(connectId)) {
      SerialUSB.println("### ERROR! ###");
      goto err;
    }

  err:
    delay(INTERVAL);
}

float Read(void){
    long sum = 0;
    for (int i = 0; i < 30; i++) {
        long data=0;
        while(digitalRead(DAT)!=0);
        for(char i=0;i<24;i++) {
            digitalWrite(CLK,1);
            delayMicroseconds(1);
            digitalWrite(CLK,0);
            delayMicroseconds(1);
            data = (data<<1)|(digitalRead(DAT));
        }
        digitalWrite(CLK,1); //gain=128
        delayMicroseconds(1);
        digitalWrite(CLK,0);
        delayMicroseconds(1);
        data = data^0x800000;

        sum += data;
    }
    float data = sum /30;
    float volt;float gram;
    volt =data*(4.2987/16777216.0/128);     // スミマセン。定数4.2987の意味はよくわかりません。
    gram=volt/(0.001*4.2987/5000.0);        // 5000=Load cellの定格5kg
    return gram-offset;
}

結果

[2019/5/4 修正] 一晩動かしたら色々と問題が確認されました。

  • 水分が蒸散している様子が見られるようです。 ロードセルの温度特性が悪い様です。
  • 振動もよく拾っています。(アクリル板の剛性が弱いため?) 原因不明ですが、(ほぼ)定期的なノイズが発生しています。
  • ロードセルを大きな定格に変えれば、もっと重い物を量ることも可能だと思います。 測定したい重量に合わせた定格を選択しないと温度特性含め、誤差が大きいです。また、精度を求めるならば、それなりに信頼性のある(高価な)ロードセル、アンプを使用する必要があるかもしれません。