Weighing with an HX711 and a Load Cell
| Difficulty | Advanced |
|---|---|
| Category | Sensors |
| Supported boards | Arduino Uno R3 and compatible ATmega328P boards |
| Time needed | 70 minutes |
| Prerequisites | Digital and Analog, and When Each Applies |
| Tested board | Not yet verified |
| Tested on | Not yet verified |
| Arduino IDE version | Not yet verified |
| Library | Not yet verified |
What it does
A load cell is a piece of metal that bends very slightly under weight, with strain gauges bonded to it that change resistance as it bends. The change is tiny: a few microvolts per gram.
An Arduino’s analog input resolves about 5 millivolts, which is roughly a thousand times too coarse to see anything at all. The HX711 is the bridge. It is a 24-bit converter built specifically for load cells, with a built-in amplifier, and it turns those microvolts into numbers you can work with.
This is the most precise measurement in the library, and the one that most depends on doing the calibration properly.
Before you begin
Required parts and tools
- An Arduino Uno or compatible board.
- One HX711 module. This is Siratek product 2881.
- A load cell, which is not included. Buy one rated a little above the heaviest thing you mean to weigh.
- A soldering iron. The supplied ten-pin header is loose and must be soldered on.
- Something rigid to mount the cell on, and a known weight for calibration.
The board has two sides
The green board is marked clearly:
J1, the load cell side:E+ E- A- A+ B- B+JP2, the Arduino side:GND DT SCK VCC
E+ and E- excite the load cell. A- and A+ are the measurement input, channel A. B- and B+ are a second channel at lower gain, which you can ignore for a single cell.
Wiring the load cell
A four-wire load cell almost always uses these colours:
| Wire | To | Meaning |
|---|---|---|
| Red | E+ |
Excitation positive |
| Black | E- |
Excitation negative |
| White | A- |
Signal negative |
| Green | A+ |
Signal positive |
White and green are the pair that varies between manufacturers. If pressing down makes the reading go more negative, swap those two. Nothing is harmed by getting it wrong; the sign simply inverts.
Some cells have a fourth colour, often yellow, which is a shield. Connect it to GND or leave it; do not put it on a signal pin.
Mounting matters more than the electronics
This is the part people skip, and it is why a working circuit gives useless numbers.
A bar load cell is designed to be clamped at one end and loaded at the other, with the middle free to flex. The arrow on its side shows the direction the force should act.
- Bolt one end to something solid. A cell held in the hand measures your hand.
- Load the other end through a platform, with spacers so the cell can bend. If the platform touches the base anywhere else, the force bypasses the cell and the reading goes nowhere.
- Keep the load central. Weight at the far corner of a wide platform reads differently from the same weight in the middle. That is not drift; it is the cell being bent in a way it was not designed for.
Spend the time on the mechanics. A perfectly calibrated cell mounted badly is worse than useless, because it looks right.
Two numbers you must find
Every load cell and every mounting produces its own two constants.
The offset, or tare: what the system reads with nothing on it. This is not zero, and it changes if you move the platform or tighten a bolt.
The scale factor: how many raw counts correspond to one gram. This depends on the cell’s rating, the HX711’s gain and your mounting.
Neither can be looked up. Both must be measured, with the procedure below, and both must be measured again if you change the mechanics in any way.
It is slow, and that is fine
The HX711 runs at 10 samples a second, or 80 if a pin on the chip is tied differently. Ten is plenty for a scale, and the slower rate is quieter.
It is also not SPI and not I2C, despite having a clock and a data pin. It is its own simple protocol, which the library bit-bangs, so any two digital pins work.
Pin reference
| Module pin | Connect to | Purpose |
|---|---|---|
GND |
Uno GND |
Ground |
DT |
Uno D3 |
Data out of the HX711 |
SCK |
Uno D2 |
Clock from the Arduino |
VCC |
Uno 5V |
Power |
E+ E- A- A+ |
The load cell | Red, black, white, green |
Wiring steps
- Unplug the USB cable.
- Solder the ten-pin header to the board.
- Solder or screw the load cell’s four wires to
E+,E-,A-,A+by colour. GNDtoGND,VCCto5V.DTtoD3,SCKtoD2.- Mount the cell properly before taking it seriously.
- Plug the USB cable back in.
Software and libraries
Install HX711 by Bogdan Necula, or the similarly named library by Rob Tillaart. The sketches below use the first. Record which one, because their method names differ.
Minimal working example
Start with raw counts. They look meaningless and they are exactly what you need.
// Siratek: raw readings. Press on the platform and watch the numbers.
#include "HX711.h"
const int dataPin = 3;
const int clockPin = 2;
HX711 scale;
void setup() {
Serial.begin(9600);
scale.begin(dataPin, clockPin);
Serial.println("Siratek: raw counts. Press down and see which way they move.");
}
void loop() {
if (scale.is_ready()) {
Serial.println(scale.read());
} else {
Serial.println("HX711 not ready. Check DT, SCK and power.");
}
delay(500);
}
Three things to check here, in order.
Does it say “not ready”? Then the wiring is wrong, and nothing else will work.
Do the numbers change when you press? If not, the load cell wiring or the mounting is at fault, not the board.
Do they go up when you press down? If they go down, swap the white and green wires.
Calibration
Now the two constants. This is the part that turns counts into grams.
// Siratek: find the offset and the scale factor for YOUR cell and mounting.
// Follow the prompts. Write both numbers down.
#include "HX711.h"
HX711 scale;
// The weight of the object you will use. Measure it on a kitchen scale.
const float knownGrams = 500.0;
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
scale.begin(3, 2);
Serial.println("Siratek: remove everything from the platform, then send any character.");
while (Serial.available() == 0) {
delay(50);
}
while (Serial.available()) {
Serial.read();
}
scale.tare(20); // average twenty readings for the zero
long offset = scale.get_offset();
Serial.print("offset = ");
Serial.println(offset);
Serial.print("Now put the ");
Serial.print(knownGrams, 0);
Serial.println(" g weight on, then send any character.");
while (Serial.available() == 0) {
delay(50);
}
long loaded = scale.get_value(20); // averaged, with the offset removed
float factor = loaded / knownGrams;
Serial.print("raw with weight = ");
Serial.println(loaded);
Serial.print("scale factor = ");
Serial.println(factor, 4);
Serial.println();
Serial.println("Put both numbers into the weighing sketch.");
}
void loop() {
}
Use the heaviest weight you can that is still within the cell’s rating. Calibrating a 5 kg cell with a 20 g weight gives a factor dominated by noise.
A litre of water is a kilogram, near enough, and most people have a bottle.
Weighing
// Siratek: a scale, using the two numbers you measured.
#include "HX711.h"
HX711 scale;
// From the calibration sketch. Yours will differ, and they are not optional.
const long myOffset = 0;
const float myFactor = 1.0;
void setup() {
Serial.begin(9600);
scale.begin(3, 2);
scale.set_offset(myOffset);
scale.set_scale(myFactor);
Serial.println("Siratek: scale ready.");
}
void loop() {
// Average ten readings. A single one jumps around by a gram or two.
float grams = scale.get_units(10);
Serial.print(grams, 1);
Serial.println(" g");
delay(500);
}
Averaging ten readings is the difference between a scale and a random number generator. At this resolution the last digit is always moving, and the eye reads a jittering display as broken even when the average is correct.
Drift, and why a tare button is worth adding
Leave a calibrated scale running and the zero wanders, by a gram or two over an hour. Strain gauges are temperature sensitive, and the metal itself relaxes.
Real scales handle this by taring every time you use them, and so should yours: a button that calls scale.tare() costs one pin and removes the problem entirely.
if (digitalRead(tareButton) == LOW) {
scale.tare(20);
Serial.println("tared");
}
Expected result
Raw counts that move clearly when you press on the platform, and after calibration, a weight in grams accurate to a gram or two with a stable reading.
Put the known weight back on and check it reads what it should. Then put it in a different place on the platform and check again: a large difference tells you about the mounting, not the electronics.
Troubleshooting
| Symptom | Likely cause | Check or fix |
|---|---|---|
| “not ready” forever | DT and SCK swapped, or no power |
Check all four Arduino wires |
| Raw value never changes | Load cell wiring, or bad mounting | Check colours, then the mechanics |
| Reading goes down when you press | Signal pair reversed | Swap white and green |
| Wildly fluctuating raw values | A load cell wire not connected | Reseat; check solder joints |
| Weight roughly right but out by a factor | Wrong scale factor | Recalibrate with a known weight |
| Reads zero no matter what | set_scale() with the default |
Put your own factor in |
| Zero wanders over an hour | Temperature and metal relaxation | Normal; add a tare button |
| Different reading at the platform’s edge | Off-centre loading | Expected; load centrally |
| Changed after tightening a bolt | Mechanics changed | Recalibrate |
| Reading saturates under load | Cell over its rating | Use a cell rated above your maximum |
| Noisy near a motor | Microvolt signals pick up interference | Separate the supplies; keep leads short |
Next steps
- Easier first: Digital and Analog, and When Each Applies, for why an analog pin cannot do this.
- Related products: a 16×2 LCD to show the weight, and a push button for tare.
- Next project: a kitchen scale with a display and a tare button, which is a genuinely useful object rather than a demonstration.
Sources and attribution
All text, wiring guidance and code in this tutorial are original Siratek work.
- HX711 datasheet for the 24-bit conversion, the sample rates and the channel arrangement.
- The
E+ E- A- A+ B- B+andGND DT SCK VCCheaders and the loose ten-pin header were read from the Siratek product photographs for item 2881. The same photographs show the board supplied without a load cell, which is why one appears in the parts list.
Load cell wire colours are near-universal but not guaranteed, so the tutorial gives a test rather than asserting them. Offset and scale factor are presented as values the reader must measure, as they depend on the individual cell and its mounting. No third-party tutorial text, diagrams, photographs or code has been reproduced here.

