部品 · 読了まで16分

HX711とArduino:ロードセルの配線、キャリブレーション、デジタルはかり

HX711とArduinoの配線、ロードセルの線の色、50 kgセル4個の接続、風袋引きとキャリブレーション係数、不安定な値の直し方、LCD・OLED・ESP32・Picoのコードを解説します。

HX711とArduinoの組み合わせは、ロードセルのマイクロボルト単位の信号を読み取り、グラム単位の重さに変える、最も定番で安い方法です。キッチンスケール、体重計、養蜂箱のはかり、ペットの餌皿モニター、モーターの推力測定台は、どれも同じ考え方で動いています。ロードセルが重さで目に見えないほどわずかにたわみ、HX711がその小さな変化を24ビットの数値に変え、Arduinoがキャリブレーション係数でその数値をグラムに換算します。

このガイドでは、ロードセルの中のホイートストンブリッジのしくみ、線の色の意味(E+、E-、A+、A-)、体重計から取り出した50 kgのハーフブリッジセル4個の配線方法、HX711ライブラリを使った風袋引きとキャリブレーション係数の求め方をステップごとに学びます。続いて、LCDと風袋引きボタン付きのデジタルはかりを作り、値がふらつく原因と安定させる方法を確認し、最後にESP32とOLEDディスプレイ、Raspberry Pi Pico(MicroPython)でも同じことを行います。

HX711ロードセルアンプモジュール
HX711モジュール:片側にはロードセル用のE+、E-、A-、A+端子(さらに2つ目のチャンネル用のB-、B+)、反対側にはArduinoにつなぐGND、DT、SCK、VCCピンがあります。

ロードセルとは?そのしくみ

ロードセルは、ひずみゲージを貼り付けたアルミや鋼の部品です。ひずみゲージは薄い箔にジグザグの模様でエッチングされた抵抗で、金属が伸びると配線が長く細くなって抵抗が上がり、縮むと抵抗が下がります。この変化はとてつもなく小さいものです。ゲージ率が約2のゲージでは、1000分の1のひずみで抵抗はわずか0.2%しか変わりません。1000 Ωのゲージなら2 Ωで、通常のanalogRead()ではまず検出できません。

この小さな変化を測れるようにするため、4つのひずみゲージをホイートストンブリッジとしてつなぎます。ブリッジは、2つの分圧回路を並べただけのものです。電源はE+とE-の間に入り、A+とA-は2つの分圧回路の中点です。負荷がないときは4つの抵抗が等しいので、両方の中点は同じ電圧になり、出力はゼロです。負荷をかけると、2つのゲージが伸び、2つが縮みます。片方の中点が上がり、もう片方が下がります。左の分圧回路の上下の抵抗をR1とR2、右の分圧回路の上下の抵抗をR3とR4とすると、出力はVout = Vexc × (R4/(R3+R4) − R2/(R1+R2))で、重さに比例して大きくなります。分圧の考え方は分圧回路の計算ツールで試せます。

ロードセルのラベルにある1 mV/Vのような数値は感度です。定格容量のとき、励起電圧1 Vあたり1 mVを出力するという意味です。HX711モジュールはブリッジを約4.3 Vで駆動するので、5 kgのセルは5 kgのときでも4.3 mVしか出さず、1グラムあたりではわずか0.86 µVです。そのため、ゲイン128の専用の24ビットADCが必要になります。

負荷(5 kg、1 mV/Vのセル)ブリッジの出力HX711の生の値(ゲイン128)
0 g0 mV0(風袋引き後)
100 g0.086 mV≈ 43,000
1 kg0.86 mV≈ 429,500
5 kg(定格容量)4.3 mV≈ 2,147,000

表には注目すべき点があります。生の値は電源電圧に左右されません。HX711はブリッジに供給する電圧(AVDD)を測定の基準電圧としても使うため、電源が少し下がると、ブリッジの出力も同じ比率で下がり、結果は変わりません。これをレシオメトリック測定と呼びます。大まかな目安として、1 mV/Vのセルの定格容量は約2,147,000カウントに相当します。これをセルの容量(グラム)で割ると、おおよそのキャリブレーション係数が得られます。1 kgで≈ 2150、5 kgで≈ 430、20 kgで≈ 107です。

HX711モジュールとは?仕様

HX711は、Avia Semiconductorが計量用に作った24ビットのシグマデルタ型ADCです。プログラマブルゲインアンプ(PGA)、ブリッジに給電するレギュレーター、内蔵発振器を備え、独自のシンプルなシリアル通信で、わずか2本の線で外部とやり取りします。この通信はI2Cではありません。DT(DOUT)線がLOWになるとデータの準備ができた合図で、ArduinoはSCK線に25〜27個のパルスを送り、24ビットを1つずつ読み取ります。パルスの数で次の読み取りのチャンネルとゲインが決まります。25パルスはチャンネルAでゲイン128、26パルスはチャンネルBでゲイン32、27パルスはチャンネルAでゲイン64です。

