Smartphone Arduino Weighing Scale with Load Cell and HX711

iot_scale_main_blog.JPG

“As an Amazon Associates Program member, clicking on links may result in Maker Portal receiving a small commission that helps support future projects.”

A load cell is an application of strain measurements relating to weight measurement. A load is applied to a strain gauge, which causes the gauge to strain a certain amount and output a voltage proportional to the applied load. This relationship between strain and voltage is used in many applications where weight measurement is important. Load cells are very common because of their linearity, cost effectiveness, and their ease of implementation. In this tutorial, I will introduce an Arduino-compatible load cell that exemplifies all of the aforementioned advantages. I will also introduce calibration with known masses to create a powerful and accurate weighing system that can be used for highly accurate measurement purpose such as: chemistry, horticulture, cooking, and much more!


Load Cells and Arduino Library

A 24-bit analog-to-digital converter called the HX711 converts the small changes in strain from the load cell into 24-bit changes in voltage (Arduino 0-5V). This allows the Arduino to resolve weight (mass) changes down to the range of the load cell (typically 500g, 1kg, 5kg, or more) divided by half the bit depth (223). For a 1kg load cell, this results in mass change detection down to 0.0001g. In practice, however, the analog-to-digital converter and load cell both can have inherent noise (electrical and mechanical) which results in a much lower precision closer to 0.1% of the measurement value - which we will explore and quantify using measurements later in this tutorial.

For this tutorial, I will be using a lightweight HX711 load cell library by Queuetue named “<Q2HX711.h>”. The use of this library was found to be the easiest and most stable to implement in terms of performance. To download the library, go to the Library Manager in the Arduino IDE and type HX711. The ‘Queuetue HX711 Library’ will be used in this tutorial, and the program used is based off their example.

hx711_library.png

The HX711 simple example demonstrates the basic functionality for getting the scale working. Below is the sample code:

#include <Q2HX711.h>

const byte hx711_data_pin = 3;
const byte hx711_clock_pin = 4;

Q2HX711 hx711(hx711_data_pin, hx711_clock_pin);

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(hx711.read()/100.0);
  delay(500);
}
After uploading the code above and appropriately wiring the HX711 to the Arduino and also ensuring the HX711 is properly wired to the load cell, the code should output a value close to half of 224. This allows the load cell to measure both positive and negative load. Positive load being added mass, and negative load represents the load cell being strained in the opposite direction of gravity.

Parts List and Wiring

The HX711 can be powered anywhere from 2.7V - 5.5V. The full data sheet with specifications for the HX711 can be found here. I won’t be doing any alterations of the HX711 library, so the aforementioned statements are the extent to which I will discuss the HX711, apart from wiring.

The main parts used in this experiment are:

Arduino Uno - $13.00 [Our Shop]

  1. 1kg Load Cell + HX711 - $12.99 [Our Shop]

  2. Jumper Wires - $5.99 [Amazon]

  3. Calibrated Weights - $9.99 [Amazon]

Or purchase our load cell calibration kit directly from our store:

 
 

The HX711 is easily wired to the Arduino using any two digital or analog pins. The load cell must also be accurately wired to the HX711 to ensure that the appropriate strain gauge leads are used to approximate the weight given by the load cell. Next, we will explore calibration and test the load cell as a weighing scale.


Calibration Method and Testing

The load cell is quite sensitive and depending on the changing environment, calibration may be essential. I will outline a method using two calibration points: the zero (tare) value and a calibrated mass value. The calibrated mass method will ensure that each time the load cell is used, it will be calibrated with a known mass, ensuring the best approximation of mass of objects of unknown mass. I recommend calibration before each use, and whenever the environment changes or the load cell is moved.

Using the equation for a line we can begin to understand how calibration will take place and how we will specifically implement calibration with an Arduino board and load cell. The equation for a line is:

where x in this case is the reading from the HX711's ADC, y is the known mass, m is the slope of the calibation line, and b is the intercept where y = 0, which is also the 'tare' point, when no mass is added to the scale. If dummy points x0, y0 are used as one point on the line, and x1, y1 are used as the second point on the line:
we can define both m and b in terms of those known masses and ADC values:

which leads to our final definition of the calibration line using two known masses:

In our specific case, since one calibration point is with no added mass, we can say y0 = 0, which simplifies the expression above:
Since strain gauges linearly relate strain to force applied, we are able to use a linear relationship when calibrating the load cell. I also went through the process of plotting several different calibrated masses against the load cell HX711 readout in order to verify this linearity at multiple strains. This plot is shown below:
load_cell_hx711_calibration_plot.png

The linearity over multiple masses reassures us that the two-point calibration method suffices!

The simplest way to understand the calibration is to use the HX711 ADC reading with no added mass (tare). Then, once the zero value is calibrated, ask Arduino to again read the HX711 ADC value with a known calibration mass. This will create an up-to-date linear calibration slope and intercept, ensuring the most accurate weighing. The code below outlines this process.

#include <Q2HX711.h>

const byte hx711_data_pin = 3;
const byte hx711_clock_pin = 4;

