Running 13 Hx711 ADCs with efficient code

Hi All,

First of all let me thank you for your time to read this post and potentially help.
I'm a mechanical engineer so electronics and coding are not my strong points at all.

My setup is an Arduino Due connected to 13 HX711 ADCs to run 13 load cells to measure tension in lines.
The purpose of what created is like lab equipment for a particular experiment.

I can run each one of the sensors individually, and I can run them all at the same time without major problems.

But the code is very long and repetitive and kind of slow. I'd like to make it shorter and faster as the Due also runs an SD card to store the data and a Screen to display it real time.

I've looked into Arrays but I don't see how I can implement it to do things like:

  • setting up all 13 HX711s
  • setting the pins for each of those instances
  • reading averages, getting values setting scale and tare with FOR statments, etc

I've also looked into the HX711-multi library which works, but has some drawbacks. It requires a clock line instead of a clock line for each HX711 which is hard to implement on my pcb now. It doesn't have the tare and scale functionality (like the hx711.h lib) which is very important for my project.

Here's my simplified code, any help on direction or reading material would be greatly appreciated

//cluster for HX711
#include "HX711.h"  //HX711 library

HX711 scale1;       //set up scale #1
HX711 scale2;       //set up scale #2
HX711 scale3;       //set up scale #3
HX711 scale4;       //set up scale #4
HX711 scale5;       //set up scale #5
HX711 scale6;       //set up scale #6
HX711 scale7;       //set up scale #7
HX711 scale8;       //
HX711 scale9;       //
HX711 scale10;      //
HX711 scale11;      //
HX711 scale12;      //
HX711 scale13;      //


const float calib[13] = {9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8};
/*
const float calib1 = 9.8;  //scale1 scale factor
const float calib2 = 9.8;  //scale2 scale factor
const float calib3 = 9.8;  //scale3 scale factor
const float calib4 = 9.8;  //scale4 scale factor
const float calib5 = 9.8;  //scale5 scale factor
const float calib6 = 9.8;  //scale6 scale factor
const float calib7 = 9.8;  //scale7 scale factor
const float calib8 = 9.8;  //scale7 scale factor
const float calib9 = 9.8;  //scale7 scale factor
const float calib10 = 9.8;  //scale7 scale factor
const float calib11 = 9.8;  //scale7 scale factor
const float calib12 = 9.8;  //scale7 scale factor
const float calib13 = 9.8;  //scale7 scale factor
*/

const int init_sample = 10; //initial sample size
const int mini_sample = 5;  //mini sample size
const int sec_sample = 20;  //secondary sample size


//========================================================