項目値
分解能24ビット、2の補数(0x800000〜0x7FFFFF)
チャンネルAゲイン128(±20 mV)または64(±40 mV)、AVDDが5 Vのとき
チャンネルBゲイン32で固定(±80 mV)
サンプリングレート10 SPS(RATE = GND)または80 SPS(RATE = VCC)
電源2.6〜5.5 V
電流1.5 mA未満、パワーダウン時は1 µA未満
ブリッジの励起電圧(E+)一般的な緑のモジュールで、5 V入力のとき約4.3 V
安定までの時間電源投入、復帰、ゲイン変更の後に400 ms(10 SPS)
インターフェース2線:DT(データ)とSCK(クロック+パワーダウン制御)

安い緑のモジュールのほとんどは、基板上でRATEピンがGNDにつながっているので、1秒に10回読み取ります。10 SPSはノイズが少なく、50/60 Hzの商用電源のノイズも除去できるため、ほとんどの場合、計量には最適です。SCK線が60 µsより長くHIGHのままだと、HX711はパワーダウンモードに入り、ブリッジへの給電も止めます。電池で動くプロジェクトでは、power_down()とpower_up()関数でこれを活用できます。

ロードセルの種類:どの容量を選ぶ?

1 kgのバー型ロードセル
1 kgのバー型(ストレートバー)ロードセル:中央の2つ穴のある薄い部分がたわみ、そこにひずみゲージが貼られています。ラベルの矢印は力の向きを示します。
種類容量線の数主な用途おおよその係数(カウント/g)
バー型、フルブリッジ1 kg4アクセサリー、手紙、精密なキッチンスケール≈ 2150
バー型、フルブリッジ5 kg4キッチンスケール、ペットの餌皿≈ 430
バー型、フルブリッジ20 kg4小包、荷物、植木鉢のはかり≈ 107
ハーフブリッジ(体重計のセル)50 kg(4個で200 kg)3体重計、養蜂箱測定して求める
S字型50 kg〜1 t4吊りはかり、引張力ラベルのmV/Vによる

容量は、測る最も重い荷物の約1.5倍を選びましょう。容量が大きすぎると分解能が下がります。20 kgのセルでも50 gの手紙は量れますが、5 kgのセルより4倍粗い値になります。ただし、小さなセルに過負荷をかけるほうが問題です。バー型のセルは通常、容量の約120%までは安全ですが、150%を超えると金属が永久に曲がり、二度とゼロに戻らなくなることがあります。合計の容量は、重さを分担するセルの数でも決まります。四隅に置いた50 kgのセル4個なら、合わせて200 kgまで支えられます。

線の色とHX711の配線

ロードセルの線HX711の端子役割
赤E+ブリッジの励起(+)
黒E-ブリッジの励起(−)
白A-信号(−)
緑A+信号(+)
HX711のピンArduino UnoESP32Raspberry Pi Pico
VCC5V3V33V3(OUT)、36番ピン
GNDGNDGNDGND、38番ピン
DT(DOUT)D2GPIO 25GP15、20番ピン
SCK(PD_SCK)D3GPIO 26GP14、19番ピン
HX711はI2Cデバイスではありません。DTとSCKをA4/A5につなぐ必要はなく、I2Cスキャナーで見つかることもありません。コードに正しい番号を書けば、この2本の線はどのデジタルピンにもつなげます。ESP32とPicoでは、モジュールを必ず3.3 Vで給電してください。緑のモジュールではVCCがDT線の信号レベルも決めるため、5 Vで給電すると3.3 Vの入力に5 Vがかかります。

色はメーカーによって異なることがあります。黒の代わりに黄、緑の代わりに青を使うセルや、白と緑の役割が入れ替わっているセルもあります。確実に調べるには、テスターを抵抗レンジにします。励起のペア(E+、E-)と信号のペア(A+、A-)は通常どちらも約1000 Ωで、組み合わせを交差させたペアはその4分の3ほどになります。信号線を逆につないでも何も壊れません。重さを載せると値が下がるだけです。線を入れ替えるか、キャリブレーション係数をマイナスにすれば直ります。B+とB-は2つ目のチャンネル用で、セル1個のプロジェクトでは使いません。

50 kgのハーフブリッジロードセル4個の配線(体重計)

体重計に入っている、中央がE字型の50 kgのセルには、ひずみゲージが2つと線が3本しかないため、1個でブリッジの半分です。線はたいてい赤、白、黒ですが、中点の線は必ず測定で見つけてください。外側の2本の間は約2 kΩ、中央の線と外側の各線の間は約1 kΩになります。ほとんどのセルでは中点が赤です。4つのセルを輪のようにつなぐと、完全なホイートストンブリッジになります。

  1. 台の四隅にセルを置き、角に1(左前)、2(右前)、3(右後ろ)、4(左後ろ)と番号を付けます。
  2. 隣り合うセルの同じ色の外側の線同士をつなぎます。1と2の白、2と3の黒、3と4の白、4と1の黒です。
  3. 対角にあるセル1とセル3の赤の線をE+とE-につなぎます。
  4. もう一方の対角のセル2とセル4の赤の線をA+とA-につなぎます。
  5. はんだ付けの前に測定します。E+とE-の間、A+とA-の間がどちらも約2 kΩになるはずです。値が大きく違う場合は、どこかの接続が間違っています。
  6. 重さを載せると値が下がる場合は、A+とA-の線を入れ替えるか、マイナスの係数を使います。