float y1 = 20.0; // calibrated mass to be added
long x1 = 0L;
long x0 = 0L;
float avg_size = 10.0; // amount of averages for each mass measurement

Q2HX711 hx711(hx711_data_pin, hx711_clock_pin); // prep hx711

void setup() {
  Serial.begin(9600); // prepare serial port
  delay(1000); // allow load cell and hx711 to settle
  // tare procedure
  for (int ii=0;ii<int(avg_size);ii++){
    delay(10);
    x0+=hx711.read();
  }
  x0/=long(avg_size);
  Serial.println("Add Calibrated Mass");
  // calibration procedure (mass should be added equal to y1)
  int ii = 1;
  while(true){
    if (hx711.read()<x0+10000){
    } else {
      ii++;
      delay(2000);
      for (int jj=0;jj<int(avg_size);jj++){
        x1+=hx711.read();
      }
      x1/=long(avg_size);
      break;
    }
  }
  Serial.println("Calibration Complete");
}

void loop() {
  // averaging reading
  long reading = 0;
  for (int jj=0;jj<int(avg_size);jj++){
    reading+=hx711.read();
  }
  reading/=long(avg_size);
  // calculating mass based on calibration and linear fit
  float ratio_1 = (float) (reading-x0);
  float ratio_2 = (float) (x1-x0);
  float ratio = ratio_1/ratio_2;
  float mass = y1*ratio;
  Serial.print("Raw: ");
  Serial.print(reading);
  Serial.print(", ");
  Serial.println(mass);
}

A demo of the weighing scale program is also shown below:

Process for Using the Weighing Program Above:

    1. Restart program with nothing on the load cell platform
    2. Open serial port
    3. Wait for tare to finish and Arduino to print out: "Add Calibrated Mass"
    4. Add calibrated mass equal to the variable "y1" value above (20g in my case)
    5. Wait for print out: "Calibration Complete"
    6. Real-time mass should be printing out!

IoT with BLExAR App

Thus far, this tutorial has discussed the load cell basics, calibration with known masses, and the Arduino library. Now, I introduce the use of the BLExAR app and the IoT Scale code to the Arduino board. Below is the wiring change required for the CC2541 Bluetooth integration:

BLExAR App for IoT Integration

BLExAR App for IoT Integration

hx711_load_cell_wiring_cc2541.png

Below is the IoT scale code that is needed for integration with the BLExAR app:

#include <Q2HX711.h>
#include <SoftwareSerial.h>

SoftwareSerial ble_device(8,9); // CC2541 TX/RX pins

const byte hx711_data_pin = 3;
const byte hx711_clock_pin = 4;

float y1 = -1.0; // calibrated mass to be added
long x1 = 0L;
long x0 = 0L;
float avg_size = 15.0; // amount of averages for each mass measurement
char ble_reading = 'Z'; // Bluetooth char preallocation
float ratio_2 = 0.0; // for linear fit

Q2HX711 hx711(hx711_data_pin, hx711_clock_pin); // prep hx711

void setup() {
  ble_device.begin(9600); // prepare BLE module
  delay(1000); // allow load cell and hx711 to settle
  // tare procedure
  for (int ii=0;ii<int(avg_size);ii++){
    delay(10);
    x0+=hx711.read();
  }
  x0/=long(avg_size);
}

void loop() {
if (x1==-1L or y1==-1.0){
    String char_str;
    ble_device.write("Send Cal");
    while(true){
      ble_reading = ble_device.read();
      if (ble_reading==-1){
      } else {
        if (ble_reading=='\n' or ble_reading=='\r'){
          break;
        } else{
          char_str+=ble_reading;
        }
      }
    }   
    for (int jj=0;jj<int(avg_size);jj++){
      x1+=hx711.read();
    }
    x1/=long(avg_size);
    y1 = char_str.toFloat();
  } else {
    long reading = 0L;
    for (int jj=0;jj<int(avg_size);jj++){
      reading+=hx711.read();
    }
    reading/=long(avg_size);
    float ratio_1 =(float) (reading-x0);
    float ratio_2 =(float) (x1-x0);
    float ratio = ratio_1/ratio_2;
    float weight = y1*ratio;
    char ble_str[6];
    dtostrf(weight,2,4,ble_str);
    ble_device.write(ble_str);
  }
}

The IoT application of this code is shown below in a video:


Conclusion

This tutorial introduced load cells and strain gauges to approximate mass using the linearity of strain gauges and taking advantage of earth’s gravitation. Using known calibrated masses, we were able to create a routing that calibrates the load cell and approximate mass. This weighing scale routine was implemented in real-time to create a highly accurate weighing scale that is both portable and inexpensive - all using Arduino and Arduino-compatible components. The load cell weighing scale can be used to measure strain in real-time and allow engineers to record and ultimately study changes in mass and weight.

I also introduced the IoT portion of this to be compatible with the BLExAR app, which can be downloaded on the Apple App store (link here).

BLExAR Application on the App Store

BLExAR Application on the App Store

Citation for This Page:
 

See More in Arduino: