HX711 24 bit ADC with four load cells

Hi guys,

I found the HX711 and was curious if it could work for one of my projects which currently uses other ADC.. This 24 BIT ADC has 2 differential inputs for 2 load cells. In the end I need 4 load cells so that means the use of 2 x HX711. All the code I found is only refering to measuring one load cell on the A- and A+ input instead of two. The output for communication is fed to the A0 and A1 analog inputs.

Now would it be possible to have two of the HX711 connected to an UNO and read all the load cells to a serial print function. The data needs to be ported to a PC by USB. So the second HX711 connected to A2 and A3.

Would the hx711.h libary need to be adapted or can I change the libaries name for example hx711-1 and hx711-2 and both use in the same sketch ?

Any tips or trick if this could work would be appriciated.

/* sample for digital weight scale of hx711, display with a HD44780 liquid crtstal monitor
 *
 * hardware design: syyyd
 * available at http://syyyd.taobao.com
 *
 * library design: Weihong Guan (@aguegu)
 * http://aguegu.net
 *
 * library host on
 * https://github.com/aguegu/Arduino
 */

// Hx711.DOUT - pin #A1
// Hx711.SCK - pin #A0

#include "hx711.h"

Hx711 scale(A1, A0);

void setup() {

  Serial.begin(9600);

}

void loop() {

  Serial.print(scale.getGram(), 1);
  Serial.println(" g");

  delay(200);
}

Building a scale with loadcell i each corner? Then parallell loadcells diagonally. (This was what I found in my 'dead' bathroom scale, where I 'harvested' the loadcells)

Need to measure independ at each corner a value. Wheel pressure on each wheel......... :)

Paco

That chip is digital out.
Each chip will need it own control_line (PD/CLK) to be able talk to one chip at a time

Ny,

That would mean 8 analog inputs need to be used?

Paco

No. The chip 'talks' digitally. You read a number directly from the chip. Study its datasheet, U'll find out.

NY,

I studied the datasheet. Table 3 and figure 2 are conflicting where table 3 is correct and figure 2 contains channel B at 64 gain which should be channel A 64 gain. Understand now that pulses 25,26,27 determen which data is send out from the HX711 and which gain should be used. But my knowledge at this moment fails to see how I can read the data to the MCU othe rthen the sample codes. I have no clue if the current available .h and .cpp files are designed to get also the B channel data. In all samples only one value is displayed Serial.print(scale.getGram(), 1); Serial.println(" g"); or do I understand wrong?

Paco

..thats what the library is for..: Helping you do the 'tricky' job. The readme hold this info (I belive the example program must be used in this process)

How to Calibrate Your Scale

  1. Call set_scale() with no parameter.
  2. Call set_tare() with no parameter.
  3. Place a known weight on the scale and call get_units(10).
  4. Divide the result in step 3 to your known weight. You should get about the parameter you need to pass to set_scale.
  5. Adjust the parameter in step 4 until you get an accurate reading.

source: https://github.com/bogde/HX711

It this http://www.dfrobot.com/wiki/index.php/Weight_Sensor_Module_V1 the same lib ?

Yep I found that Lib this afternoon too.

Still do not fully understand it all but I ordered two of these babies and when they are in I first gonna check with this lib if I can get it to work on A channel and then see if the B channel can be trapped too into a println function to get the data over to the PC. It looks like all only use the A channel to be captured or am I missing something then? Then comes the trick to read four channels. One channel at the time..........for now.

All the hardwork will be done like tarre and zeroing in the PC. I only need the raw data (milivolts). Maybe at a later stage I will see if I can adapt with Blue Tooth and an Android app to get the data the same way as on the PC by USB.

First I have to understand what goes on.

Paco

I have not looked at the library, but it sounds to me like it needs modifying to allow you the option of which IO lines you want to use for each HX711 object. That way you only need one set of library files and when it gets initialized, for example, for the first hx711 you assign it A0 & A1, then for the second kx711 object you assign it A2 & A3 (similar to the OneWire library or most other libraries that can use any IO). You may also need to add the ability to request data from channel B. Take note that chB has a fixed gain of 32 and chA can be either 128(default) or 64. Your weight calculations will have to be adjusted for that.

Hello Matt,