セル(角)白の線黒の線赤の線
1 – 左前2の白へ4の黒へE+
2 – 右前1の白へ3の黒へA+
3 – 右後ろ4の白へ2の黒へE-
4 – 左後ろ3の白へ1の黒へA-
セル2個でもはかりは作れます。1の白と2の黒、1の黒と2の白をつなぎ、この2つの接続点をE+とE-に、2本の赤の線をA+とA-につなぎます。セル1個の場合は、1 kΩの抵抗2本でブリッジを完成させます。外側の線をE+とE-に、赤の線をA+に、直列にした2本の抵抗の中点をA-につなぎます。抵抗はテスターで選び、値が最も近い2本を使ってください。差が大きすぎるとHX711が飽和します。セルの数が少ないほど、温度によるドリフトが大きくなります。

HX711ライブラリのインストール

  1. Arduino IDEで「ツール」>「ライブラリを管理」を開き、検索欄にHX711と入力します。
  2. Bogdan NeculaのHX711 Arduino Libraryをインストールします。ライブラリのインストールが初めてなら、Arduinoライブラリの追加方法ガイドをご覧ください。
  3. インストール後、「ファイル」>「スケッチ例」>「HX711 Arduino Library」にHX711_basic_exampleとHX711_full_exampleのスケッチがあります。下のコードでも同じ関数を使います。
関数働き
begin(dt, sck, gain)(初期化)ピンを設定する。gainの初期値は128(チャンネルA)
is_ready() / wait_ready_timeout(ms)新しい値の準備ができたか確認する。タイムアウト版はモジュールがなくてもプログラムが止まらない
read() / read_average(n)24ビットの生の値、またはn回の平均を返す
tare(n)n回の平均をゼロ点(オフセット)として保存する
get_value(n)平均からオフセットを引いた値(風袋引き後の生の値)
set_scale(factor) / get_units(n)係数を設定する。get_unitsは重さ(get_value / 係数)を返す
set_offset() / get_offset()風袋の値を手動で書き込む・読み出す(保存用)
power_down() / power_up()HX711とブリッジをスリープさせる・復帰させる
set_gain(128、64、32のいずれか)チャンネルとゲインを選ぶ(32 = チャンネルB)

風袋引きとキャリブレーション係数の求め方

HX711はグラムではなく、生の数値を返します。この数値を重さに変えるには、2つの値が必要です。空のはかりが示すオフセット(風袋)と、1グラムあたりのカウント数であるキャリブレーション係数です。式は簡単で、重さ = (生の値 − オフセット) / 係数です。オフセットはtare()関数で求め、係数は重さのわかっている物を使って一度だけ求めます。たとえば、空のはかりが84,120を示し、500 gのおもりを載せると298,870になった場合、差は214,750で、係数は214,750 / 500 = 429.5です。

  1. セルを台にしっかり固定します。キャリブレーションは、はかりを最終的な形にした状態で行います。
  2. 下のコードを書き込み、シリアルモニタを9600ボーで開き、はかりが空の状態で風袋引きが終わるのを待ちます。
  3. 重さのわかっている物を中央に置きます。別のはかりで量った水のペットボトルでも十分です。容量の半分くらいの重さが最もよい結果になります。
  4. シリアルモニタに物の重さをグラムで入力し(例:500)、Enterを押します。コードが係数を計算して表示し、すぐに確認用の値を読み取ります。
  5. 係数をメモし、はかりのコードに書き入れます。違う重さで何度か繰り返して平均を取ると、精度が上がります。
