Components · 16 min read

HX711 Arduino: Load Cell Wiring, Calibration and Digital Scale

HX711 Arduino wiring, load cell wire colours, four 50 kg cells, tare and calibration factor, fixing unstable readings, plus LCD, OLED, ESP32 and Pico code.

The HX711 and Arduino combination is the most popular and cheapest way to read the microvolt-level signal from a load cell and turn it into a weight in grams. Kitchen scales, bathroom scales, beehive scales, pet food bowl monitors and motor thrust stands all share the same idea: the load cell bends by an invisible amount under weight, the HX711 turns that tiny change into a 24-bit number, and the Arduino converts that number into grams with a calibration factor.

In this guide you'll learn how the Wheatstone bridge inside a load cell works, what the wire colours mean (E+, E-, A+, A-), how to wire four 50 kg half-bridge cells taken from a bathroom scale, and how to tare and find the calibration factor step by step with the HX711 library. Then you'll build a digital scale with an LCD and a tare button, see why the readings jitter and how to steady them, and finally do the same with an ESP32 and OLED display and with a Raspberry Pi Pico (MicroPython).

HX711 load cell amplifier module
HX711 module: one edge has the E+, E-, A-, A+ terminals for the load cell (plus B-, B+ for the second channel), the other edge has the GND, DT, SCK and VCC pins that go to the Arduino.

What is a load cell and how does it work?

A load cell is a piece of aluminium or steel with strain gauges glued onto it. A strain gauge is a resistor etched in a zigzag pattern on a thin foil: when the metal is stretched, the track gets longer and thinner and its resistance rises; when it's compressed, the resistance drops. The change is incredibly small. A gauge with a gauge factor of about 2 changes its resistance by only 0.2 percent at a strain of one part per thousand; for a 1000 Ω gauge that's 2 Ω, which a normal analogRead() could never detect.

To make this tiny change measurable, four strain gauges are wired as a Wheatstone bridge. A bridge is simply two voltage dividers side by side: the supply goes between E+ and E-, while A+ and A- are the midpoints of the two dividers. With no load, all four resistors are equal, so both midpoints sit at the same voltage and the output is zero. When a load is applied, two gauges stretch and two compress; one midpoint rises while the other falls. If R1 and R2 are the top and bottom resistors of the left divider and R3 and R4 those of the right one, the output is Vout = Vexc × (R4/(R3+R4) − R2/(R1+R2)), and it grows in proportion to the weight. You can play with the divider idea in the voltage divider calculator.

A figure such as 1 mV/V on a load cell's label is its sensitivity: at full capacity the cell outputs 1 mV for every volt of excitation. Because the HX711 module drives the bridge with about 4.3 V, a 5 kg cell produces only 4.3 mV at 5 kg and just 0.86 µV per gram. That's why you need a dedicated 24-bit ADC with a gain of 128.

Load (5 kg, 1 mV/V cell)Bridge outputHX711 raw value (gain 128)
0 g0 mV0 (after tare)
100 g0.086 mV≈ 43,000
1 kg0.86 mV≈ 429,500
5 kg (full capacity)4.3 mV≈ 2,147,000

There's a detail worth noticing in the table: the raw value doesn't depend on the supply voltage. The HX711 uses the voltage that feeds the bridge (AVDD) as its measurement reference too, so if the supply drops a little, the bridge output drops by the same ratio and the result stays the same. This is called ratiometric measurement. As a rough rule, full capacity on a 1 mV/V cell equals about 2,147,000 counts. Divide that by the cell's capacity in grams and you get an approximate calibration factor: ≈ 2150 for 1 kg, ≈ 430 for 5 kg and ≈ 107 for 20 kg.

What is the HX711 module? Specifications

The HX711 is a 24-bit sigma-delta ADC made by Avia Semiconductor for weighing applications. It contains a programmable gain amplifier (PGA), a regulator that powers the bridge and an internal oscillator, and it talks to the outside world over just two wires with its own simple serial protocol. That protocol is not I2C: when the DT (DOUT) line goes LOW, data is ready, and the Arduino reads the 24 bits one by one by sending 25–27 pulses on the SCK line. The number of pulses selects the channel and gain for the next reading: 25 pulses mean channel A with gain 128, 26 pulses channel B with gain 32, and 27 pulses channel A with gain 64.