void setup() {

Serial.begin(57600);  //initiate serial port
Serial.println("START");
//cluster for HX711

scale1.begin(22, 23);  //(DT,SCK) set hx711 pins for scale1 
scale1.set_gain(64); //set hx711 gain A (128 or 64)  B(32)

scale2.begin(24, 25);  //(DT,SCK) set hx711 pins for scale2 
scale2.set_gain(64); //set hx711 gain A (128 or 64)  B(32)

scale3.begin(26, 27);  //(DT,SCK) set hx711 pins for scale3 
scale3.set_gain(64); //set hx711 gain A (128 or 64)  B(32)

scale4.begin(28, 29);  //(DT,SCK) set hx711 pins for scale4 
scale4.set_gain(64); //set hx711 gain A (128 or 64)  B(32)

scale5.begin(30, 31);  //(DT,SCK) set hx711 pins for scale5 
scale5.set_gain(64); //set hx711 gain A (128 or 64)  B(32)

scale6.begin(32, 33);  //(DT,SCK) set hx711 pins for scale6 
scale6.set_gain(64); //set hx711 gain A (128 or 64)  B(32)

scale7.begin(34, 35);  //(DT,SCK) set hx711 pins for scale7 
scale7.set_gain(64); //set hx711 gain A (128 or 64)  B(32)

scale8.begin(36, 37);  
scale8.set_gain(64); 

scale9.begin(38, 39);  
scale9.set_gain(64); 

scale10.begin(40, 41); 
scale10.set_gain(64); 

scale11.begin(42, 43);  
scale11.set_gain(64); 

scale12.begin(44, 45);  
scale12.set_gain(64); 

scale13.begin(46, 47);  
scale13.set_gain(64); 


  
Serial.println("Initializing scales");
Serial.println("0%");
scale1.read();                      //raw reading from the ADC
scale2.read();  
scale3.read(); 
scale4.read(); 
scale5.read();  
scale6.read(); 
scale7.read(); 

Serial.println("10%");
scale1.read_average(init_sample);   //average of X readings from the ADC
scale2.read_average(init_sample);   
scale3.read_average(init_sample);   
scale4.read_average(init_sample);  
scale5.read_average(init_sample);   
scale6.read_average(init_sample);   
scale7.read_average(init_sample);  

Serial.println("20%");
scale1.get_value(mini_sample);      //average of Y readings from the ADC minus the tare weight (not set yet)
scale2.get_value(mini_sample);      
scale3.get_value(mini_sample);     
scale4.get_value(mini_sample);     
scale5.get_value(mini_sample);      
scale6.get_value(mini_sample);     
scale7.get_value(mini_sample);  

Serial.println("30%");
scale1.get_units(mini_sample);      //average of Y readings from the ADC minus tare weight (not set) divided by the SCALE parameter (not set yet)
scale2.get_units(mini_sample);     
scale3.get_units(mini_sample);     
scale4.get_units(mini_sample);  
scale5.get_units(mini_sample);     
scale6.get_units(mini_sample);     
scale7.get_units(mini_sample);  

Serial.println("40%");
scale1.set_scale(calib[1]);          // Set scale1 calibration factor
scale2.set_scale(calib[2]);
scale3.set_scale(calib[3]);
scale4.set_scale(calib[4]);
scale5.set_scale(calib[5]);
scale6.set_scale(calib[6]);
scale7.set_scale(calib[7]);

Serial.println("50%");
scale1.tare();                        // reset the scale1 to 0
scale2.tare(); 
scale3.tare(); 
scale4.tare(); 
scale5.tare(); 
scale6.tare(); 
scale7.tare(); 

Serial.println("55%");
scale1.read();                        //raw reading from the ADC
scale2.read(); 
scale3.read(); 
scale4.read(); 
scale5.read(); 
scale6.read(); 
scale7.read(); 

Serial.println("60%");
scale1.read_average(sec_sample);      // average of Z readings from the ADC
scale2.read_average(sec_sample); 
scale3.read_average(sec_sample); 
scale4.read_average(sec_sample); 
scale5.read_average(sec_sample); 
scale6.read_average(sec_sample); 
scale7.read_average(sec_sample); 

Serial.println("70%");
scale1.get_value(mini_sample);        // average of Y readings from the ADC minus the tare weight, set with tare()
scale2.get_value(mini_sample); 
scale3.get_value(mini_sample); 
scale4.get_value(mini_sample); 
scale5.get_value(mini_sample); 
scale6.get_value(mini_sample); 
scale7.get_value(mini_sample); 

Serial.println("80%");
scale1.get_units(mini_sample);        // average of Y readings from the ADC minus tare weight, divided by the SCALE parameter set with set_scale
scale2.get_units(mini_sample); 
scale3.get_units(mini_sample); 
scale4.get_units(mini_sample); 
scale5.get_units(mini_sample); 
scale6.get_units(mini_sample); 
scale7.get_units(mini_sample); 

Serial.println("90%");
scale1.tare();                        //reset the scale to 0
scale2.tare();            
scale3.tare();            
scale4.tare();            
scale5.tare();            
scale6.tare();            
scale7.tare();            

Serial.println("scales 100%");

}


void tension_printSerial() {
  // print to the serial port too:
   Serial.print(millis()/1000);
   Serial.print("...S1.");
   Serial.print(scale1.get_units(1), 0);
   Serial.print("...S2.");
   Serial.print(scale2.get_units(1), 0);
   Serial.print("...S3.");
   Serial.print(scale3.get_units(1), 0);
   Serial.print("...S4.");
   Serial.print(scale4.get_units(1), 0);
   Serial.print("...S5.");
   Serial.print(scale5.get_units(1), 0);
   Serial.print("...S6");
   Serial.print(scale6.get_units(1), 0);
   Serial.print("...S7.");
   Serial.println(scale7.get_units(1), 0);  
}


void loop() {
tension_printSerial();
}

IMG_0475.JPG

The code you posted won't build because scale8 - scale13 are not defined. Also you have no loop function.