C++ (Arduino IDE)
1#include "HX711.h"
2
3const int DT_PIN = 2;                      // HX711 DT (DOUT)
4const int SCK_PIN = 3;                     // HX711 SCK (PD_SCK)
5
6HX711 scale;
7
8void setup() {
9  Serial.begin(9600);
10  scale.begin(DT_PIN, SCK_PIN);            // kanal A, kazanç 128 / channel A, gain 128
11  if (!scale.wait_ready_timeout(1000)) {   // modül cevap vermiyor / module not answering
12    Serial.println("HX711 bulunamadi / HX711 not found");
13    while (true) {}
14  }
15  scale.set_scale();                       // faktör 1: ham sayı / factor 1: raw counts
16  Serial.println("Tarti bos olsun, dara aliniyor... / Keep it empty, taring...");
17  delay(2000);
18  scale.tare(20);                          // 20 ölçümün ortalaması sıfır / average of 20 readings = zero
19  Serial.println("Bilinen agirligi koy, gramini yaz (or. 500) / Place a known weight, type its grams (e.g. 500)");
20}
21
22void loop() {
23  if (Serial.available()) {
24    float bilinen = Serial.parseFloat();   // Seri Monitör'den gram / grams from Serial Monitor
25    if (bilinen > 0) {
26      double fark = scale.get_value(20);   // dara düşülmüş ham fark / tared raw difference
27      float faktor = fark / bilinen;
28      Serial.print("Ham fark / raw difference: ");
29      Serial.println(fark, 0);
30      Serial.print("Kalibrasyon faktoru / calibration factor: ");
31      Serial.println(faktor, 2);
32      scale.set_scale(faktor);             // hemen kontrol et / check right away
33      Serial.print("Kontrol / check: ");
34      Serial.print(scale.get_units(10), 1);
35      Serial.println(" g");
36    }
37  }
38}

このコードはtare(20)で20回の平均をゼロとして扱います。10 SPSでは約2秒かかります。重さを載せると、get_value(20)が風袋引き後の生の差を返し、それを既知のグラム数で割ると係数になります。係数がマイナスになっても心配はいりません。信号線が逆になっているだけで、マイナスの係数でもはかりは正しく動きます。起動のたびに係数を入力しなくて済むように、EEPROM.put()でArduinoの不揮発性メモリに書き込み、EEPROM.get()で読み出せます。詳しくはArduinoのEEPROMの記事をご覧ください。

Arduinoのデジタルはかり:風袋引きボタン付きでLCDにグラムを表示

では、求めた係数を使って本物のはかりを作りましょう。重さは16x2のI2C LCDに表示し、D4のボタンでいつでも風袋引きができます。先に容器を載せて風袋引きし、中身だけを量れます。LCDはA4(SDA)とA5(SCL)につなぎます。詳しくはI2C LCDディスプレイの記事を、内部プルアップの使い方はボタンの配線の記事をご覧ください。

C++ (Arduino IDE)
1#include <Wire.h>
2#include <LiquidCrystal_I2C.h>
3#include "HX711.h"
4
5const int DT_PIN = 2;                      // HX711 DT
6const int SCK_PIN = 3;                     // HX711 SCK
7const int DARA_BUTON = 4;                  // dara butonu, diğer ucu GND / tare button, other leg to GND
8const float FAKTOR = 429.5;                // kendi faktörünü yaz / use your own factor
9
10HX711 scale;
11LiquidCrystal_I2C lcd(0x27, 16, 2);       // adres, sütun, satır / address, columns, rows
12float filtreli = 0;                        // filtrelenmiş ağırlık / filtered weight
13
14void setup() {
15  pinMode(DARA_BUTON, INPUT_PULLUP);
16  lcd.init();
17  lcd.backlight();
18  lcd.print("Dara aliniyor...");
19  scale.begin(DT_PIN, SCK_PIN);
20  scale.set_scale(FAKTOR);
21  scale.tare(20);                          // açılışta terazi boş olmalı / scale must be empty at start
22  lcd.clear();
23  lcd.print("Agirlik:");
24}
25
26void loop() {
27  if (digitalRead(DARA_BUTON) == LOW) {    // butona basıldı / button pressed
28    lcd.setCursor(0, 1);
29    lcd.print("Dara...         ");
30    scale.tare(20);
31    filtreli = 0;
32    while (digitalRead(DARA_BUTON) == LOW) {}   // bırakılmasını bekle / wait for release
33    delay(50);                             // kontak sıçramasını atla / skip contact bounce
34  }
35
36  if (scale.is_ready()) {
37    float w = scale.get_units(4);          // 4 ölçümün ortalaması / average of 4 readings
38    if (fabs(w - filtreli) > 5.0) {
39      filtreli = w;                        // büyük değişim: filtreyi atla / big change: skip the filter
40    } else {
41      filtreli = 0.7 * filtreli + 0.3 * w; // üstel ortalama (EMA) / exponential moving average
42    }
43    float goster = filtreli;
44    if (fabs(goster) < 0.5) goster = 0;    // sıfırdaki titremeyi gizle / hide jitter around zero
45
46    char yazi[12];
47    dtostrf(goster, 8, 1, yazi);           // 8 karakter, 1 ondalık / 8 chars, 1 decimal
48    lcd.setCursor(0, 1);
49    lcd.print(yazi);
50    lcd.print(" g");
51  }
52}

このコードでは3つの小さな工夫をしています。1つ目は指数移動平均(EMA)です。新しい値は結果に30%しか反映されないため、ふらつきがならされます。2つ目に、重さが急に5 g以上変わったらフィルタを飛ばし、表示をすぐ新しい値に切り替えます。フィルタが効くのは、荷重が安定しているときだけです。3つ目は不感帯です。±0.5 g未満の値を0として表示するので、空のはかりで0.3、-0.2、0.1のように数字が踊ることがなくなります。get_units(4)は呼ぶたびに4回の読み取りを待つため、10 SPSでは表示が1秒に約2.5回更新されます。