FeatureValue
Resolution24 bits, two's complement (0x800000 – 0x7FFFFF)
Channel AGain 128 (±20 mV) or 64 (±40 mV), with 5 V AVDD
Channel BFixed gain of 32 (±80 mV)
Sample rate10 SPS (RATE = GND) or 80 SPS (RATE = VCC)
Supply2.6–5.5 V
CurrentUnder 1.5 mA; under 1 µA in power-down
Bridge excitation (E+)About 4.3 V on the common green module with a 5 V input
Settling time400 ms after power-up, wake-up or a gain change (10 SPS)
Interface2 wires: DT (data) and SCK (clock + power-down control)

On most cheap green modules the RATE pin is tied to GND on the board, so the module takes 10 readings per second. 10 SPS is less noisy and also rejects 50/60 Hz mains interference, which makes it the best choice for weighing in most cases. If the SCK line stays HIGH for more than 60 µs, the HX711 enters power-down mode and also cuts power to the bridge. In battery-powered projects this is handy through the power_down() and power_up() functions.

Types of load cell: which capacity should you choose?

1 kg bar-type load cell
A 1 kg bar (straight bar) load cell: the thin section with the double hole in the middle bends, and the strain gauges are glued onto it; the arrow on the label shows the direction of the force.
TypeCapacityWiresTypical useApprox. factor (counts/g)
Bar, full bridge1 kg4Jewellery, letters, precise kitchen scale≈ 2150
Bar, full bridge5 kg4Kitchen scale, pet food bowl≈ 430
Bar, full bridge20 kg4Parcels, luggage, plant pot scale≈ 107
Half bridge (bathroom scale cell)50 kg (200 kg with 4)3Body scale, beehiveFind by measuring
S-type50 kg – 1 t4Hanging scale, pulling forceDepends on the mV/V on the label

Pick a capacity of about 1.5 times the heaviest load you'll measure. An oversized cell lowers the resolution: you can weigh a 50 g letter on a 20 kg cell, but the reading will be four times coarser than on a 5 kg cell. Overloading a small cell is worse, though; bar cells usually handle about 120 percent of their capacity safely, but above 150 percent the metal can bend permanently and the cell will never return to zero. Total capacity also depends on how many cells share the weight: four 50 kg cells at the corners carry 200 kg together.

Wire colours and HX711 wiring

Load cell wireHX711 terminalFunction
RedE+Bridge excitation (+)
BlackE-Bridge excitation (−)
WhiteA-Signal (−)
GreenA+Signal (+)
HX711 pinArduino UnoESP32Raspberry Pi Pico
VCC5V3V33V3(OUT), pin 36
GNDGNDGNDGND, pin 38
DT (DOUT)D2GPIO 25GP15, pin 20
SCK (PD_SCK)D3GPIO 26GP14, pin 19
The HX711 is not an I2C device: you don't have to connect DT and SCK to A4/A5, and an I2C scanner will never find it. These two lines can go to any two digital pins as long as you put the right numbers in the code. On the ESP32 and Pico, always power the module from 3.3 V; on the green module VCC also sets the signal level of the DT line, so a module powered from 5 V puts 5 V on 3.3 V inputs.

Colours can vary between manufacturers; some cells use yellow instead of black or blue instead of green, or swap the roles of white and green. To be sure, set your multimeter to ohms: the excitation pair (E+, E-) and the signal pair (A+, A-) usually read around 1000 Ω, while the cross pairs read about three quarters of that. Swapping the signal wires doesn't damage anything; the value simply goes down as you add weight. You fix it by swapping the wires or by making the calibration factor negative. B+ and B- belong to the second channel and stay unused in single-cell projects.

Wiring four 50 kg half-bridge load cells (body scale)

