How to Use a Load Cell and HX711 Amplifier with Arduino.
What is a load cell?
A load cell is a transducer or sensor that converts a force into a quantifiable output such as an electrical signal. The strength of the output is proportional to the force (compression, tension, pressure, etc.) applied to the load cell. The commonest application of load cells is in weighing scales.
There are several types of load cells including strain gauge load cells, hydraulics load cells, pneumatic load cells, capacitive load cells and piezoelectric load cells. Strain gauge load cells are the most common and in this tutorial am using a bar-type strain gauge load cell.
How does a Strain Gauge Load cell work?
A Strain Gauge Load Cell uses the principal of a Wheatstone bridge to measure the change in resistance when a force is applied and output a corresponding voltage. In a load cell’s Wheatstone bridge, one or more of the resistors are strain gauges.
A strain gauge is an electrical component whose resistance changes when it undergoes mechanical strain from an applied force. This change in resistance can be converted to a signal that is proportional to the force causing the strain.
It consists of a thin metal conductor foil attached to a flexible backing material, known as the carrier. Electrical leads are soldered to the foil, allowing current to flow through the strain gauge. As the surface under test stretches or contracts, the strain gauge deforms accordingly, leading to variations in electrical resistance that corresponds to changes in the surface dimensions.
In this tutorial I am using a four wire bar-type strain gauge load cell which is made up of four strain gauges in a full Wheatstone bridge configuration
A Wheatstone bridge is simply two voltage dividers wired in parallel arms of a circuit with a common voltage source.
A bridge circuit is said to be “balanced” when the current flowing in the R1 / R2 branch is equal to the current flowing in the R3 / R4 branch because all resistors are equal in their resistance values and there is no voltage difference between points C and D.
Therefore there is no output voltage, Vout = 0
Whenever the resistance of any of the resistors in the Wheatstone bridge changes, there will be a potential difference between points C and D and the output voltage will be given as:
When setting up the Bar-Type Strain Gauge Load Cell, you should leave enough room for the load cell to bend when subjected to the force that you are trying to measure. One end of the load cell is fixed and the other end is left suspended with a platform to place the weight to measure.
When a force is applied to a load cell, some of the strain gauges will undergo compression and others tension which will create a change in resistance hence generating a voltage.
HX711 Load Cell Amplifier
The voltage signal generated by a load cell is very small and cannot be directly detected by a microcontroller like Arduino. The HX711 Load Cell Amplifier is 24 bit analog-to-digital converter chip that is used to convert signal from the load cell into a digital signal that a microcontroller like Arduino can process.
Specifications of HX711 load Cell Amplifier
- Data Accuracy: 24 bit analog-to-digital converter chip
- Operation supply voltage range: 4.8 ~ 5.5V
- Operation supply Current: 1.6mA
- Refresh Frequency: 10/80 Hz
- On-chip power supply regulator for load-cell and ADC analog power supply
- Two selectable differential input channels
Connecting the load cell to Arduino.
The load cell is connected to Arduino via the HX711 amplifier as shown below. The four wires of most bar-type load cells are colored Red, Black, White and Green and are connected to the HX711 amplifier as follows:
- Red to E+ (Excitation+)
- Black to E– (Excitation-)
- White to A+ (Amplifier+, Output+ (O+) or Signal+ (S+))
- Green to A– (Amplifier-, Output- (O-) or Signal- (S-))
The HX711 uses a two wire interface (Clock and Data) for communication with Arduino and any of the GPIO pins should work but I have connected the Clock to Pin 5 and Data to Pin 4 because these are the pins specified in the Arduino library am going to use to read data from the HX711.
Calibrating the Load Cell
Before using the load cell as a weighing scale, we need to first calibrate the load cell using a known weight to get a calibration constant that will act as our reference for future measurements. There are a number of libraries that can be used to interface a load cell with Arduino but am going to use the HX711_ADC.h library.
After installing the library, you can look for the Calibration example in the Arduino IDE by going to File>Examples>HX711_ADC>Calibration
This will open the calibration code sketch.
Upload the code to your Arduino board and open the Serial monitor and set it to 57600.
This calibration code is going to prompt you to tare the load cell, then add a known weight to the load cell and tell Arduino what that weight is via the Serial Monitor. A calibration factor will be calculated and then you will be told to save that value and asked whether to store that factor value to Arduino’s EEPROM. The whole process will look like shown below;
Weighing scale using a Strain Gauge Load cell, HX711 Amplifier and Arduino.
After calibrating the load cell, we can now use it to make a weighing scale. The schematic for the weighing scale is as shown below. I have included an I2C OLED where the weight of the object being measured will be displayed.
Code for the Weighing scale using Load cell and HX711 Amplifier with Ardunio.
This code is almost the same as the example sketch for calibration but I have added the libraries for controlling the I2C OLED and the corresponding code for displaying the measured weight on the display.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HX711_ADC.h>
#if defined(ESP8266)|| defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//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...");
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)// Check your I2C address and enter it here, in Our case address is 0x3C
display.clearDisplay();
display.display();
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 = 5000; // 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);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Weight");
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(25,18);
display.print(String(int(i)) + "g");
display.display();
newDataReady = 0;
t = millis();
}
}
}
In case you need further guidance on the working of I2C OLED, you can refer to my other tutorial on How to use I2C OLED with Arduino.
After uploading this code to your Arduino board, when an object is placed on the weighing platform, the weight of that object will be displayed on the OLED.