不安定な値:ふらつき、ドリフトとその直し方

HX711のプロジェクトの問題のほとんどは、コードではなく機械的な部分から生まれます。バー型のロードセルは片持ち梁のように働きます。片端をベースに、もう片端を上の板にねじで固定し、両端に数ミリのスペーサー(ワッシャーや3Dプリントしたブロック)をはさみます。こうするとセルがZ字型に収まり、中央が自由にたわめます。セルの中央がベースや板に触れていたり、ねじを締めすぎていたり、板がたわんだりすると、値はドリフトし続けます。セルの矢印が力の向き(下向き)を向いていることを確認し、ひずみゲージのある中央部分には何も触れさせないでください。

  • 丈夫なベース:ベースと板はたわんではいけません。厚い合板、MDF、アルミ板を使いましょう。机の振動も値に表れます。
  • 短く固定した線:セルの線は短くしてより合わせ、固定します。垂れ下がったケーブルはセルを押し、値を変えてしまいます。
  • きれいな電源:ノートパソコンのUSBポートはノイズが多いことがあります。モジュールのVCCとGNDの間に100 nFと10 µFのコンデンサを入れ、モーター、リレー、Wi-Fiアンテナから離すと効果があります。
  • ウォームアップ:電源投入後の数分間は、セルとモジュールが温まる間にゼロ点が数グラムずれることがあります。精密に測る前は少し待ってから風袋引きしましょう。
  • 平均:get_units(10)はノイズを約3分の1に減らしますが、10 SPSでは1秒かかります。速さと安定性のバランスを取りましょう。ほかのフィルタの方法はセンサーデータのフィルタリングの記事をご覧ください。
  • クリープ:長時間かけたままの荷重では、数分かけて値が数グラム変わることがあります。これはセルの性質で、安いセルほど目立ちます。
  • 現実的な目安:しっかり取り付けた5 kgのセルで0.5〜1 g、50 kgのセル4個で作った体重計で50〜100 gの安定性が出れば、よい結果です。
安い緑のHX711ボードの一部には、製造上の不具合でE-端子がGNDにつながっておらず、値がずっとドリフトするものがあります。テスターでE-とGNDピンの間の抵抗を測り、0 Ωに近くなければ、2つの間に短い線をはんだ付けしてください。この小さな修正で、原因不明のドリフトのよくある原因が1つなくなります。

ESP32で作るはかり:OLEDディスプレイとキャリブレーションの保存

同じライブラリはESP32でもそのまま動きます。下の例では、0.96インチのSSD1306 OLEDに重さを大きな数字で表示し、GPIO 27のボタンで風袋引きし、Preferencesライブラリでキャリブレーション係数をフラッシュに保存します。シリアルモニタに既知の重さをグラムで入力するだけで、新しい係数が計算されて保存されます。OLEDの配線(SDA GPIO 21、SCL GPIO 22)とライブラリについては、OLEDディスプレイの記事をご覧ください。

C++ (Arduino IDE)
1#include <Wire.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_SSD1306.h>
4#include <Preferences.h>
5#include "HX711.h"
6
7const int DT_PIN = 25;                     // HX711 DT
8const int SCK_PIN = 26;                    // HX711 SCK
9const int DARA_BUTON = 27;                 // dara butonu, diğer ucu GND / tare button, other leg to GND
10
11HX711 scale;
12Adafruit_SSD1306 display(128, 64, &Wire, -1);
13Preferences ayar;
14float faktor;
15
16void agirlikGoster(float g) {
17  display.clearDisplay();
18  display.setTextSize(1);
19  display.setCursor(0, 0);
20  display.print(F("BlueGrays Terazi"));
21  display.setTextSize(2);                  // büyük rakamlar / big digits
22  display.setCursor(0, 28);
23  if (fabs(g) < 1000) {
24    display.print(g, 1);
25    display.print(F(" g"));
26  } else {
27    display.print(g / 1000.0, 3);          // 1 kg üstü kilogram / kilograms above 1 kg
28    display.print(F(" kg"));
29  }
30  display.display();
31}
32
33void setup() {
34  Serial.begin(115200);
35  pinMode(DARA_BUTON, INPUT_PULLUP);
36  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);   // SDA 21, SCL 22
37  display.setTextColor(SSD1306_WHITE);
38
39  ayar.begin("terazi", false);             // flash'ta ayar alanı / settings namespace in flash
40  faktor = ayar.getFloat("faktor", 429.5); // kayıt yoksa varsayılan / default if nothing saved
41
42  scale.begin(DT_PIN, SCK_PIN);
43  scale.set_scale(faktor);
44  scale.tare(20);
45  Serial.println("Kalibrasyon: agirligi koy, gramini yaz / Calibrate: place a weight, type its grams");
46}
47
48void loop() {
49  if (digitalRead(DARA_BUTON) == LOW) {
50    scale.tare(20);
51    while (digitalRead(DARA_BUTON) == LOW) delay(10);   // bırakılmasını bekle / wait for release
52    delay(50);                             // kontak sıçramasını atla / skip contact bounce
53  }
54
55  if (Serial.available()) {
56    float bilinen = Serial.parseFloat();
57    if (bilinen > 0) {
58      faktor = scale.get_value(20) / bilinen;  // yeni faktör / new factor
59      scale.set_scale(faktor);
60      ayar.putFloat("faktor", faktor);     // elektrik kesilse de kalır / survives power loss
61      Serial.printf("Yeni faktor / new factor: %.2f\n", faktor);
62    }
63  }
64
65  if (scale.wait_ready_timeout(200)) {
66    agirlikGoster(scale.get_units(5));
67  }
68}