The 50 kg cells from bathroom scales, the ones with an E-shaped middle, contain only two strain gauges and 3 wires, so each one is half a bridge. The wires are usually red, white and black, but always find the centre tap by measuring: the two outer wires read about 2 kΩ between them, and the centre wire reads about 1 kΩ to each outer wire. On most cells the centre tap is red. When you connect four cells together like a ring, you get a full Wheatstone bridge.

  1. Place the cells at the four corners of the platform and number the corners 1 (front left), 2 (front right), 3 (back right) and 4 (back left).
  2. Join the same-coloured outer wires of neighbouring cells: the whites of 1 and 2, the blacks of 2 and 3, the whites of 3 and 4, and the blacks of 4 and 1.
  3. Connect the red wires of the diagonal cells 1 and 3 to E+ and E-.
  4. Connect the red wires of the other diagonal, cells 2 and 4, to A+ and A-.
  5. Measure before soldering: E+ to E- and A+ to A- should both read about 2 kΩ. If the value is very different, one of the joints is wrong.
  6. If the value goes down when you add weight, swap the A+ and A- wires or use a negative factor.
Cell (corner)White wireBlack wireRed wire
1 – front leftto the white of 2to the black of 4E+
2 – front rightto the white of 1to the black of 3A+
3 – back rightto the white of 4to the black of 2E-
4 – back leftto the white of 3to the black of 1A-
You can also build a scale with two cells: join the white of 1 to the black of 2 and the black of 1 to the white of 2; these two junctions go to E+ and E-, and the two red wires go to A+ and A-. With a single cell, you complete the bridge with two 1 kΩ resistors: the outer wires go to E+ and E-, the red wire to A+, and the midpoint of the two series resistors to A-. Pick the resistors with a multimeter and use the two closest ones; if they differ too much, the HX711 saturates. The fewer cells you use, the more temperature drift you get.

Installing the HX711 library

  1. In the Arduino IDE, open Tools > Manage Libraries and type HX711 in the search box.
  2. Install HX711 Arduino Library by Bogdan Necula. If this is your first time installing a library, have a look at the adding Arduino libraries guide.
  3. After installing, you'll find the HX711_basic_example and HX711_full_example sketches under File > Examples > HX711 Arduino Library; the code below uses the same functions.
FunctionWhat it does
begin(dt, sck, gain)Sets up the pins; gain defaults to 128 (channel A)
is_ready() / wait_ready_timeout(ms)Is a new reading ready? The timeout version won't lock up the program if the module is missing
read() / read_average(n)Returns the raw 24-bit value or the average of n readings
tare(n)Stores the average of n readings as the zero point (offset)
get_value(n)Average minus offset: the tared raw value
set_scale(factor) / get_units(n)Sets the factor; get_units returns the weight (get_value / factor)
set_offset() / get_offset()Writes or reads the tare value manually (to save it)
power_down() / power_up()Puts the HX711 and the bridge to sleep and wakes them up
set_gain(128, 64 or 32)Selects channel and gain (32 = channel B)

How do you tare and find the calibration factor?

The HX711 doesn't give you grams, it gives you a raw number. To turn that number into weight you need two values: the offset (tare) that the empty scale reads, and the number of counts per gram, the calibration factor. The formula is simple: weight = (raw value − offset) / factor. The tare() function finds the offset; you work out the factor once, using an object whose weight you know. For example, if the empty scale reads 84,120 and the value becomes 298,870 when you place a 500 g weight on it, the difference is 214,750 and the factor is 214,750 / 500 = 429.5.

  1. Mount the cell firmly on the platform; calibration should be done with the scale in its final form.
  2. Upload the code below, open the Serial Monitor at 9600 baud and wait for the tare while the scale is empty.
  3. Place an object of known weight in the middle. A water bottle weighed on another scale works fine; a weight of around half the capacity gives the best result.
  4. Type the object's weight in grams into the Serial Monitor (e.g. 500) and press Enter. The code calculates and prints the factor and immediately takes a check reading.
  5. Write the factor down and put it in your scale code. Repeating with different weights a few times and averaging improves accuracy.
Arduino (C++)
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}

The code treats the average of 20 readings as zero with tare(20); at 10 SPS that takes about 2 seconds. When you add the weight, get_value(20) returns the tared raw difference, and dividing it by the known grams gives the factor. Don't worry if the factor comes out negative: it just means the signal wires are reversed, and the scale still works correctly with a negative factor. To avoid entering the factor at every start-up, you can write it to the Arduino's permanent memory with EEPROM.put() and read it back with EEPROM.get(); details are in the Arduino EEPROM article.

