In this guide, you’ll learn how to create a scale with the ESP32 using a load cell and the HX711 amplifier. First, you’ll learn how to wire the load cell and the HX711 amplifier to the ESP32 to build a scale. Then, we’ll show you how to calibrate the scale, and a simple example to get the weight of objects. Later, we’ll also add a display to show the measurements and a button to tare the scale.
Table of Contents
In this tutorial, we’ll cover the following topics:
- Introducing Load Cells (Strain Gauges)
- HX711 Amplifier
- Setting Up Load Cell
- Wiring Load Cell and HX711 Amplifier to the ESP32
- Installing HX711 Library
- Calibrating the Scale
- Weighting Objects – Code
- Digital Scale with ESP32
Introducing Load Cells
A load cell converts a force into an electrical signal that can be measured. The electrical signal changes proportionally to the force applied. There are different types of load cells: strain gauges, pneumatic, and hydraulic. In this tutorial, we’ll cover strain gauge load cells.
Strain gauge load cells are composed of a metal bar with attached strain gauges (under the white glue in the picture above). A strain gauge is an electrical sensor that measures force or strain on an object. The resistance of the strain gauges varies when an external force is applied to an object, which results in a deformation of the object’s shape (in this case, the metal bar). The change of the resistance is proportional to the load applied, which allows us to calculate the weight of objects.
Usually, load cells have four strain gauges hooked up in a Wheatstone bridge (as shown below) that allow us to get accurate resistance measurements. For a more detailed explanation of how strain gauges work, read this article.
The wires coming from the load cell usually have the following colors:
- Red: VCC (E+)
- Black: GND (E-)
- White: Output – (A-)
- Green: Output + (A+)
Applications
Strain gauge load cells can be used in a wide variety of applications. For example:
- check if an object’s weight changes over time;
- measure the weight of an object;
- detect the presence of an object;
- estimate a container’s liquid level;
- etc.
Because the changes in strain when weighting objects are so small, we need an amplifier. The load cell we’re using is usually sold together with an HX711 amplifier. So, that’s the amplifier we’ll use.
HX711 Amplifier
The HX711 amplifier is a breakout board that allows you to easily read load cells to measure weight. You wire the load cell wires on one side, and the microcontroller on the other side. The HX711 communicates with the microcontroller using two-wire interface (Clock and Data).
You need to solder header pins on the GND, DT, SCK, and VCC pins to connect to the ESP32. I soldered the load cell wires directly to the E+, E-, A-, and A+ pins. The load cell wires were very thin and fragile, be careful when soldering to not damage the wires.
For more information about the HX711 amplifier, you can consult the HX711 datasheet.
Setting Up the Load Cell
Our load cell kit came with two acrylic plates and some screws to set up the load cell as a scale. You can use wood plates or 3D-print your own plates.
You should attach the plates to the load cell in a way that creates a strain between the opposite ends of the metal bar. The bottom plate holds the load cell, and the upper plate is where you place the objects.
The following figure shows what my load cell with the acrylic plates looks like.
Where to Buy Load Cell with HX711?
You can check the load cell with the HX711 on Maker Advisor to find the best price (with or without acrylic plates included). There are load cells with different measurement ranges. The most common maximum weights are 1kg, 5kg, 10kg, and 20kg.
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Wiring Load Cell and HX711 Amplifier to the ESP32
The HX711 amplifier communicates via two-wire interface. You can connect it to any GPIOs of your chosen microcontroller. We’re connecting the data pin (DT) to GPIO 16 and the clock pin (CLK) to GPIO 4. You can use any other suitable pins (check the ESP32 pinout guide).
Follow the next table or schematic diagram to wire the load cell to the ESP32 board.
Load Cell | HX711 | HX711 | ESP32 |
Red (E+) | E+ | GND | GND |
Black (E-) | E- | DT | GPIO 16 |
White (A-) | A- | SCK | GPIO 4 |
Green (A+) | A+ | VCC | 3.3V |
Installing the HX711 Library
There are several different libraries to get measurements from a load cell using the HX711 amplifier. We’ll use the HX711 library by bodge. It is compatible with the ESP32, ESP8266, and Arduino.
Arduino IDE
Follow the next instructions to install the library if you’re using Arduino IDE.
- Open Arduino IDE and go to Sketch > Include Library > Manage Libraries.
- Search for “HX711 Arduino Library” and install the library by Bogdan Necula.
VS Code with PlatformIO
If you’re using VS Code with the PlatformIO extension to program your boards, follow the next instructions.
- After creating a new project on PlatformIO for your board, go to the PIO Home (click on the house icon on the bottom bar). Then, click on Libraries. Search for HX711 and select the Library by bodge.
- Then, click on Add to Project and select the project you’re working on.
Now, if you go to your project folder and open the platformio.ini file, there should be a line to include the library as follows:
lib_deps = bogde/HX711@^0.7.5
Also add the following line to change the Serial Monitor speed to 115200:
monitor_speed = 115200
Calibrating the Scale (ESP32 with Load Cell)
At this time, we assume you have wired the load cell to the HX711 amplifier and the amplifier to the ESP32. You should also have your scale set up (two plates wired on opposite ends on the load cell), and have installed the HX711 library.
Before getting the weight of objects, you need to calibrate your load cell first by getting the calibration factor. Your calibration factor will be different than mine, so you shouldn’t skip this section.
1) Prepare an object with a known weight. I used my kitchen scale and weighed a glass with water (300g).
2) Upload the following code to your ESP32. We wrote the following code taking into account the instructions to calibrate the load cell provided by the library documentation.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-load-cell-hx711/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
// Calibrating the load cell
#include <Arduino.h>
#include "soc/rtc.h"
#include "HX711.h"
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 16;
const int LOADCELL_SCK_PIN = 4;
HX711 scale;
void setup() {
Serial.begin(115200);
rtc_cpu_freq_config_t config;
rtc_clk_cpu_freq_get_config(&config);
rtc_clk_cpu_freq_to_config(RTC_CPU_FREQ_80M, &config);
rtc_clk_cpu_freq_set_config_fast(&config);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}
void loop() {
if (scale.is_ready()) {
scale.set_scale();
Serial.println("Tare... remove any weights from the scale.");
delay(5000);
scale.tare();
Serial.println("Tare done...");
Serial.print("Place a known weight on the scale...");
delay(5000);
long reading = scale.get_units(10);
Serial.print("Result: ");
Serial.println(reading);
}
else {
Serial.println("HX711 not found.");
}
delay(1000);
}
//calibration factor will be the (reading)/(known weight)
3) After uploading, open the Serial Monitor at a baud rate of 115200 and reset the ESP32 board.
4) Follow the instructions on the Serial Monitor: remove any weights from the scale (it will tare automatically). Then, place an object with a known weight on the scale and wait until you get a value.
5) Calculate your calibration factor using the formula:
calibration factor = (reading)/(known weight)
In our case, the reading is -141449. The known weight is 300g, so our calibration factor will be: -141449/300 = -471.497.
calibration factor = -141449/300 = -471.497
Save your calibration factor because you’ll need it later. Yours will be different than ours.
Because the output of the sensor is proportional to the force applied to the load cell, you can calibrate your scale using whatever unit makes sense for you. I used grams, but you can use pounds, kilograms, or even pieces of cat food (as in this Andreas Spiess video).
Weighting Objects (ESP32 with Load Cell)
Now that you know your calibration factor, you can use your load cell to weight objects. Start by weighing objects with a known weight and repeat the calibration process if the values are not accurate.
Copy the following code to your Arduino IDE. Before uploading it to your board, don’t forget to insert your calibration factor in line 43/44 of the code. The following code is the example provided by the library that demonstrates the use of most of its functions.
/*
* Complete project details at https://RandomNerdTutorials.com/esp32-load-cell-hx711/
*
* HX711 library for Arduino - example file
* https://github.com/bogde/HX711
*
* MIT License
* (c) 2018 Bogdan Necula
*
**/
#include <Arduino.h>
#include "HX711.h"
#include "soc/rtc.h"
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 16;
const int LOADCELL_SCK_PIN = 4;
HX711 scale;
void setup() {
Serial.begin(115200);
rtc_cpu_freq_config_t config;
rtc_clk_cpu_freq_get_config(&config);
rtc_clk_cpu_freq_to_config(RTC_CPU_FREQ_80M, &config);
rtc_clk_cpu_freq_set_config_fast(&config);
Serial.println("HX711 Demo");
Serial.println("Initializing the scale");
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
Serial.println("Before setting up the scale:");
Serial.print("read: \t\t");
Serial.println(scale.read()); // print a raw reading from the ADC
Serial.print("read average: \t\t");
Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC
Serial.print("get value: \t\t");
Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight (not set yet)
Serial.print("get units: \t\t");
Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight (not set) divided
// by the SCALE parameter (not set yet)
scale.set_scale(INSERT YOUR CALIBRATION FACTOR);
//scale.set_scale(-471.497); // this value is obtained by calibrating the scale with known weights; see the README for details
scale.tare(); // reset the scale to 0
Serial.println("After setting up the scale:");
Serial.print("read: \t\t");
Serial.println(scale.read()); // print a raw reading from the ADC
Serial.print("read average: \t\t");
Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC
Serial.print("get value: \t\t");
Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight, set with tare()
Serial.print("get units: \t\t");
Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight, divided
// by the SCALE parameter set with set_scale
Serial.println("Readings:");
}
void loop() {
Serial.print("one reading:\t");
Serial.print(scale.get_units(), 1);
Serial.print("\t| average:\t");
Serial.println(scale.get_units(10), 5);
scale.power_down(); // put the ADC in sleep mode
delay(5000);
scale.power_up();
}
How the Code Works
Start by including the required libraries. We’ve included Arduino.h in case you’re using PlatformIO instead of Arduino IDE.
#include <Arduino.h>
#include "HX711.h"
#include "soc/rtc.h"
Note: we’ve read in some places that you need to slow down the ESP32 processor because of the HX711 frequency. I’m not sure if this is really needed or not. We’ve experimented with and without slowing down and everything worked fine in both scenarios. Nonetheless, we’ve added that option to the code. You can always remove it. To do that you need to include soc/rtc.h.
The following lines define the GPIOs you’ll use to connect to the HX711 amplifier. We chose GPIOs 16 and 4. You can use any other suitable GPIOs.
const int LOADCELL_DOUT_PIN = 16;
const int LOADCELL_SCK_PIN = 4;
Then, create an instance of the HX711 library called scale that you’ll use later on to get the measurements.
HX711 scale;
setup()
In the setup(), initialize the Serial monitor.
Serial.begin(115200);
Slow down the ESP32 processor.
rtc_cpu_freq_config_t config;
rtc_clk_cpu_freq_get_config(&config);
rtc_clk_cpu_freq_to_config(RTC_CPU_FREQ_80M, &config);
rtc_clk_cpu_freq_set_config_fast(&config);
Initialize the load cell by calling the begin() method on the scale object and passing the GPIOs as arguments.
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
Then, it calls several methods that you can use to get readings using the library.
- read(): gets a raw reading from the sensor
- read_average(number of readings): gets the average of the latest defined number of readings
- get_value(number of readings): gets the average of the last defined number of readings minus the tare weight;
- get_units(number of readings): gets the average of the last defined number of readings minus the tare weight divided by the calibration factor — this will output a reading in your desired units.
Serial.println("Before setting up the scale:");
Serial.print("read: \t\t");
Serial.println(scale.read()); // print a raw reading from the ADC
Serial.print("read average: \t\t");
Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC
Serial.print("get value: \t\t");
Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight (not set yet)
Serial.print("get units: \t\t");
Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight (not set) divided
// by the SCALE parameter (not set yet)
In the following line, don’t forget to insert your calibration factor. It uses the set_scale() method.
scale.set_scale(INSERT YOUR CALIBRATION FACTOR)
Then, call the tare() method to tare the scale.
scale.tare(); // reset the scale to 0
After this setup, the scale should be ready to get accurate readings in your desired unit. The example calls the same previous methods so that you can see the difference before and after setting up the scale.
Serial.print("read: \t\t");
Serial.println(scale.read()); // print a raw reading from the ADC
Serial.print("read average: \t\t");
Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC
Serial.print("get value: \t\t");
Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight, set with tare()
Serial.print("get units: \t\t");
Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight, divided
// by the SCALE parameter set with set_scale
loop()
In the loop(), the example calls the get_units() method in two different ways: to get one single readings (without any parameters) and to get the average of the last 10 readings.
Serial.print("one reading:\t");
Serial.print(scale.get_units(), 1);
Serial.print("\t| average:\t");
Serial.println(scale.get_units(10), 5);
It shuts down the ADC that reads the sensor by using the power_down() method. Then, it waits for 5 seconds, powers up the ADC (power_up()), and the loop() repeats. So, you’ll get new readings on the Serial Monitor every 5 seconds.
scale.power_down(); // put the ADC in sleep mode
delay(5000);
scale.power_up();
Demonstration
Upload the code to your ESP32 board. After uploading, open the Serial Monitor at a baud rate of 115200.
Let the code run a few seconds so that it has time to set up the scale (you’ll see the message on the Serial Monitor). Then, place any object on the scale to measure it and you’ll get the results on the Serial Monitor.
I experimented with several objects and compared them against the value on my kitchen scale, and the results were the same. So, I can say that my ESP32 scale is at least as accurate as my kitchen scale.
Digital Scale with ESP32
In this section, we’ll create a simple digital scale with the ESP32. We’ll add an OLED display to show the results and a pushbutton to tare the scale.
Parts Required
Here’s a list of the parts required for this project:
- ESP32 (read Best ESP32 Development Boards)
- Load Cell with HX711 Amplifier
- I2C SSD1306 OLED Display
- Pushbutton
- 10K Ohm Resistor
- Breadboard
- Jumper Wires
Schematic Diagram
Add an OLED display and a pushbutton to your previous circuit on the following pins:
OLED Display | ESP32 |
VCC | 3.3V or 5V* |
GND | GND |
SDA | GPIO 21 |
SCL | GPIO 22 |
*connect to 3.3V or 5V depending on the model.
Not familiar with the OLED display? Read: ESP32 OLED Display with Arduino IDE
Wire the pushbutton via a 10kOhm pull-down resistor to GPIO 19. The other lead of the pushbutton should be connected to 3.3V. You can use any other suitable GPIO (check the ESP32 pinout guide).
You can follow the next schematic diagram to wire your parts.
ESP32 Digital Scale – Code
For simplicity, we’ll handle the pushbutton using a simple library that detects button presses with debouncing (so we don’t need to worry about that in our code). To write to the OLED display, we’ll use the Adafruit SSD1306 and Adafruit GFX libraries.
Pushbutton Library
There are many libraries with many functionalities to handle pushbuttons. We’ll use the pushbutton library by polulu. It is a simple library but comes with everything we need for this project. In your Arduino IDE, go to Sketch > Include Library > Manage Libraries and search for “pushbutton“. Install the pushbutton library by polulu.
Alternatively, if you don’t want to use the library you can add the debounce code yourself (which is not difficult). For a debounce code example, in the Arduino IDE, you can go to File > Examples > Digital > Debounce.
OLED Libraries
We’ll use the following libraries to control the OLED display. Make sure you have these libraries installed:
You can install the libraries using the Arduino Library Manager. Go to Sketch > Include Library > Manage Libraries and search for the library name.
Installing Libraries – PlatformIO
If you’re using VS Code with the PlatformIO extension, follow the next steps to install the library:
- After creating a new project on PlatformIO for your board, go to the PIO Home (click on the house icon on the bottom bar). Then, click on Libraries. Search for pushbutton and select the Pushbutton library by Polulu.
- Then, click on Add to Project and select the project you’re working on.
- Repeat the process for the Adafruit SSD1306 and Adafruit GFX libraries. Also, don’t forget to add the HX711 library too.
In your platformio.ini file, you should have the following lines that include all the required libraries (also change the Serial Monitor speed to 115200).
monitor_speed = 115200
lib_deps =
bogde/HX711@^0.7.5
pololu/Pushbutton@^2.0.0
adafruit/Adafruit SSD1306@^2.4.6
adafruit/Adafruit GFX Library@^1.10.10
Code
Copy the following code to your Arduino IDE. Before uploading it to the ESP32, you need to insert your calibration factor (obtained previously).
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-load-cell-hx711/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
// Library HX711 by Bogdan Necula: https://github.com/bogde/HX711
// Library: pushbutton by polulu: https://github.com/pololu/pushbutton-arduino
#include <Arduino.h>
#include "HX711.h"
#include "soc/rtc.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Pushbutton.h>
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 16;
const int LOADCELL_SCK_PIN = 4;
HX711 scale;
int reading;
int lastReading;
//REPLACE WITH YOUR CALIBRATION FACTOR
#define CALIBRATION_FACTOR -471.497
//OLED Display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//Button
#define BUTTON_PIN 19
Pushbutton button(BUTTON_PIN);
void displayWeight(int weight){
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
// Display static text
display.println("Weight:");
display.display();
display.setCursor(0, 30);
display.setTextSize(2);
display.print(weight);
display.print(" ");
display.print("g");
display.display();
}
void setup() {
Serial.begin(115200);
rtc_cpu_freq_config_t config;
rtc_clk_cpu_freq_get_config(&config);
rtc_clk_cpu_freq_to_config(RTC_CPU_FREQ_80M, &config);
rtc_clk_cpu_freq_set_config_fast(&config);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(2000);
display.clearDisplay();
display.setTextColor(WHITE);
Serial.println("Initializing the scale");
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale(CALIBRATION_FACTOR); // this value is obtained by calibrating the scale with known weights; see the README for details
scale.tare(); // reset the scale to 0
}
void loop() {
if (button.getSingleDebouncedPress()){
Serial.print("tare...");
scale.tare();
}
if (scale.wait_ready_timeout(200)) {
reading = round(scale.get_units());
Serial.print("Weight: ");
Serial.println(reading);
if (reading != lastReading){
displayWeight(reading);
}
lastReading = reading;
}
else {
Serial.println("HX711 not found.");
}
}
How the Code Works
Start by including the required libraries:
#include <Arduino.h>
#include "HX711.h"
#include "soc/rtc.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Pushbutton.h>
Define the pins for the HX711 (load cell)—we’re using the same as previous examples:
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 16;
const int LOADCELL_SCK_PIN = 4;
Create an HX711 instance called scale.
HX711 scale;
The following variables will hold the current weight reading and the last weight reading. We only want to update the OLED display in case there’s a new reading, so that’s why we need these two variables. Additionally, we don’t want to measure decimals of grams which will make the scale too sensitive for our application—that’s why these variables are integers. If you need decimals in your measurements, you can define float variables instead.
int reading;
int lastReading;
Don’t forget to replace the next value with your calibration factor. In my case, that line of code looks as follows (my value is negative):
#define CALIBRATION_FACTOR -471.497
Next, we need to define the OLED width and height:
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
And create an instance of the Adafruit_SSD1306 library called display.
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Define the GPIO you’ll use to read the button and create a Pushbutton object called button on that pin.
#define BUTTON_PIN 19
Pushbutton button(BUTTON_PIN);
displayWeight() function
We created a function called displayWeight() that accepts as arguments the weight you want to display on the OLED.
void displayWeight(int weight){
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
// Display static text
display.println("Weight:");
display.display();
display.setCursor(0, 30);
display.setTextSize(2);
display.print(weight);
display.print(" ");
display.print("g");
display.display();
}
Not familiar with the OLED display? Read: ESP32 OLED Display with Arduino IDE.
setup()
In the setup(), initialize the Serial Monitor.
Serial.begin(115200);
Initialize the OLED display:
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(2000);
display.clearDisplay();
display.setTextColor(WHITE);
And finally, initialize the load cell:
Serial.println("Initializing the scale");
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale(CALIBRATION_FACTOR); // this value is obtained by calibrating the scale with known weights
scale.tare(); // reset the scale to 0
loop()
The pushbutton library allows us to wait for an event in case of a pushbutton press or pushbutton release. In this case, we check whether the pushbutton was pushed using the getSingleDebouncePress() method and call the tare() function if the button was pressed.
if (button.getSingleDebouncedPress()){
Serial.print("tare...");
scale.tare();
}
The HX711 provides a non-blocking method to get readings. It defines a maximum timeout to wait for the hardware to be initialized and doesn’t block your code in case the scale gets disconnected or in case of hardware failures.
if (scale.wait_ready_timeout(200)) {
reading = round(scale.get_units());
Serial.print("Weight: ");
Serial.println(reading);
In the loop(), we are constantly getting new readings and checking them against the latest reading. If we got a new measurement, we call the displayWeight() function to update the OLED display.
if (reading != lastReading){
displayWeight(reading);
}
Demonstration
After uploading the code to your board, you can start weighing objects with your load cell. The readings will show up on the OLED display. You can tare the scale by pressing the pushbutton.
Once again, the readings on my ESP32 digital scale correspond to the readings on my kitchen scale.
Wrapping Up
In this tutorial, you learned how to interface a strain gauge load cell with the ESP32 using the HX711 amplifier. The output of the load cell is proportional to the force applied. So, you can calibrate it to be used in g, kg, ib, or any other unit that makes sense for your project.
In summary, you learned how to calibrate the scale and how to get the weight of objects. You also learned how to create a simple digital scale with the ESP32 using an OLED display to show the measurements and a pushbutton to tare the scale.
We hope you found this tutorial useful to get you started with a load cell. Besides being useful to measure the weight of objects, it can also be useful in many applications like detecting the presence of an object, estimating the level of liquid in a tank, calculating water’s evaporation rate, checking if there’s food on your pet’s bowl, etc.
Because of the wi-fi capabilities of the ESP32, you can build an IoT scale using a web server to display the results on your browser’s smartphone, or save the readings on the Firebase database and access them from anywhere, send a notification when the weight is below a certain value, etc. What IoT tutorials would you like to see using the load cell? Let us know in the comments below.
We have tutorials for other popular sensors that you might find useful:
- ESP32: K-Type Thermocouple with MAX6675 Amplifier (Temperature Sensor)
- ESP32 with DS18B20: Temperature Sensor
- ESP32 with BME680: Gas, Pressure, Humidity, and Temperature Sensor
- ESP32 with BME280: Temperature, Humidity, and Pressure Sensor
- ESP32 DHT11/DHT22: Temperature, and Humidity Sensor
- ESP32 with BMP388: Altimeter Sensor
- ESP32 HC-SR04: Ultrasonic Distance Sensor
- ESP32 PIR: Motion Sensor
- ESP32 BMP180: Pressure Sensor
- ESP32 with BH1750 Ambient Light Sensor
- ESP32 with TDS Sensor (Water Quality)
Learn more about the ESP32 with our resources:
Someone needs a soldering lesson! that HX711looks like it is a problem waiting to happen, especially since the red and black could touch.
Some tips:
Twist the bare strands of the wire together before soldering.
Put the wire through the hole, making sure there are no strands sticking out.
Apply the soldering iron to the PCB pad and wire.
Feed a little solder to the junction.
Trim excess wire so that there is no chance of them touching other wires or parts.
Dave
Hi,
Yes, you are right. And thanks for the tips.
But what happened was that I messed up the connections at first. Then, I had to desolder everything and I couldn’t remove the solder on the holes. So, I had to solder the wires at the top. Additionally, the wires were so thin, that they broke with a little bend. I have to admit that I’m not proud of that soldering job :\
Thanks for your comment.
Regards,
Sara
“Then, I add to desolder everything and I couldn’t remove the solder on the holes.”
Put a paper towel on table…add solder to blob up the connection hole…heat up the solder and quickly tap the board on the table.
Hi.
Thanks for the tip.
I’ll try that next time.
Regards,
Sara
You can also get stainless steel rod/file sets made for this purpose. Heat up the solder and run an appropriate sized rod through the hole and you’re done.
Just one correction: You wrote “The strain gauge resistance is proportional to the load applied”. It should read: the change of the resistance ist proportional…
The change ist usually less than 0.1 percent of the straingauge resistance.
Hi.
Yes. You are right. I’ll fix that.
Thanks for your comment.
Regards,
Sara
Hola muy bueno una consulta el esp32 trabaja con niveles de 0 a 3v no hay problemas con el hx711 en ese caso?
Hi.
I had no issues at all.
Regards,
Sara
How about a similar project in micropython?
Dear Tutorial
I want to ask about digital scale code. I alread try the code digital scale with hx711 and the result is good . it can ready material weight on the top of the loadcell.
I want to improve feature the weigh with lock the reading on screen after the weigh stable for 3 second.
Please help me , how to read the stable weigh for 3 second and put the read onscreen. If we want to weigh another , we only start with push the zero button.
Thanks for your kindness
Best regards
Aswan
From indonesia
Hello Aswan,
Your question my be answered by reading how to “multi-task” in the three part articles here:
https://learn.adafruit.com/multi-tasking-the-arduino-part-1
https://learn.adafruit.com/multi-tasking-the-arduino-part-2
https://learn.adafruit.com/multi-tasking-the-arduino-part-3
If you go through these examples you will learn a variety of ways to manage the timing of tasks for which the controller is responsible.
Hope this helps.
Forrest Erickson
Hi,
I was wondering if anyone might have any thoughts on what would be the minimum weight that could be measured. Could it potentially measure down to, say, 1 gram? I’m working on a project to measure things like air speed or current speed in water, in a creative way. So, have some sort of filament, perhaps a piece of plastic, that the force is applied to, and have that filament apply a force to the sensor. Does it make any sense to think that something like that could work?
Hi.
Yes, the load cell is very sensitive and it is possible to calibrate it using very small weights.
Regards,
Sara
It takes so much work to make a strain gauge from scratch. Congrats for getting one going! Very fun article!
I want to measure the tension in a streached screen so do I have to add weight to make sure the load cell is in full contact with the screen?
Thank you for the hx711 tutorial, it has been very useful in helping me develop my project to calculate the volume and flow rate of liquid being poured into a container.
I had some issues with my project in regards to using further functions from the pololu pushbutton library like waitForButton() and I would like to inform you of what I found.
In your hx711 tutorial the pushbutton is wired as follows: The 3.3volt rail is wired to one side of the pushbutton, the other side of the pushbutton is wired to GPIO19 and the 10k resistor, the other end of the resistor is wired to 0 volts.
The theory being the input is held low by the 10k resistor while the button is unpressed, and the input rises to 3.3 volts while the button is pressed.
Then a default pushbutton object is created in the code with:
Pushbutton button(BUTTON_PIN);
The documentation on the pololu github page says:
“This library supports many different ways of connecting a button to your board. The simplest way is to select a pin that is not being used for anything else and to connect a normally-open momentary pushbutton from that pin to ground.”
And is followed with:
“To create a Pushbutton object with default settings, which enables the internal pull-up on the pin and interprets a high pin value as the default (unpressed) state of the button, put these lines near the top of your sketch:”
#include <Pushbutton.h>
Pushbutton button(BUTTON_PIN);
The theory being that the input is held high by the internal pullup resistor and goes low when the button is pressed.
With the hardware being wired in reverse, using waitForPress() didn’t respond until the button was released, using waitForRelease() would respond when the button was pressed, and using waitForButton() resulting in no waiting because the input was already low.
I had already soldered my project together, so I (mostly) resolved the problem by declaring the button:
Pushbutton button(BUTTON_PIN,1,0);
Which should set the default unpressed button state to low.
I say mostly because with the internal pullup pulling the input up and the 10k resistor pulling the input down, the input rests somewhere between 1.6 and 0.3 volts while the button is unpressed, depending on the value of the pullup resistor, which is between 10k and 100k according to expressif.
Again, thank you for the tutorial, I found it most useful.
Regards,
Wayne
Pololu references:
https://github.com/pololu/pushbutton-arduino
Internal pullup resistance:
https://esp32.com/viewtopic.php?t=5111
Hi Sara,
Thanks for this great article.
I am new to this field, and I currently using ESP8266 board, HX711 and load cell, everything is working fine so far but I have issues with calibrating factor.
If i can get more info on that, It will help out a lot.
Thank you
Hi.
Can you be more specific?
What issues?
Regards,
Sara
Hi sara, can i ask u about HX711, my serial monitor appears the words “HX711 not found”, I’m confused what the problem is, thanks
Hi.
It’s probably a wrong connection/wiring on your circuit or the module is broken.
Regards,
Sara
Hey Sara,
I am using ESP32 with load cell which is connected through HX711 amplifier(same as described above).
I connect all wires same as you described in this website.
But I cant be able to calibrate my load cell.
my calibration factor is changed every time even with the same weight. and when i used this calibration factor in the weight measure program it shows very different values.
FOR EXAMPLE:
I calibrate with 800g/1 kg/2 kg and the values it shows are
646 and 698 for 800g
10 and -11 for 1 kg
20 and -125 for 2 kg.
After calculating calibration factor with the above values, weight scale shows very different weight. and also the values were fluctuating like 4000/5000/3056/1234 and so on. It Should give the stable values? should’nt it?
Can you please help me with this. I am trying to build my university project. I can give you more details if you want.
Hi sara, first of all thank you very much for this tutorial im using it as my tesis and this helps em a lot. Im really new in arduino and ESP32 but im trying to learn. I only want to ask you about the code, when i paste on my project (Im using VsCode with PlatformIO) i have an error on this function
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M);
The error is this —> identifier “rtc_clk_cpu_freq_set” is undefined
Searching i find this function “rtc_clk_cpu_freq_set” is in ESP8266 boards and not (in my case) in ESP32 v4.
My question is: Is really necesary change the cpu frecuency to 80mhz? or i can try to test without the cpu frecuency change.
Again, thank you very much to share this tutorial, i will link this on my presentation.
Try it without that line and see if you get good results.
Regards,
Sara
Hi
which kind of pins can be used instead of GPIO16 and GPIO4 and why?
For example GPIO17 and GPIO16 also can be used but other GPIO couple no.
Why??
Thanks
Hi.
Yes, you can use other GPIOs depending on the board you’re using.
Make sure you use a safe pin for input — check the ESP32 GPIO guide: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
Regards,
Sara
Thanks Sara – this was a great demonstration and I am able to get the weight displayed in the serial monitor -BUT I have hard times with 2 of the below:
Displaying in the OLED (I am using “AITIAO 2PCS 0.96″ OLED ESP-WROOM-32 ESP32 Display 2.4GHz WiFi Bluetooth Dual Mode Development Board Display for Wemos D1 AP STA”). Bought from Amazon : a.co/d/b8NK4sG
Also can I transfer the weight of the item to count considering I have n of items with same weight.
Can we have an example for that please.
We have a tutorial showing how to write to an OLED of a similar board: https://randomnerdtutorials.com/esp32-built-in-oled-ssd1306/
Just make sure to double-check the pinout of your specific board. Then, it is easy to adjust to use the proper pins.
Regards.
Sara
HI Sara, I ran it , but the result says
one reading : nan | average: nan
😭😭
Hi.
That’s probably an issue with the wiring.
Regards,
Sara
It seem the arduino-esp32 API changed some functions in the arduino-esp32 version 2.0.9 package.
#include “soc/rtc.h”
void setup(){
Serial.begin(115200);
rtc_cpu_freq_config_t config;
rtc_clk_cpu_freq_get_config(&config);
rtc_clk_cpu_freq_to_config(RTC_CPU_FREQ_80M, &config);
rtc_clk_cpu_freq_set_config_fast(&config);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}
and then it should work properly again.
Kind regards,
Salomé
Yes, it really works! Thanks for sharing! I had this problem and now finally my code can run.
However, as mentioned earlier, in ESP32 you don’t even need to reduce your speed anymore, as the newer versions of the library can handle ESP32 at full speed. Here I’m using it along with configured OTA, a 3.5″ TFT display and a bunch of other stuff and it’s running normally at 240MHz.