I also found out that the two channels can not have the same gain setting. :0 Currently busy with something else but as soon as that is ready this HX711 will be the next step. I let you know how far I can get.

Paco

I tried the lib mentioned earlier : github.com/bogde/HX711 . It works on both channels A & B by setting the gain parameter to 128 or 32. Have not connected 2 scales to A & B simultaneously yet, but I expect that will work. In the example the gain 64 (Channel A) has a bug, which is not relevant if you use gain 128. For my application the fact that amplifier gain for A and B is different is not an issue; difference can be corrected in the software gain.

Hi!!!

I am working in a very similar project, until now I actually read properly channel A from two HX711 modules, there are still problems reading channel B mainly because the only way that I found to change chanel is with set_gain command, second, the gain can not be set equal for all channels

This is my code (Modified version from the great library at https://github.com/bogde/HX711.

include "HX711.h"

// HX711.DOUT - pin #A1 // HX711.PD_SCK - pin #A0

HX711 scale(A1, A0); // parameter "gain" is ommited; the default value 128 is used by the library HX711 scale1(A3, A2); // parameter "gain" is ommited; the default value 128 is used by the library

void setup() { float cal1=0; float cal2=0;

Serial.begin(38400); //Serial.println("HX711 x 2 ");

scale.set_gain(128); scale1.set_gain(128);

Serial.println("Before setting up the scale:"); Serial.print("read scale 0: \t\t"); Serial.println(scale.read()); // print a raw reading from the ADC Serial.print("read scale 1: \t\t"); Serial.println(scale1.read()); // print a raw reading from the ADC

Serial.print("read average scale 0: \t\t"); Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC

Serial.print("read average scale 1: \t\t"); Serial.println(scale1.read_average(20)); // print the average of 20 readings from the ADC

Serial.print("get value scale 0: \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 value scale 1: \t\t"); Serial.println(scale1.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight (not set yet)

Serial.print("get units scale 0: \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) Serial.print("get units scale 1: \t\t"); Serial.println(scale1.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)

/* Serial.println("Calibrating HX711 1"); scale.set_scale(); scale.tare(); Serial.println("Put 1000g over LC #1"); delay(5000); cal1=scale.get_units(10); scale.set_scale(cal1/1000); Serial.print("Calibration value : "); Serial.println (cal1/1000);

Serial.println("Calibrating HX711 2"); delay(2000);

scale1.set_scale(); scale1.tare(); Serial.println("Put 1000g over LC #2"); delay(5000); cal2=scale1.get_units(10); scale1.set_scale(cal2/1000);

Serial.print("Calibration value: "); Serial.println (cal2/1000); */

scale.set_gain(128); scale.read(); scale.set_scale(107.f); scale.tare();

scale1.set_gain(128); scale1.read(); scale1.set_scale(107.f); scale1.tare();

/* scale.set_gain(32); scale.read(); scale.set_scale(107.f); scale.tare();

scale1.set_gain(32); scale1.read(); scale1.set_scale(107.f); scale1.tare();

scale.set_gain(128); scale1.set_gain(128); scale.read(); scale1.read();

*/

Serial.println("After setting up the scale:");

Serial.print("read scale 0: \t\t"); Serial.print(scale.read()); // print a raw reading from the ADC

Serial.print("\t read scale 1: \t\t"); Serial.println(scale1.read());

Serial.print("read average scale 0: \t\t"); Serial.print(scale.read_average(20)); // print the average of 20 readings from the ADC

Serial.print("\t read average scale 1: \t\t"); Serial.println(scale1.read_average(20)); // print the average of 20 readings from the ADC

Serial.print("get value scale 0: \t\t"); Serial.print(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight, set with tare()

Serial.print("\t get value scale 1: \t\t"); Serial.println(scale1.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight, set with tare()

Serial.print("get units scale 0: \t\t"); Serial.print(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.print("\t get units scale 1: \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 scale 0:\t"); // Serial.print(scale.get_units(), 1);

scale.set_gain(128); scale1.set_gain(128); delay(100); float A = scale.get_units(10); float B = scale1.get_units(10);

/* scale.set_gain(32); scale1.set_gain(32); delay(100); float C = scale.get_units(10); float D = scale1.get_units(10); */

Serial.print("\t A:\t"); Serial.print(A, 1); Serial.print("\t B:\t"); Serial.print(B, 1);

/* Serial.print("\t C:\t"); Serial.print(C, 1); Serial.print("\t D:\t"); Serial.print(D, 1); */

Serial.print("\t Weight: \t"); Serial.println((A+B), 1);

Serial.print("\t Pos:\t"); if ((A+B)>500) { Serial.println((A*10-B*10)/(A+B), 1); } else { Serial.println(0, 1); }

//scale.power_down(); // put the ADC in sleep mode //scale1.power_down(); //delay(500); //scale.power_up(); //scale1.power_up(); }

Did you be able to read properlly channel B???

Sofar I am still not in a need to read channel B too. Reading four loadcells with the HX711 is for my next project. But Always keen to know the results.

Paco

scale1.set_scale(107.f);

How do you obtain the scale value? I’m getting confused with calibration of HX711…Please help me, thanks!

Use the HX711 lib on Github made by Bogde.
Only use one loadcell and get it working.
Then add second load cell.

simple code with calibration inside the sketch not the .h file from the lib.

// Arduino with load cell
#include <HX711.h>

// HX711.DOUT	- pin #A1
// HX711.PD_SCK	- pin #A0

HX711 scale(A1, A0); // 24 bit load cell amplifier

long ForceValue = 0;

// Put two known loads on the sensor and take readings. Put those values
// here.
float aReading = 192.0; // put the value of the lowest rate here. 192 is a sample value
float aLoad = 500; // your lowest load value for example 500 grams or use no laod and take that value as lowest.
float bReading = 344.0; put the value of the highest rate here. 344 is a sample value.
float bLoad = 1000; // your highest load value for example 1000 grams

long time = 0;
int interval = 500; // Take a reading every 500 ms

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

void loop() {
  
  ForceValue = scale.read(); // 
  float newReading = ForceValue;
  
  // Calculate load based on A and B readings above
  float load = ((bLoad - aLoad)/(bReading - aReading)) * (newReading - aReading) + aLoad;
  
  // millis returns the number of milliseconds since the board started the current program
  if(millis() > time + interval) {
    Serial.print("Reading: ");
    Serial.print(newReading,1); // 1 decimal place
    Serial.print("  Load: ");
    Serial.println(load,1);  // 1 decimal place, println adds a carriage return
    time = millis();
  }
}

backbone:
Use the HX711 lib on Github.
Only use one loadcell and get it working.
Then add second load cell.

simple code with calibration inside the sketch not the lib.

// Arduino with load cell

#include <HX711.h>

// HX711.DOUT - pin #A1
// HX711.PD_SCK - pin #A0

HX711 scale(A1, A0); // 24 bit load cell amplifier

long ForceValue = 0;

// Put two known loads on the sensor and take readings. Put those values
// here.
float aReading = 192.0; // put the value of the lowest rate here. 192 is a sample value
float aLoad = 500; // your lowest load value for example 500 grams or use no laod and take that value as lowest.
float bReading = 344.0; put the value of the highest rate here. 344 is a sample value.
float bLoad = 1000; // your highest load value for example 1000 grams

long time = 0;
int interval = 500; // Take a reading every 500 ms

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

void loop() {
 
  ForceValue = scale.read(); //
  float newReading = ForceValue;
 
  // Calculate load based on A and B readings above
  float load = ((bLoad - aLoad)/(bReading - aReading)) * (newReading - aReading) + aLoad;
 
  // millis returns the number of milliseconds since the board started the current program
  if(millis() > time + interval) {
    Serial.print("Reading: “);
    Serial.print(newReading,1); // 1 decimal place
    Serial.print(”  Load: ");
    Serial.println(load,1);  // 1 decimal place, println adds a carriage return
    time = millis();
  }
}

thanks! I will try this :slight_smile:

This may not be the correct place to ask, but is it necessary to connect the hx11 to analog pins? It seems like they are digital, so could I connect them to digital pins instead? I also have a project I am working on where I will need to read 4 load cells, and I was going to just use 4 hx711 chips.

..you arswered that yourself.. All arduinos pins can be used

knut_ny: ..you arswered that yourself.. All arduinos pins can be used

Thank you, I was just confused because every code example I could find had them on analog pins. I should have one soon, and I'll try it on various pins.