Arduino digital scale: showing grams on an LCD with a tare button

Now let's build a real scale using your factor. The weight is shown on a 16x2 I2C LCD, and a button on D4 tares at any time, so you can put a container on first, tare, and then weigh only what's inside. The LCD connects to A4 (SDA) and A5 (SCL); see the I2C LCD display article for details and the button wiring article for using the internal pull-up.

Arduino (C++)
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}

The code uses three small tricks. The first is an exponential moving average (EMA): each new reading contributes only 30 percent to the result, which smooths out the jitter. Second, if the weight suddenly changes by more than 5 g the filter is skipped and the display jumps straight to the new value; the filter only kicks in with a steady load. Third, a dead band: values below ±0.5 g are shown as 0, so dancing digits like 0.3, -0.2, 0.1 disappear on an empty scale. Because get_units(4) waits for four readings on every call, at 10 SPS the display refreshes about 2.5 times a second.

Unstable readings: jitter, drift and how to fix them

Most problems in HX711 projects come from the mechanics, not the code. A bar load cell works like a cantilever beam: one end is screwed to the base and the other to the top plate, with a spacer of a few millimetres (washers or a 3D-printed block) at each end. That way the cell sits in a Z shape and its middle can bend freely. If the middle of the cell touches the base or the plate, if the screws are overtightened or if the plate flexes, the readings will keep drifting. Make sure the arrow on the cell points in the direction of the force (down), and never let anything touch the middle section where the strain gauges are.

  • Rigid base: The base and the plate must not flex; use thick plywood, MDF or an aluminium sheet. Vibrations from the table also show up in the reading.
  • Short, secured wires: Keep the cell wires short, twist them together and fix them in place. A dangling cable pushes on the cell and changes the value.
  • Clean power: A laptop's USB port can be noisy. Adding 100 nF and 10 µF capacitors across the module's VCC and GND and keeping away from motors, relays and the Wi-Fi antenna helps.
  • Warm-up time: During the first few minutes after power-up, while the cell and module warm up, the zero point can drift by a few grams; wait before precise measurements, then tare.
  • Average: get_units(10) cuts the noise by about three times but takes 1 second at 10 SPS. Balance speed and stability; for other filtering methods, see the sensor data filtering article.
  • Creep: Under a load that stays on for a long time, the value can change by a few grams over minutes. This is in the nature of the cell and is more noticeable on cheap cells.
  • Realistic expectations: 0.5–1 g of stability with a well-mounted 5 kg cell, and 50–100 g on a body scale built from four 50 kg cells, are good results.
On some cheap green HX711 boards, a manufacturing fault leaves the E- terminal unconnected to GND, and the readings drift constantly. Measure the resistance between E- and the GND pin with a multimeter: if it isn't close to 0 Ω, solder a short wire between the two. This small fix removes a common cause of unexplained drift.

Scale with the ESP32: OLED display and permanent calibration

The same library runs unchanged on the ESP32. The example below shows the weight in large digits on a 0.96-inch SSD1306 OLED, tares with a button on GPIO 27 and saves the calibration factor to flash with the Preferences library. Just type the known weight in grams into the Serial Monitor and the new factor is calculated and stored permanently. For OLED wiring (SDA GPIO 21, SCL GPIO 22) and libraries, see the OLED display article.

Arduino (C++)
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}

When you power the HX711 from the ESP32's 3V3 pin, the module's regulator can't reach 4.3 V and the bridge runs on a little under 3.3 V. Because the measurement is ratiometric, the factor barely changes; only the noise increases slightly. The ESP32 is also ready for Wi-Fi: showing the weight on a web page or sending a notification to your phone when the food bowl is empty takes just a few extra lines. To get started, read What is the ESP32?. On a battery-powered beehive scale, you put the HX711 to sleep between readings with scale.power_down() and the ESP32 with deep sleep. To keep SCK HIGH while the ESP32 sleeps, latch the pin with gpio_hold_en(); otherwise it floats and the HX711 may wake up on its own. Also remember to discard the readings from the first 400 ms after waking up.