Not complete but it compiles and should give you an idea.

#include "HX711.h"  //HX711 library

HX711 scale[7];       //set up scale #1
byte scalePins[7][2] = {{22,23},{24,25},{26,27}, {28,29}, {30,31},{32,33},{34,35}};      
const float calib[13] = {9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8};

const int init_sample = 10; //initial sample size
const int mini_sample = 5;  //mini sample size
const int sec_sample = 20;  //secondary sample size

void setup() {

  Serial.begin(57600);  //initiate serial port
  Serial.println("START");
  
  for (int idx = 0; idx < 7; idx++)
  {
    scale[idx].begin(scalePins[idx][0], scalePins[idx][1]);
    scale[idx].set_gain(64);
    scale[idx].set_scale(calib[idx]);   // Set scale calibration factor
    scale[idx].tare();                        // reset the scale to 0
  }
}

void loop()
{
  
}

ToddL1962:
The code you posted won't build because scale8 - scale13 are not defined. Also you have no loop function.

Sorry about that, my mistake to not define 8 to 13, was just trying to make it work with 7 as it will be trivial going from 7 to 13.

The absence of the loop was just a simply copy/paste mistake. Fixed it now on the original post.

ToddL1962:
Not complete but it compiles and should give you an idea.

This is awesome and exactly what I wanted to do but couldn't figure out how to write it. Thank you so much for the help.

This is now my working code implemented using your suggestion above.
It works well. One thing that could be improved is the calibration of the loadcells (setup).
It goes through them one by one taking readings and averages etc. I wonder if there is way to do this step for all 7 (or 13) hx711s in parallel instead of series?

Taking the readings though (loop part) works very well and at the right speed (10Hz) which is the current speed of the hx711s.

#include "HX711.h"  //HX711 library

HX711 scale[7];       //sets up 7 scales
byte scalePins[7][2] = {{22,23},{24,25},{26,27}, {28,29}, {30,31},{32,33},{34,35}};     //defines the pairs of pins for each scale
const float calib[7] = {9.8, 9.8, 9.8, 9.8, 9.8, 9.8, 9.8};                             //defines the calibration factor for each scale

const int init_sample = 10; //initial sample size
const int mini_sample = 5;  //mini sample size
const int sec_sample = 20;  //secondary sample size

void setup() {

  Serial.begin(57600);      //initiate serial port
  Serial.println("START");
 
  for (int idx = 0; idx < 7; idx++)
  {
    scale[idx].begin(scalePins[idx][0], scalePins[idx][1]);   //initializes each of the scales using the pin pairs
    scale[idx].set_gain(64);                                  //sets the gain for each of the scales

Serial.print("Calibrating ");
Serial.println(idx);

    scale[idx].read();                          //raw reading from the ADC
    scale[idx].read_average(init_sample);       //average of X readings from the ADC
    scale[idx].get_value(mini_sample);          //average of Y readings from the ADC minus the tare weight (not set yet)
    scale[idx].get_units(mini_sample);          //average of Y readings from the ADC minus tare weight (not set) divided by the SCALE parameter (not set yet)
    scale[idx].set_scale(calib[idx]);           //set scale calibration factor
    scale[idx].tare();                          //reset the scale to 0
    scale[idx].read();                          //raw reading from the ADC 
    scale[idx].read_average(sec_sample);        //average of Z readings from the ADC
    scale[idx].get_value(mini_sample);          //average of Y readings from the ADC minus the tare weight, set with tare()
    scale[idx].get_units(mini_sample);          //average of Y readings from the ADC minus tare weight, divided by the SCALE parameter set with set_scale
    scale[idx].tare();                          //reset the scale to 0
    
Serial.print(idx);
Serial.println(" DONE");

  }
}

void tension_printSerial() {
   Serial.print(millis()/1000);                     //prints seconds to serial
  for (int idy = 0; idy < 7; idy++)
  {
    Serial.print("...");
    Serial.print(scale[idy].get_units(1), 0);       //prints each scale to serial
  }
   Serial.println("grams");
}
   
void loop() {
tension_printSerial();
}

Is it just wrong of me to assume the arduino can read more than one hx711 at the same time?

If it just can't, the code probably can't be improved much and to make the calibration step faster I'm better off switching the hx711s to 80hz instead of 10hz even though this results in a noisier signal?