読者です 読者をやめる 読者になる 読者になる

HX711で重さを量る

ハカリなど重さを量るには、一般的にロードセルとひずみゲージセンサーを使って実現している。HX711 は安価なひずみゲージを読み取るためのICで、24bit ADCを搭載していて、ICにクロックを送ることでデータを受け取る。ebay では実装済の物が一つ100円以下で買える。

ロードセルは単体で買っても、ロードセルを設置ことが大変。その辺のハカリをバラすと入っているし、そのまま設置できるので大変楽。ロードセルにはVDD/GNDと、ひずみゲージの+-の線があるので、それをHX711のE+(VDD),E-(GND)、A+, A- (チャンネルAを使う場合)に接続すればOK。

HX711 用ライブラリ

Arduino 用はあるけど、mbed 用でちゃんと動く物がなかったので書いた。

HX711 hx711(dataPin, clockPin);
hx711.setScale(100000f); # ひづみゲージにや電源よって最適な値は異なる
hx711.tare();
float gram = hx711.getGram();

で動く。HX711 の仕様書を読んだメモ

https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/hx711_english.pdf

  • DOUT が LOW になったら準備完了
  • 同期に用いる PD_SCK にあわせて 24bit 分のデータをDOUTから MSB で出力する
  • その後のPD_SCKでのHIGH/LOWの回数にあわせて、次回のゲインが決まる
    • 標準は 128 (1回のHIGH/LOW)
    • CH A を使う場合は 128 もしくは 64
    • CH B を使う場合は 32 をセットする。
# HX711.hpp

#ifndef HX711_h
#define HX711_h

#include <mbed.h>

const float defautScale = 490000.0f;
const float lbToGram = 453.5f;

class HX711
{
  private:
    DigitalIn dataPin;
    DigitalOut clockPin;
    uint8_t gainPulse;
    uint32_t offset;
    float scale;
  public:
    HX711(PinName dataPinName, PinName clockPinName) :
      dataPin(dataPinName), clockPin(clockPinName, 0)
    {
      offset = 0;
      gainPulse = 1;
      scale = defautScale;
    }

    void tare() {
      offset = avg(10);
    }

    const float getOffset() {
      return offset;
    }

    float readGram(uint8_t times = 10) {
      float res = (float)avg(times) - offset;
      return res / scale * lbToGram;
    }

    uint32_t avg(uint8_t times = 10) {
      uint32_t res = 0;
      for(uint8_t i = 0; i < times; i++) {
        res += read();
      }
      return res / times;
    }

    bool isReady() {
      return dataPin == 0;
    }

    void setGainPulse(uint8_t _gainPulse) {
      gainPulse = _gainPulse;
      read();
    }

    void setScale(const float _scale) {
      scale = _scale;
    }

    const float getScale() {
      return scale;
    }

    uint32_t read() {
      uint32_t res = 0;
      uint8_t i = 0;

      while (!isReady());

      for(i = 0; i < 24; i++) {
        clockPin = 1;
        res = res << 1;
        clockPin = 0;
        if (dataPin == 1) {
          res++;
        }
      }

      for (int i = 0; i < gainPulse; i++) {
        clockPin = 1;
        clockPin = 0;
      }

      res ^= 0x00800000;
      return res;
    }
};

#endif