Connecting multiple load cells together that can read individual weights.

I am developing a project that requires eight load cells each capable of measuring an individual weight simultaneously (in practice). Currently, I have multiple load cells each connected to a HX711 amplifier (https://www.sparkfun.com/products/13879) which connects directly into an Arduino Mega.

I have three related questions all on the same project. Can I use the Qwiic MUX Breakout (TCA9548A) (https://www.sparkfun.com/products/14685) board to connect multiple, but individual load cells, thus reducing the number of digital pins being currently used? It is my understanding that the MUX breakout board is for connecting multiple load cells that communicate as one system. But I want to hang different weights to each load cell and be able to display the weights.

Another related query I have is regarding the Qwiic scale (NAU7802) (https://www.sparkfun.com/products/15242) which has been used on projects connecting load cells to the MUX breakout board. Is this better than the HX711 amplifier board or one in the same thing?

And lastly, if neither of the above is an option in my project can I use a load sensor combinator board (https://www.sparkfun.com/products/13878) to connect the multiple load cells, or will I have the same problem of only being able to read them all as one (similar to the four used in a bathroom scale).

Any other advice for connecting multiple but individually reading load cells would be greatly appreciated.

Thanks in advance. I hope I have provided enough information.

The MUX is for multiplexing I2C connections - unfortunately, it looks like the HX711 isn’t talking I2C, but a different 2-wire serial protocol. The Qwiic scale board provides I2C - it looks like the library only allows for a single address at 0x2A. The MUX board should allow you to connect all of them at the same time - so, you’d need 8 Qwiic scale boards, and a MUX board.

I was going to add that you might be able to add in support to the Qwiic Scale library to handle changing addresses on the device, eliminating the need for the MUX, but a quick glance at the NAU7802 datasheet suggests that there’s not really NVRAM onboard to store the setting, so each Scale would come up at 0x2A every time it’s reset. Not super workable. I might’ve missed something in there, though.

You could use a couple of 74HC4051 (one for clock and one for data) and that gets you talking to 8 HX711 amplifiers at the expense of 4 lines (5 if you want to control en/dis). If you don’t want to set the HX711s to sleep (low power) you could probably only multiplex the data line and common-connect the clock lines. There are plenty of other ICs that can help you there as well. I only mention the HC4051 because SFE has a cool breakout board for them.

https://www.sparkfun.com/products/13906

And this other one would give you 16 independent HX711 at the expense of 5 lines (6 if you want to control en/dis).

https://www.sparkfun.com/products/9056

davere:
The MUX is for multiplexing I2C connections - unfortunately, it looks like the HX711 isn’t talking I2C, but a different 2-wire serial protocol. The Qwiic scale board provides I2C - it looks like the library only allows for a single address at 0x2A. The MUX board should allow you to connect all of them at the same time - so, you’d need 8 Qwiic scale boards, and a MUX board.

I was going to add that you might be able to add in support to the Qwiic Scale library to handle changing addresses on the device, eliminating the need for the MUX, but a quick glance at the NAU7802 datasheet suggests that there’s not really NVRAM onboard to store the setting, so each Scale would come up at 0x2A every time it’s reset. Not super workable. I might’ve missed something in there, though.

Davere,

Thank you for your reply. The single address on the HX711 is the problem I am currently having. I don’t know how to read each one on the same LCD if they have the same address. Thanks for looking into the datasheet. I’m brand new to electronics and programming and really get lost in this. I think I was attempting to find something like the MUX to reduce the number of I/O being used on the Arduino, but actually, I think by using this I think it might be easier to address each loadcell separately and it’s probably my lack of programming experience to account for why I’m not able to display each loadcell value on the same LCD.

I think at my stage of understanding I’m mainly looking for a yes, or no the concept will/won’t work with said components…

languer:
You could use a couple of 74HC4051 (one for clock and one for data) and that gets you talking to 8 HX711 amplifiers at the expense of 4 lines (5 if you want to control en/dis). If you don’t want to set the HX711s to sleep (low power) you could probably only multiplex the data line and common-connect the clock lines. There are plenty of other ICs that can help you there as well. I only mention the HC4051 because SFE has a cool breakout board for them.

https://www.sparkfun.com/products/13906

And this other one would give you 16 independent HX711 at the expense of 5 lines (6 if you want to control en/dis).

https://www.sparkfun.com/products/9056

Languer,

Thank you for your reply. The 74HC4051 Multiplexer looks interesting. I think this is similar to the combination board but with more control? I would like the load cells to be continuously monitored so I’m not sure if I could run on a low power mode. You have given me something to look more into, so thank you. I appreciate the reply.

I don’t suppose you have an idea if the type of load cell makes a difference with what I use here? Currently, I am using the 10kg straight bar cells (https://www.sparkfun.com/products/13329), but the intention is to use the 200kg s-type cells (https://www.sparkfun.com/products/14282) I don’t want to spend all this time finding components to connect multiple load cells that won’t work with the larger capacity cells.

Thanks in advance.

bnawoc:
Davere,

Thank you for your reply. The single address on the HX711 is the problem I am currently having. I don’t know how to read each one on the same LCD if they have the same address. Thanks for looking into the datasheet. I’m brand new to electronics and programming and really get lost in this. I think I was attempting to find something like the MUX to reduce the number of I/O being used on the Arduino, but actually, I think by using this I think it might be easier to address each loadcell separately and it’s probably my lack of programming experience to account for why I’m not able to display each loadcell value on the same LCD.

I think at my stage of understanding I’m mainly looking for a yes, or no the concept will/won’t work with said components…

Well, I just wrote out a long reply, and lost it . I’m pretty new to the Arduino related stuff, myself - I do have some background in firmware and device driver programming, so that helped me get started, but I’m learning a lot, too!

Actually, any of the three options you have at hand will work. Unless I’m looking at the wrong board, the Mega has 54 digital pins available, and you only need two per HX711 (the other pins are power and ground, and those can tie together for all boards and go back to dedicated power/ground ports on the Mega). So, you need 16 digital pins, total - you’ve got 4x that. Programmatically, this isn’t too bad, either - you’d instantiate 8 HX711 objects (with the correct pins assigned to each), and read each one as required. Output to the display is a matter of formatting the output for the display you’re using and feeding it the code to show the output (namely, just design choices, there) - and that’s going to be the same regardless of which input option you pick.

The Qwiic based system (MUX board and 8 Qwiic Scale) boards is the expensive option. The programming is a bit easier, because SparkFun has developed some nice libraries for you already, and you have ready made examples! Wiring it all up is relatively easy, too, because of how the Qwiic system is set up - you just plug them in using Qwiic cables.

The 74HC4051 multiplexor that Languer mentions is definitely viable, too. You’d actually need two of them - one for your clock line, and one for your data line. You’d need 8-10 pins total (down from 16) - 3 each to tell the multiplexor which which channel to talk to, 1 each to act as the common pin (so, clock or data), and optionally 1 each to tell the multiplexor to disconnect from all channels (may not be needed). Programming this option is harder, but the 16-channel mux has a nice example included under the documents section - it’s hard to read, because the poster left out a code tag. I pulled it down and reformatted it, but the forum has a problem with the code, so I can’t post it here (I get a 403 Forbidden error when I try to post it - I can email it to you if you PM your email?). It would be pretty easy to adapt the code to talk to the 8-channel mux (basically, you change it from 4 control pins down to 3). This option costs, like, $5.

Honestly, given that you’re using a Mega - if you already own the HX711s, I’d just wire them up directly, unless you need actually need all of those pins for your project? You’ve got a resource rich board there - might as well use it!

bnawoc:
… I don’t suppose you have an idea if the type of load cell makes a difference with what I use here? Currently, I am using the 10kg straight bar cells (https://www.sparkfun.com/products/13329), but the intention is to use the 200kg s-type cells (https://www.sparkfun.com/products/14282) …

Thanks in advance.

The HX711 board should work with any of those type of load cells. You need to calibrate them just the same. Multiple load cells just mean multiple HX711 boards (one HX711 board per load cell). Some example snippet of code as to how to address them:
#define RESOLUTION 2      //decimal places of HX711 reading
#define AVG_FACT 16        //averaging factor of HX711 reading

#define HX711_CLK_1 6     //clock IO of HX711 (scale #1)
#define HX711_DOUT_1 5    //data IO of HX711 (scale #1)
HX711 scale1;

#define HX711_CLK_2 8     //clock IO of HX711 (scale #2)
#define HX711_DOUT_2 9    //data IO of HX711 (scale #2)
HX711 scale2;

...

scale1.begin(HX711_DOUT_1, HX711_CLK_1);
scale2.begin(HX711_DOUT_2, HX711_CLK_2);

...

Serial.print(scale1.get_units(AVG_FACT), RESOLUTION);  //set resolution of displayed float val
Serial.print(scale2.get_units(AVG_FACT), RESOLUTION);  //set resolution of displayed float val

If you have the spare IO, you certainly do not need the multiplexer.

Not sure if it was obvious from the previous post, but the HX711 does not have any type of address. When coding for them you just need different instantiations for each different one (e.g. “HX711 scale1”, “HX711 scale2”, … “HX711 scale8”.

If you were using the Qwiic board then those do have an address and it cannot be changed so you need to have the Qwiic multiplexer board, but between the HX711 and the Qwiic options, the later one would be more expensive and I don’t really know why you would want to go that route (unless you already had started with that option).

If you have a MEGA then you probably have IO available without needing the multiplexer. But if you were running short on IO and you do not want to run the HX711 in low power (which it seems is not a requirement for your) then you should be able to drive all the HX711 clock lines from one single pin on the MEGA (I am not dead certain on this, but I see no reason for that not to work; worst case ,I think, you could need to split the clock drive in two pins).

davere:
Well, I just wrote out a long reply, and lost it . I’m pretty new to the Arduino related stuff, myself - I do have some background in firmware and device driver programming, so that helped me get started, but I’m learning a lot, too! … You’ve got a resource rich board there - might as well use it!

Thanks, Davere I really appreciate your offer to assist me further with this. I think based on what you’ve said and the reply from Languer that I will stick with the HX711 route. Mainly because I have them already, and because since this reply I’ve been able to hook up extra load cells without any issue. I think what you say about the number of I/O available is important to remember. I have it in my head that I need to preserve as much as I can, which is a complete waste. You’re right, I have plenty for what I need, and now that I have connected an extra loadcell I can see that it is easier this way, and relatively cheap.

The problem I was having was in my code. Well, that and my understanding of the I2C address on the HX711s etc. I convinced myself that because they share the same address that I couldn’t individually read them, but having read all these messages, I can obviously see that is possible and in fact, I did exactly that by simply using different instantiations as Languer kindly pointed out in his latest reply. I was using a piece of code to find the HX711 address and identify boards, and it kept showing me one. It was only when I got frustrated, ignored that step and just tried to program it that I realised its fine.

Anyway, thank you for your help.

languer:
If you have the spare IO, you certainly do not need the multiplexer.

Not sure if it was obvious from the previous post, but the HX711 does not have any type of address. When coding for them you just need different instantiations for each different one (e.g. “HX711 scale1”, “HX711 scale2”, … “HX711 scale8”…that not to work; worst case ,I think, you could need to split the clock drive in two pins).

Thank you very much, Languer, that one line you wrote about just declaring each HX711 solved a lot of my issues. Like i mentioned in my reply to Davere. I thought there was more to this. Fortunately, I’ve figured that out now. I’ve found this very helpful though and it lets me know the path I’m on is a viable one. Thank you for confirming about the larger capacity load cells. That is the next step and its great that calibration is the same. I have a very easy to use calibration program for these.

It’s interesting to see your code, it is very similar to mine except I’m not using #define. I tried a could of times but couldn’t get it to work. My code works fine, but i feel like it’s over-complicated or something. I’m using “const int” and “float” instead of #define, which i don’t think is great. I know floating type math is much slower in loops for instance. I tried to add my code properly but kept getting the 403 error like Davere. I can’t find any way of doing it so I will attempt to write it out in plain text, but I’ve had to remove lots hashtags and parenthesis etc. Apologies if this is not ideal to read. This is the start of my code (I’ve also tried to attach it with no prevail), but its the const int and float section that I think is not ideal:

include HX711.h

include Wire.h

include LiquidCrystal_I2C.h

const int LOADCELL_DOUT_PIN_1 = 4; //first load cell

const int LOADCELL_SCK_PIN_1 = 5;

const int LOADCELL_DOUT_PIN_2 = 8; //second load cell

const int LOADCELL_SCK_PIN_2 = 9;

float load_cell_value_1;

float load_cell_value_2;

float cylinder_weight_1 = 0.600; //test weight

float cylinder_weight_2 = 0.600; //possibly use same test weight value as above.

HX711 LoadCell_1; //(LOADCELL_DOUT_PIN_1, LOADCELL_SCK_PIN_1);

HX711 LoadCell_2; //(LOADCELL_DOUT_PIN_2, LOADCELL_SCK_PIN_2);

float calibration_factor_1 = 225.8; // LC1 updated calibration on 06/05 with 600g

float calibration_factor_2 = 217.8; // LC2 calibration on 06/05 with 600g

void setup

Serial.begin(9600);

LoadCell_1.begin(LOADCELL_DOUT_PIN_1, LOADCELL_SCK_PIN_1);

LoadCell_2.begin(LOADCELL_DOUT_PIN_2, LOADCELL_SCK_PIN_2);

Whenever I try any other way I get errors. This is the only success I’ve had with the code using the const int and float so I’ve stuck with it.

Thanks for your suggestions about driving all the clock lines with one pin. I’m going to look into that because I’m not sure how that works. Is it as simple as literally combining all incoming clock lines to a single pin via a breadboard or similar? I’m using a breadboard atm so that would be quite easy.

Thank you for your help.

Using constants instead of #defines is fine. One advantage of constants is that the compiler does check the validity of the type at compile time. If trying to use #define again remember you can’t use “=” and can’t use “;”.

As for combining the clock lines, yes you just use the same MEGA output to drive several HX711. I would start with two and build up until either you reach a limit or you have all of them wired. Using you example, your code would look like this:

const int LOADCELL_SCK_PIN_1 = 5;
const int LOADCELL_SCK_PIN_2 = 5;

or

HX711 LoadCell_1; //(LOADCELL_DOUT_PIN_1, LOADCELL_SCK_PIN_1);
HX711 LoadCell_2; //(LOADCELL_DOUT_PIN_2, LOADCELL_SCK_PIN_1);

As far as defines for constants go, it’s really more preference than anything else. Modern compilers (including avr-gcc) are smart enough to know that a variable declared “const” isn’t going to change, so they keep them in program space, not in RAM. defines and const variables take up literally the same amount of space in the same memory area. defines can also lead to weird compile time issues, if you have a typo - but you just have to remember that a text substitution has been done on the code when you start looking at compiler errors.

There’s a lot more to preprocessor statements than just making constants, of course. I believe my use of them harkens back to a time when compilers were relatively blunt instruments, and const variables weren’t handled like constants in some compilers, and it’s just habit now. Still… a bunch of all caps defines is my happy place, so… LOL…

languer:
Using constants instead of #defines is fine. One advantage of constants is that the compiler does check the validity of the type at compile time. If trying to use #define again remember you can’t use “=” and can’t use “;”.

As for combining the clock lines, yes you just use the same MEGA output to drive several HX711. I would start with two and build up until either you reach a limit or you have all of them wired. Using you example, your code would look like this:

const int LOADCELL_SCK_PIN_1 = 5;

const int LOADCELL_SCK_PIN_2 = 5;


or


HX711 LoadCell_1; //(LOADCELL_DOUT_PIN_1, LOADCELL_SCK_PIN_1);
HX711 LoadCell_2; //(LOADCELL_DOUT_PIN_2, LOADCELL_SCK_PIN_1);

Thank you, Languer. This is very helpful.

davere:
As far as defines for constants go, it’s really more preference than anything else. Modern compilers (including avr-gcc) are smart enough to know that a variable declared “const” isn’t going to change, so they keep them in program space, not in RAM. defines and const variables take up literally the same amount of space in the same memory area. defines can also lead to weird compile time issues, if you have a typo - but you just have to remember that a text substitution has been done on the code when you start looking at compiler errors.

There’s a lot more to preprocessor statements than just making constants, of course. I believe my use of them harkens back to a time when compilers were relatively blunt instruments, and const variables weren’t handled like constants in some compilers, and it’s just habit now. Still… a bunch of all caps defines is my happy place, so… LOL…

haha. Great, thanks for clarifying Davere. Really helpful chat altogether. :smiley:

I’m not sure if this sits exactly in the same category. I can shift it if not. I’m wondering if it is possible to write a particular piece of code that can detect if a load cell is connected. Let me explain.

I have 4 load cells connected to the Arduino. My current program works perfectly at measuring individual weights on each. I have changed the connection type on my load cells to connect to the HX711 via a plug (4-pin plug) like this: https://shop.edwinrobotics.com/connecto … r-set.html

I want to have a program that runs smoothly when three are connected (or any number) and then while running can detect when another one is connected.

Currently, when i plug a load cell in while the program is running it misses all of the setup stage and reads the weight without having been tare or anything else that I do in the beginning because the code will be in the loop stage. I was thinking of something like having an if loop in the setup section to check if the HX711 is connected (i don’t know how to do this), or have a ‘if’ loop in the void loop section to run the setup stage again if a loadcell is connected.

I don’t have any example code to share (not that i could anyway), so mainly trying to find out if this is possible and if you think it is how you think its possible.

Thanks in advance.