Learn how to use a load cell with the HX711 Load Cell Amplifier. In this post we’ll go over how to use a load cell with the HX711 Load Cell amplifier. We’ll cover the basic, module pin out, how to connect the load cell and the HX711, how to connect to Arduino, how to program in Arduino, and also a HX711 project.
What is a Load Cell?
A load cell is a sensor that measures the force applied to it along a specific direction and converts it to an electrical signal that can be converted to an equivalent force value. There are many types of load cells, in this post we will focus on a Bar-Type Strain Gauge Load Cells. For the load cell shown on the image, you fix one end (via screws) to a fixed object. The other end will be where the force is applied (normally attached to something). Think of this for the example of a small scale (full example further below). One end attached to the base of the scale, and the other end attached to the plate where you place things whose weight you want to measure.

What is the HX711 Load Cell Amplifier?
The HX711 Load Cell Amplifier is a module that is used to take the signal coming from your load cell and convert it into a signal that your Arduino (or similar microcontroller) can take and process. In post we’ll focus on using the HX711 for a single load cell. The HX711 runs on a supply voltage that can range from 2.6V – 5.5V and it must operate in a temperature range of -40deg C (-40deg F) to +85 deg C (185 deg F). Make sure to pay close attention to the recommended excitation voltage for the load cell being used. The load cell I will use for the example project will need a 5V excitation voltage, so that will drive me to select a 5V input voltage for the HX711 (even though the board it self has a range of 2.6V – 5.5V).

Connecting HX711 and Load Cell to Arduino Nano
From Load Cell to HX711:
Red cable: connected to E+ on HX711
White cable: connected to A- on HX711
Black cable: connected to E- on HX711
Green cable: connected to A+ on HX711
From HX711 to Arduino Nano:
GND: connected to GND on the Arduino Nano
DT: Connected to D4 on the Arduino Nano
SCK: Connected to D5 on the Arduino Nano
VCC: Connected to 5V on the Arduino Nano
Load Cell Setup – Leave room!
It is critical when setting up the Bar-Type Strain Gauge Load Cell that you leave enough room for the load cell to bend when subjected to the force that you are trying to measure. The bending induced by such force is what will induce an associated bending strain, which will translate into an electrical signal that goes into the HX711 and the Arduino to be converted into a weight or force. Net, make sure to leave room for the load cell to bend.

Example using the HX711 and a 1 Kg Load Cell
I went ahead and designed and 3D printed some parts to put together a simple small scale, so you can easily see a simple application of a load cell with the HX711.