HX711 with the Raspberry Pi Pico (MicroPython)

MicroPython doesn't ship with an HX711 module, but the protocol is so simple that you can write the driver yourself in a few lines. The class below waits for the DT line to go LOW, reads the data by sending 24 pulses on SCK, sends 1–3 extra pulses to select the gain and converts the result from two's complement to a signed number. Interrupts are disabled briefly during the read, so the SCK line never stays HIGH for more than 60 µs and the HX711 doesn't accidentally go to sleep. For MicroPython setup, see What is the 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)

The calibration logic is the same as on the Arduino: with hx.scale = 1.0, place the known weight and divide the get_units() result by its weight in grams to get the factor. On the Pico, power the HX711 from the 3V3(OUT) pin as well. If you want to show the weight on a screen, add an OLED with the ssd1306.py driver and print the value with oled.text().

Project ideas with the HX711 and a load cell

  • Kitchen scale: A 5 kg cell, a tare button and an OLED display for a scale with 1 g resolution.
  • Body scale: The four cells from an old bathroom scale, an HX711 and an I2C LCD showing kilograms.
  • Smart pet feeder: When the bowl's weight drops below a set value, the ESP32 sends a notification and a servo motor opens a flap to drop food.
  • Plant pot scale: Work out how much water a plant needs as the pot gets lighter, and compare the result with a soil moisture sensor.
  • Beehive monitor: Put 4 cells under the hive, follow the honey flow through the daily weight gain and log the data over Wi-Fi.
  • Parts counter: Teach it the weight of a single screw and work out how many screws are in the box from the total weight.
  • Data logging: Send the readings to your computer over the serial port and chart them using the sending data to Excel method.

Common mistakes and how to fix them

SymptomLikely causeFix
The program freezes on the read() lineDT or SCK not connected, or wrong pin number in the codeCheck the wires and use wait_ready_timeout()
The value is always 8388607 or -8388608Input saturated: A+/A- broken, or E and A wires mixed upCheck the wire colours with a multimeter
The value is always 0DT line stuck LOW, module not poweredMeasure the VCC, GND and DT connections
The value drops when you add weightA+ and A- reversedSwap the wires or use a negative factor
The reading drifts slowly all the timeWarm-up, creep, missing E- to GND link, stressed mountingWait for warm-up, measure E- to GND, fix the mounting
Values jump by a few gramsLong wires, noisy power, flexing plateShorten the wires, add capacitors, average
Weight differs depending on positionThe plate flexes or one of the 4 cells carries no loadMake the plate rigid and bring the cells to the same height
Small weights are right, large ones are wrongThe factor was found with a very small weightRecalibrate with a weight of around half the capacity
When troubleshooting, first print the raw value to the Serial Monitor with read() and press lightly on the cell with your finger. If the raw number changes by thousands, the electronics are fine and the problem lies in the calibration or the mechanics; if it doesn't change at all, check the wiring, and if it saturates, check the wire colours.

Once a load cell with an HX711 is mounted and calibrated properly, you have a device that measures to the gram with cheap parts. Save your calibration factor, build solid mechanics and tune the filter to your project's speed; the rest is up to your imagination. For a broader view of measuring things, take a look at the Arduino sensors guide. In the BlueGrays app you'll find projects for reading sensors, showing values on LCD and OLED displays and logging data with the ESP32, with step-by-step circuit diagrams and code, so you can combine your scale with them.

Frequently asked questions

How much weight can the HX711 measure?

The HX711 itself has no kilogram limit; the maximum weight is set by the capacity of the load cell. With a 1 kg cell you can measure 1 kg, and with four 50 kg cells 200 kg. The HX711 only converts the bridge's microvolt-level output into a 24-bit number.

How do you calculate the HX711 calibration factor?

First tare the empty scale with tare(), then place an object of known weight and read the tared raw value with get_value(). Divide that value by the object's weight in grams to get the factor; for example, if 500 g reads 214,750, the factor is 429.5. Once you pass the factor to set_scale(), get_units() returns grams directly.

Why do my HX711 readings keep fluctuating?