ESP32の3V3ピンからHX711に給電すると、モジュールのレギュレーターは4.3 Vに届かず、ブリッジは3.3 Vより少し低い電圧で動きます。レシオメトリック測定なので係数はほとんど変わらず、ノイズが少し増えるだけです。ESP32ならWi-Fiもすぐに使えます。重さをウェブページに表示したり、餌皿が空になったらスマートフォンに通知を送ったりするのも、数行足すだけです。始めるにはESP32とは?をご覧ください。電池で動く養蜂箱のはかりでは、読み取りの合間にscale.power_down()でHX711を、ディープスリープでESP32をスリープさせます。ESP32のスリープ中にSCKをHIGHに保つには、gpio_hold_en()でピンを固定します。そうしないとピンが浮き、HX711が勝手に復帰することがあります。また、復帰後の最初の400 msの値は捨てるようにしましょう。

Raspberry Pi PicoでHX711を使う(MicroPython)

MicroPythonにはHX711のモジュールが付属していませんが、通信方式がとても簡単なので、数行でドライバを自作できます。下のクラスは、DT線がLOWになるのを待ち、SCKに24個のパルスを送ってデータを読み、ゲインを選ぶために1〜3個の追加パルスを送り、結果を2の補数から符号付きの数値に変換します。読み取り中は割り込みを一時的に止めるので、SCK線が60 µsより長くHIGHのままになることはなく、HX711が誤ってスリープすることもありません。MicroPythonのセットアップについてはRaspberry Pi Picoとは?をご覧ください。

MicroPython
1from machine import Pin
2import machine
3import time
4
5class HX711:
6    def __init__(self, dt, sck, gain=128):
7        self.dt = Pin(dt, Pin.IN)
8        self.sck = Pin(sck, Pin.OUT, value=0)
9        self.extra = {128: 1, 64: 3, 32: 2}[gain]   # toplam 25, 27, 26 darbe / 25, 27, 26 pulses in total
10        self.offset = 0
11        self.scale = 1.0
12        self.read()                                 # kazancı ayarla / set the gain
13
14    def read(self, timeout_ms=1000):
15        start = time.ticks_ms()
16        while self.dt.value() == 1:                 # DT LOW ise veri hazır / data ready when DT is LOW
17            if time.ticks_diff(time.ticks_ms(), start) > timeout_ms:
18                raise OSError("HX711 yanit vermiyor / not responding")
19        irq = machine.disable_irq()                 # SCK 60 µs'den uzun HIGH kalmasın / keep SCK HIGH under 60 µs
20        value = 0
21        for _ in range(24):
22            self.sck.value(1)
23            value = (value << 1) | self.dt.value()
24            self.sck.value(0)
25        for _ in range(self.extra):                 # sonraki ölçümün kanalı ve kazancı / next channel and gain
26            self.sck.value(1)
27            self.sck.value(0)
28        machine.enable_irq(irq)
29        if value & 0x800000:                        # ikiye tümleyen / two's complement
30            value -= 0x1000000
31        return value
32
33    def read_average(self, times=10):
34        return sum(self.read() for _ in range(times)) / times
35
36    def tare(self, times=15):
37        self.offset = self.read_average(times)
38
39    def get_units(self, times=5):
40        return (self.read_average(times) - self.offset) / self.scale
41
42
43hx = HX711(dt=15, sck=14)                           # DT -> GP15, SCK -> GP14
44print("Tarti bos, dara aliniyor... / Scale empty, taring...")
45hx.tare()
46hx.scale = 429.5                                    # kendi faktörün / your own factor
47
48while True:
49    print("{:.1f} g".format(hx.get_units()))
50    time.sleep_ms(200)

キャリブレーションの考え方はArduinoと同じです。hx.scale = 1.0の状態で既知の重さを載せ、get_units()の結果をそのグラム数で割ると係数になります。PicoでもHX711は3V3(OUT)ピンから給電します。重さを画面に表示したいなら、ssd1306.pyドライバでOLEDを追加し、oled.text()で値を表示しましょう。