For this example, I am using an 1602 LCD to display the weight measured by the scale. That’s the LCD screen you see in the images above. I am also showing a cross sectional view of the scale so you understand how the load cell is setup (this matches the view shown previously telling you to leave room for the load cell to bend). So now let me show you how the connections will work once we add the 1602 LCD. Also, if you need more info on the 1602 LCD, please read my other post on it –> 1602 LCD – Learn how to use with Arduino.
Connecting HX711, Load Cell, and 1602 LCD to Arduino Nano
We will simply expand from the previously shown diagram by adding the 1602 LCD, setting up for I2C mode, and connecting it to A4 and A5. It is very important to note that pins A4 and A5 can be used as SDA and SCL (respectively) in the Arduino Nano for I2C communication.
Download the Arduino Library
To run the load cell with the HX711 module, you will need to install a specific library. To do so, please go to the Arduino IDE top menu, click on “Sketch”, then go to “Include Library”, the click on “Manage Libraries…”. A pop-up window will show up. On the search bar, type “HX711_ADC” by Olav Kallhovd (see screenshot below to ensure you pick the correct one). Select and then install.
Calibrating the Load Cell
Use the code below to calibrate your load cell. Remember to open the Serial Monitor and set it to 57600 (consistent with what we have on the Arduino code). The whole objective of this code is to tare de load cell, then add a known load / known weight, tell Arduino what that weight is (via Serial Monitor) and then capture those settings as part of the calibration. This can be done by taking note of the calibration constant or saving to EEPROM.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
#include <HX711_ADC.h> #if defined(ESP8266)|| defined(ESP32) || defined(AVR) #include <EEPROM.h> #endif //pins: const int HX711_dout = 4; //mcu > HX711 dout pin const int HX711_sck = 5; //mcu > HX711 sck pin //HX711 constructor: HX711_ADC LoadCell(HX711_dout, HX711_sck); const int calVal_eepromAdress = 0; unsigned long t = 0; void setup() { Serial.begin(57600); delay(10); Serial.println(); Serial.println("Starting..."); LoadCell.begin(); //LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time boolean _tare = true; //set this to false if you don't want tare to be performed in the next step LoadCell.start(stabilizingtime, _tare); if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) { Serial.println("Timeout, check MCU>HX711 wiring and pin designations"); while (1); } else { LoadCell.setCalFactor(1.0); // user set calibration value (float), initial value 1.0 may be used for this sketch Serial.println("Startup is complete"); } while (!LoadCell.update()); calibrate(); //start calibration procedure } void loop() { static boolean newDataReady = 0; const int serialPrintInterval = 0; //increase value to slow down serial print activity // check for new data/start next conversion: if (LoadCell.update()) newDataReady = true; // get smoothed value from the dataset: if (newDataReady) { if (millis() > t + serialPrintInterval) { float i = LoadCell.getData(); Serial.print("Load_cell output val: "); Serial.println(i); newDataReady = 0; t = millis(); } } // receive command from serial terminal if (Serial.available() > 0) { char inByte = Serial.read(); if (inByte == 't') LoadCell.tareNoDelay(); //tare else if (inByte == 'r') calibrate(); //calibrate else if (inByte == 'c') changeSavedCalFactor(); //edit calibration value manually } // check if last tare operation is complete if (LoadCell.getTareStatus() == true) { Serial.println("Tare complete"); } } void calibrate() { Serial.println("***"); Serial.println("Start calibration:"); Serial.println("Place the load cell an a level stable surface."); Serial.println("Remove any load applied to the load cell."); Serial.println("Send 't' from serial monitor to set the tare offset."); boolean _resume = false; while (_resume == false) { LoadCell.update(); if (Serial.available() > 0) { if (Serial.available() > 0) { char inByte = Serial.read(); if (inByte == 't') LoadCell.tareNoDelay(); } } if (LoadCell.getTareStatus() == true) { Serial.println("Tare complete"); _resume = true; } } Serial.println("Now, place your known mass on the loadcell."); Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor."); float known_mass = 0; _resume = false; while (_resume == false) { LoadCell.update(); if (Serial.available() > 0) { known_mass = Serial.parseFloat(); if (known_mass != 0) { Serial.print("Known mass is: "); Serial.println(known_mass); _resume = true; } } } LoadCell.refreshDataSet(); //refresh the dataset to be sure that the known mass is measured correct float newCalibrationValue = LoadCell.getNewCalibration(known_mass); //get the new calibration value Serial.print("New calibration value has been set to: "); Serial.print(newCalibrationValue); Serial.println(", use this as calibration value (calFactor) in your project sketch."); Serial.print("Save this value to EEPROM adress "); Serial.print(calVal_eepromAdress); Serial.println("? y/n"); _resume = false; while (_resume == false) { if (Serial.available() > 0) { char inByte = Serial.read(); if (inByte == 'y') { #if defined(ESP8266)|| defined(ESP32) EEPROM.begin(512); #endif EEPROM.put(calVal_eepromAdress, newCalibrationValue); #if defined(ESP8266)|| defined(ESP32) EEPROM.commit(); #endif EEPROM.get(calVal_eepromAdress, newCalibrationValue); Serial.print("Value "); Serial.print(newCalibrationValue); Serial.print(" saved to EEPROM address: "); Serial.println(calVal_eepromAdress); _resume = true; } else if (inByte == 'n') { Serial.println("Value not saved to EEPROM"); _resume = true; } } } Serial.println("End calibration"); Serial.println("***"); Serial.println("To re-calibrate, send 'r' from serial monitor."); Serial.println("For manual edit of the calibration value, send 'c' from serial monitor."); Serial.println("***"); } void changeSavedCalFactor() { float oldCalibrationValue = LoadCell.getCalFactor(); boolean _resume = false; Serial.println("***"); Serial.print("Current value is: "); Serial.println(oldCalibrationValue); Serial.println("Now, send the new value from serial monitor, i.e. 696.0"); float newCalibrationValue; while (_resume == false) { if (Serial.available() > 0) { newCalibrationValue = Serial.parseFloat(); if (newCalibrationValue != 0) { Serial.print("New calibration value is: "); Serial.println(newCalibrationValue); LoadCell.setCalFactor(newCalibrationValue); _resume = true; } } } _resume = false; Serial.print("Save this value to EEPROM adress "); Serial.print(calVal_eepromAdress); Serial.println("? y/n"); while (_resume == false) { if (Serial.available() > 0) { char inByte = Serial.read(); if (inByte == 'y') { #if defined(ESP8266)|| defined(ESP32) EEPROM.begin(512); #endif EEPROM.put(calVal_eepromAdress, newCalibrationValue); #if defined(ESP8266)|| defined(ESP32) EEPROM.commit(); #endif EEPROM.get(calVal_eepromAdress, newCalibrationValue); Serial.print("Value "); Serial.print(newCalibrationValue); Serial.print(" saved to EEPROM address: "); Serial.println(calVal_eepromAdress); _resume = true; } else if (inByte == 'n') { Serial.println("Value not saved to EEPROM"); _resume = true; } } } Serial.println("End change calibration value"); Serial.println("***"); } |
Testing the Load Cell
We will now test the load cell with the LCD. For this we use a different code. Note that for this you will need the LiquidCrystal_I2C library. See my previous post for more info: 1602 LCD with Arduino. The code below will allow you to display the weight measured by your load cell both by displaying on your Serial Monitor (set to 57600) and by displaying the load on the LCD. Note that I did my calibration in grams, so I print the weight in grams in the LCD (meaning I print it as Weight(g): X, where “X” is the load being measured).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
#include <LiquidCrystal_I2C.h>// include the library code #include <HX711_ADC.h> #if defined(ESP8266)|| defined(ESP32) || defined(AVR) #include <EEPROM.h> #endif LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address and the number of columns and rows //pins: const int HX711_dout = 4; //mcu > HX711 dout pin const int HX711_sck = 5; //mcu > HX711 sck pin //HX711 constructor: HX711_ADC LoadCell(HX711_dout, HX711_sck); const int calVal_eepromAdress = 0; unsigned long t = 0; void setup() { lcd.begin(); // set up the LCD's number of columns and rows: Serial.begin(57600); delay(10); Serial.println(); Serial.println("Starting..."); LoadCell.begin(); //LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive float calibrationValue; // calibration value (see example file "Calibration.ino") calibrationValue = 696.0; // uncomment this if you want to set the calibration value in the sketch #if defined(ESP8266)|| defined(ESP32) EEPROM.begin(512); // uncomment this if you use ESP8266/ESP32 and want to fetch the calibration value from eeprom #endif EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time boolean _tare = true; //set this to false if you don't want tare to be performed in the next step LoadCell.start(stabilizingtime, _tare); if (LoadCell.getTareTimeoutFlag()) { Serial.println("Timeout, check MCU>HX711 wiring and pin designations"); while (1); } else { LoadCell.setCalFactor(calibrationValue); // set calibration value (float) Serial.println("Startup is complete"); } } void loop() { static boolean newDataReady = 0; const int serialPrintInterval = 0; //increase value to slow down serial print activity // check for new data/start next conversion: if (LoadCell.update()) newDataReady = true; // get smoothed value from the dataset: if (newDataReady) { if (millis() > t + serialPrintInterval) { float i = LoadCell.getData(); Serial.print("Load_cell output val: "); Serial.println(i); //LCD Print lcd.clear(); // Clears the display lcd.setCursor(0,0); // set the cursor to column 0, line 0 lcd.print("DIYEngineers.com"); lcd.setCursor(0,1); // set the cursor to column 0, line 1 lcd.print("Weight(g): " + String(int(i))); newDataReady = 0; delay(500); t = millis(); } } } |
Results
Once the calibration is complete and the 2nd Arduino is running, you should be able to see the load cell reading on both the Serial Monitor within Arduino IDE as well as on the 1602 LCD. In the images below I show the load cell with no load applied and with a box weighing ~700 grams on top of it.
Components used in this example
*As an Amazon & Ebay Associate I earn from qualifying purchases.
Component | Link |
Arduino Nano | https://ebay.us/tqQZBm |
Load Cell (1 Kg) + HX711 Load Cell Amplifier | https://ebay.us/FpZHWR |
1602 LCD (with I2C module) | https://ebay.us/sofDTP |
Hello, thanks for the explanation.
Can you please guide me how to write a code for esp32 to get command signals from a load cell. Eg. (if the weight is less than 300g, send a signal to power a servo motor to turn 180° clockwise . Then once the weight reaches 500g send a signal to power a servo motor to turn 180° clockwise. (the purpose of servo is to open and close a food dispenser opening.)
Thank you.
Hi …I am working on same project and have same queries as yours can you help me with the code ..pls get in touch
unknownmind8@gmail.com
Hello, I would like to know what measuring speed is possible to achieve. I would need to measure the load 360x in 20ms. Is it feasible? Thank you for answer.
Is it possible to use two or four 4 wire 100 kg load cell so I can measure 200 or 400 kg ? Tnx