The most common causes are a flexing or badly mounted plate, long and loose wires, a noisy USB supply and warm-up. Mount the cell with spacers so its middle is free, shorten the wires, let it warm up for a few minutes and use averaging or a software filter. On some cheap boards, an E- terminal that isn't connected to GND also causes constant drift.

What do the load cell wire colours mean?

On common bar load cells, red goes to E+, black to E-, white to A- and green to A+. Since colours can vary between manufacturers, measuring with a multimeter is the safest way: the excitation pair and the signal pair each read about 1000 Ω. If the value drops when you add weight, just swap the A+ and A- wires.

Does the HX711 work with 3.3 V?

Yes, the HX711 works from 2.6 to 5.5 V, and on the ESP32 and Pico you should power the module from 3.3 V; otherwise the DT line runs at 5 V. At 3.3 V the bridge gets a lower excitation voltage, but because the measurement is ratiometric the calibration factor barely changes; only the noise increases a little.

Can I use a single 50 kg load cell with the HX711?

Yes, but to complete the 3-wire half-bridge cell into a full bridge you need two 1 kΩ resistors whose values are very close to each other. The outer wires go to E+ and E-, the centre wire to A+, and the midpoint of the two resistors to A-. For more stable results, it's better to use two or four cells together.

See all projects
HC-SR04 Distance Measurement (Serial Display)
#27Beginner

HC-SR04 Distance Measurement (Serial Display)

The HC-SR04 sensor works just like a bat finding its way in the dark: it sends out a sound you cannot hear, listens for the echo and measures how far away the object in front of it is. The Arduino wri

4.6(45)
68
Temperature and Humidity with DHT11
#55Intermediate

Temperature and Humidity with DHT11

How warm is your room, and is the air humid or dry? The DHT11 sensor measures temperature and humidity, and the Arduino writes the values on a two-line LCD screen, refreshing every couple of seconds.

4.7(47)
64
Digital Voltmeter with LCD Display
#56Intermediate
Premium

Digital Voltmeter with LCD Display

Find out how much voltage a battery or power adapter gives with a meter you built yourself. A divider made of two resistors brings high voltage down to a level the board can read, and the Arduino calc

4.5(27)
36
Using LCD Screen with I2C
#32Beginner
Premium

Using LCD Screen with I2C

Give your Arduino its own screen and make it write its first message. The two-line LCD screen hooks up with just a few wires; a greeting appears on the top line, then a second message on the bottom li

4.8(53)
70
Height Measurement Project
#33Intermediate
Premium

Height Measurement Project

A height meter that hangs from a door frame and tells you, in centimetres, how tall the person standing under it is. First you press the first button with nobody underneath, and the distance sensor me

4.5(25)
34
Temperature Measurement with NTC and 2x16 Lcd Display
#44Beginner
Premium

Temperature Measurement with NTC and 2x16 Lcd Display

Measure the temperature around you with a sensor that looks like a tiny bead. This part, called an NTC, lets electricity through more easily as it warms up; the Arduino reads that change, turns it int

4.5(33)
44
ESP32 I2C LCD Display (16x2)
#119Intermediate
Premium

ESP32 I2C LCD Display (16x2)

In this project, we display text by connecting a 16x2 character LCD screen to the ESP32 via the I2C protocol. Thanks to I2C, we can control the screen using just two data pins (SDA and SCL), eliminating the waste of 6+ pins associated with a classic parallel connection. The code prints a fixed message on the first line and a counter that increments every second on the second line. Additionally, we run an I2C scanner at the start to print the display’s address to the Serial Monitor (typically 0x2

4.9(23)
40
ESP32 Temperature Data Logger (DHT22 + DS1307 RTC + microSD + OLED)
#144Advanced
Premium

ESP32 Temperature Data Logger (DHT22 + DS1307 RTC + microSD + OLED)

Build a timestamped temperature logger with ESP32! Read DHT22 temperature/humidity every minute, get real-world time from DS1307 RTC, and log to microSD card as CSV. The OLED displays live temperature (large font), humidity percentage, timestamp, and log counter. The `/temp_log.csv` file on the SD card opens in Excel, Google Sheets, or Python pandas for analysis — perfect for greenhouse monitoring, home/room temperature tracking, laboratory data collection, food storage conditions, or beehiv

4.7(7)
12