HX711とロードセルを使ったプロジェクトのアイデア

  • キッチンスケール:5 kgのセル、風袋引きボタン、OLEDディスプレイで、1 g単位のはかりを作ります。
  • 体重計:古い体重計の4つのセル、HX711、I2C LCDでキログラムを表示します。
  • スマートなペットの給餌器:餌皿の重さが設定値を下回ると、ESP32が通知を送り、サーボモーターがふたを開けて餌を落とします。
  • 植木鉢のはかり:鉢が軽くなっていく様子から植物に必要な水の量を求め、その結果を土壌水分センサーと比べます。
  • 養蜂箱モニター:巣箱の下に4つのセルを置き、1日の重さの増え方から蜜の流入を追い、Wi-Fiでデータを記録します。
  • 部品カウンター:ねじ1本の重さを覚えさせ、合計の重さから箱の中のねじの本数を求めます。
  • データ記録:値をシリアルポートでパソコンに送り、Excelへのデータ送信の方法でグラフにします。

よくある失敗と対処法

症状考えられる原因対処法
read()の行でプログラムが止まるDTかSCKがつながっていない、またはコードのピン番号が違う配線を確認し、wait_ready_timeout()を使う
値がいつも8388607か-8388608入力が飽和している:A+/A-の断線、またはEとAの線の取り違えテスターで線の色を確認する
値がいつも0DT線がLOWのまま、モジュールに電源が来ていないVCC、GND、DTの接続を測定する
重さを載せると値が下がるA+とA-が逆線を入れ替えるか、マイナスの係数を使う
値がずっとゆっくりずれていくウォームアップ、クリープ、E-とGNDの接続なし、取り付けに無理な力ウォームアップを待ち、E-とGNDの間を測定し、取り付けを直す
値が数グラム飛ぶ長い線、ノイズの多い電源、板のたわみ線を短くし、コンデンサを入れ、平均を取る
置く位置で重さが変わる板がたわんでいる、または4つのセルの1つに荷重がかかっていない板を丈夫にし、セルの高さをそろえる
軽い物は正しいが、重い物がずれる係数をとても軽いおもりで求めた容量の半分くらいのおもりでキャリブレーションし直す
トラブルを調べるときは、まずread()で生の値をシリアルモニタに表示し、指でセルを軽く押してみます。生の数値が数千単位で変われば電子回路は正常で、問題はキャリブレーションか機械的な部分にあります。まったく変わらなければ配線を、飽和していれば線の色を確認してください。

HX711とロードセルを正しく取り付けてキャリブレーションすれば、安い部品でグラム単位まで測れる装置になります。キャリブレーション係数を保存し、しっかりした機構を作り、フィルタをプロジェクトに必要な速さに合わせれば、あとはアイデア次第です。測定についてもっと広く知りたいなら、Arduinoのセンサーガイドをご覧ください。BlueGraysアプリには、センサーの読み取り、LCDやOLEDディスプレイへの表示、ESP32でのデータ記録のプロジェクトが、回路図とコード付きでステップごとに用意されているので、はかりと組み合わせられます。

よくある質問

HX711でどのくらいの重さまで測れますか?

HX711自体にはキログラムの上限はなく、最大の重さはロードセルの容量で決まります。1 kgのセルなら1 kgまで、50 kgのセル4個なら200 kgまで測れます。HX711は、ブリッジのマイクロボルト単位の出力を24ビットの数値に変換するだけです。

HX711のキャリブレーション係数はどう計算しますか?

まず空のはかりをtare()で風袋引きし、重さのわかっている物を載せて、get_value()で風袋引き後の生の値を読みます。その値を物の重さ(グラム)で割ると係数になります。たとえば500 gで214,750なら、係数は429.5です。set_scale()に係数を渡せば、get_units()が直接グラムを返します。

HX711の値がふらつき続けるのはなぜですか?

よくある原因は、たわむ板や取り付けの悪さ、長くて固定されていない線、ノイズの多いUSB電源、ウォームアップです。中央が自由になるようスペーサーを使ってセルを取り付け、線を短くし、数分ウォームアップさせて、平均やソフトウェアのフィルタを使いましょう。一部の安いボードでは、E-端子がGNDにつながっていないことも、ずっとドリフトする原因になります。

ロードセルの線の色は何を意味しますか?

一般的なバー型のロードセルでは、赤がE+、黒がE-、白がA-、緑がA+です。色はメーカーによって異なることがあるので、テスターで測るのが最も確実です。励起のペアと信号のペアは、それぞれ約1000 Ωになります。重さを載せて値が下がるなら、A+とA-の線を入れ替えるだけです。

HX711は3.3 Vで動きますか?

はい、HX711は2.6〜5.5 Vで動きます。ESP32とPicoでは、モジュールを3.3 Vで給電してください。そうしないとDT線が5 Vになります。3.3 Vではブリッジの励起電圧が下がりますが、レシオメトリック測定なのでキャリブレーション係数はほとんど変わらず、ノイズが少し増えるだけです。

50 kgのロードセル1個をHX711で使えますか?

はい。ただし、3線のハーフブリッジセルをフルブリッジにするため、値がとても近い1 kΩの抵抗が2本必要です。外側の線をE+とE-に、中央の線をA+に、2本の抵抗の中点をA-につなぎます。より安定した結果を得るには、セルを2個か4個組み合わせるほうがよいでしょう。

全プロジェクトを見る
HC-SR04で距離を測定(シリアルモニタ表示)
#27初級

HC-SR04で距離を測定(シリアルモニタ表示)

HC-SR04センサーは、コウモリが暗闇で道を見つけるのと同じ仕組みで動作します。人には聞こえない音を出し、その反響を捉えて前方の物体までの距離を測ります。Arduinoは0.5秒ごとに距離をセンチメートル単位でコンピューターの画面に表示し、3〜100センチメートルの測定値を示します。駐車センサーや障害物を避けるロボットなどのプロジェクトの基礎になります。

4.6(46)
71
DHT11で温度と湿度を測定
#55中級

DHT11で温度と湿度を測定

部屋の温度は何度で、空気は湿っているでしょうか、それとも乾燥しているでしょうか?DHT11センサーが温度と湿度を測定し、Arduinoが2行のLCDディスプレイに値を表示して、数秒ごとに更新します。センサーに異常があればエラーメッセージが表示されます。自分だけの小さな気象観測装置を作る第一歩です。

4.7(47)
73
LCDディスプレイ付きデジタル電圧計
#56中級
プレミアム

LCDディスプレイ付きデジタル電圧計

自作の測定器で、電池や電源アダプターが出力する電圧を調べます。2つの抵抗で作る分圧回路が、高い電圧をボードで読み取れるレベルまで下げます。Arduinoが元の電圧を計算し、2行のLCDディスプレイにボルト単位で表示します。この回路では約55ボルトまでの直流電圧を測定できます。コンセントの商用電源には絶対に接続しないでください。

4.5(27)
36
I2CでLCDディスプレイを使う
#32初級
プレミアム

I2CでLCDディスプレイを使う

Arduinoにディスプレイを接続し、最初のメッセージを表示します。2行のLCDディスプレイは数本の配線だけで接続できます。まず上の行にあいさつを表示し、次に下の行にもう1つのメッセージを表示します。その後、表示を消去して最初から繰り返します。温度や時刻、スコアを表示するプロジェクトは、すべてこのステップから始まります。

4.8(53)
70
身長測定プロジェクト
#33中級
プレミアム

身長測定プロジェクト

ドア枠に取り付けて、下に立った人の身長をセンチメートルで表示する身長計です。まず、下に誰もいない状態で1つ目のボタンを押し、距離センサーで床までの距離を測ります。次に、人が下に立って2つ目のボタンを押すと、Arduinoが2つの測定値の差を計算し、身長をディスプレイに表示します。病院にある身長計の電子版を自分で作れます。

4.5(25)
34
NTCと2x16 LCDディスプレイで温度を測定
#44初級
プレミアム

NTCと2x16 LCDディスプレイで温度を測定

小さなビーズのようなセンサーで周囲の温度を測ります。NTCというこの部品は、温まるほど電気が流れやすくなります。Arduinoがその変化を読み取り、数式で摂氏温度に変換して、2行のLCDディスプレイに0.5秒ごとに表示します。手のひらでセンサーを温めて、数値が上がる様子を見るのも楽しみの1つです。

4.5(33)
44
ESP32 I2C LCDディスプレイ(16x2)
#119中級
プレミアム

ESP32 I2C LCDディスプレイ(16x2)

このプロジェクトでは、16x2文字のLCDをI2CでESP32に接続して文字を表示します。I2Cならデータ用の2本のピン(SDAとSCL)だけで制御でき、従来のパラレル接続のように6本以上のピンを使わずに済みます。コードでは1行目に固定メッセージ、2行目に毎秒増えるカウンターを表示します。また、起動時にI2Cスキャナーを実行し、ディスプレイのアドレス(通常は0x27または0x3F)をシリアルモニタに表示します。

4.9(23)
40
ESP32温度データロガー(DHT22 + DS1307 RTC + microSD + OLED)
#144上級
プレミアム

ESP32温度データロガー(DHT22 + DS1307 RTC + microSD + OLED)

ESP32で日時付きの温度・湿度記録システムを作ります!DHT22で1分ごとに温度と湿度を読み取り、DS1307 RTCから取得した日時とともにmicroSDカードへCSV形式で記録します。OLEDには最新の温度を大きな文字で表示し、湿度のパーセント値、日時、総記録数も表示します。SDカードの/temp_log.csvファイルはExcel、Google Sheets、Pythonのpandasで開いて分析できます。温室の監視、家や部屋の温度管理、実験室のデータ収集、食品の保管環境や養蜂箱の監視に適しています。

4.7(7)
12