Use load cell setup without tare on each use

Hi all,

I am rather new to using Arduino for reading sensors and I feel I could use your help. Currently, I am building a mechanical test setup which makes use of multiple load cells (barrel type, male threaded on both ends). I use an Arduino Uno and hx711's and wired according to the figure below.

Using the hx711 ADC library by Olav Kallhovd (sept 2017) I adapted his Read_2x_loadcell example to work for my situation. This works all well, however, it tares the sensors every time I open the serial monitor/plotter. Since my application is relatively permanent and sensors might be pre loaded when my system is set up, I would like to get rid of the tare function and for example use a manual zero factor for my sensors instead.

//-------------------------------------------------------------------------------------
// HX711_ADC.h
// Arduino master library for HX711 24-Bit Analog-to-Digital Converter for Weigh Scales
// Olav Kallhovd sept2017
// Tested with      : HX711 asian module on channel A and YZC-133 3kg load cell
// Tested with MCU  : Arduino Nano
//-------------------------------------------------------------------------------------
// This is an example sketch on how to use this library for two ore more HX711 modules
// Settling time (number of samples) and data filtering can be adjusted in the config.h file

#include <HX711_ADC.h>
#include <EEPROM.h>

//pins:
const int HX711_dout_1 = 4; //mcu > HX711 no 1 dout pin
const int HX711_sck_1 = 5; //mcu > HX711 no 1 sck pin
const int HX711_dout_2 = 6; //mcu > HX711 no 2 dout pin
const int HX711_sck_2 = 7; //mcu > HX711 no 2 sck pin

//HX711 constructor (dout pin, sck pin)
HX711_ADC LoadCell_1(HX711_dout_1, HX711_sck_1); //HX711 1
HX711_ADC LoadCell_2(HX711_dout_2, HX711_sck_2); //HX711 2

const int calVal_eepromAdress_1 = 0; // eeprom adress for calibration value load cell 1 (4 bytes)
const int calVal_eepromAdress_2 = 4; // eeprom adress for calibration value load cell 2 (4 bytes)
long t;

void setup() {
  Serial.begin(57600); delay(10);
  Serial.println();
  Serial.println("Starting...");

  float calibrationValue_1; // calibration value load cell 1
  float calibrationValue_2; // calibration value load cell 2

  calibrationValue_1 = 696.0; // uncomment this if you want to set this value in the sketch
  calibrationValue_2 = 733.0; // uncomment this if you want to set this value in the sketch
#if defined(ESP8266) || defined(ESP32)
  //EEPROM.begin(512); // uncomment this if you use ESP8266 and want to fetch the value from eeprom
#endif
  //EEPROM.get(calVal_eepromAdress_1, calibrationValue_1); // uncomment this if you want to fetch the value from eeprom
  //EEPROM.get(calVal_eepromAdress_2, calibrationValue_2); // uncomment this if you want to fetch the value from eeprom

  LoadCell_1.begin();
  LoadCell_2.begin();
  long stabilizingtime = 2000; // tare preciscion 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
  byte loadcell_1_rdy = 0;
  byte loadcell_2_rdy = 0;
  while ((loadcell_1_rdy + loadcell_2_rdy) < 2) { //run startup, stabilization and tare, both modules simultaniously
    if (!loadcell_1_rdy) loadcell_1_rdy = LoadCell_1.startMultiple(stabilizingtime, _tare);
    if (!loadcell_2_rdy) loadcell_2_rdy = LoadCell_2.startMultiple(stabilizingtime, _tare);
  }
  if (LoadCell_1.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 no.1 wiring and pin designations");
  }
  if (LoadCell_2.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 no.2 wiring and pin designations");
  }
  LoadCell_1.setCalFactor(calibrationValue_1); // user set calibration value (float)
  LoadCell_2.setCalFactor(calibrationValue_2); // user 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_1.update()) newDataReady = true;
  LoadCell_2.update();

  //get smoothed value from data set
  if ((newDataReady)) {
    if (millis() > t + serialPrintInterval) {
      float a = LoadCell_1.getData();
      float b = LoadCell_2.getData();
      Serial.print("Load_cell 1 output val: ");
      Serial.print(a);
      Serial.print("    Load_cell 2 output val: ");
      Serial.println(b);
      newDataReady = 0;
      t = millis();
    }
  }

  // receive command from serial terminal, send 't' to initiate tare operation:
  if (Serial.available() > 0) {
    float i;
    char inByte = Serial.read();
    if (inByte == 't') {
      LoadCell_1.tareNoDelay();
      LoadCell_2.tareNoDelay();
    }
  }

  //check if last tare operation is complete
  if (LoadCell_1.getTareStatus() == true) {
    Serial.println("Tare load cell 1 complete");
  }
  if (LoadCell_2.getTareStatus() == true) {
    Serial.println("Tare load cell 2 complete");
  }

}

Using another script (circuits4you.com), found below, I am able to obtain zero factors for my sensors. This is where my struggles begin since now I do not know how to implement either a manual zero factor in my first, already working, script or how to use the actual zero factor in the second script to get rid of the tare moments.
I searched the forum for comparable setups/questions but failed in finding any. Hopefully you can give me some advice and tips on how to approach this issue.
Best,
BramM

/*
 * circuits4you.com
 * 2016 November 25
 * Load Cell HX711 Module Interface with Arduino to measure weight in Kgs
 Arduino 
 pin 
 2 -> HX711 CLK
 3 -> DOUT
 5V -> VCC
 GND -> GND

 Most any pin on the Arduino Uno will be compatible with DOUT/CLK.
 The HX711 board can be powered from 2.7V to 5V so the Arduino 5V power should be fine.
*/

#include "HX711.h"  //You must have this library in your arduino library folder

#define DOUT  3
#define CLK  2

HX711 scale(DOUT, CLK);

//Change this calibration factor as per your load cell once it is found you many need to vary it in thousands
float calibration_factor = 296650; //-106600 worked for my 40Kg max scale setup 

//=============================================================================================
//                         SETUP
//=============================================================================================
void setup() {
  Serial.begin(9600);
  Serial.println("HX711 Calibration");
  Serial.println("Remove all weight from scale");
  Serial.println("After readings begin, place known weight on scale");
  Serial.println("Press a,s,d,f to increase calibration factor by 10,100,1000,10000 respectively");
  Serial.println("Press z,x,c,v to decrease calibration factor by 10,100,1000,10000 respectively");
  Serial.println("Press t for tare");
  scale.set_scale();
  scale.tare(); //Reset the scale to 0

  long zero_factor = scale.read_average(); //Get a baseline reading
  Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects.
  Serial.println(zero_factor);
}

//=============================================================================================
//                         LOOP
//=============================================================================================
void loop() {

  scale.set_scale(calibration_factor); //Adjust to this calibration factor

  Serial.print("Reading: ");
  Serial.print(scale.get_units(), 3);
  Serial.print(" kg"); //Change this to kg and re-adjust the calibration factor if you follow SI units like a sane person
  Serial.print(" calibration_factor: ");
  Serial.print(calibration_factor  );
  Serial.println();

  if(Serial.available())
  {
    char temp = Serial.read();
    if(temp == '+' || temp == 'a')
      calibration_factor += 10;
    else if(temp == '-' || temp == 'z')
      calibration_factor -= 10;
    else if(temp == 's')
      calibration_factor += 100;  
    else if(temp == 'x')
      calibration_factor -= 100;  
    else if(temp == 'd')
      calibration_factor += 1000;  
    else if(temp == 'c')
      calibration_factor -= 1000;
    else if(temp == 'f')
      calibration_factor += 10000;  
    else if(temp == 'v')
      calibration_factor -= 10000;  
    else if(temp == 't')
      scale.tare();  //Reset the scale to zero
  }

  delay(100);
}

The short (and self-evident) answer: do some work to learn how to program your Arduino.

The slightly longer answer: first, do some work to learn what each line in your two sketches does (the reference section of the Arduino website is a good resource). Then do the same for the example sketches provided with the IDE - not every one of them, just the ones that sound like they may be helpful to your situation. For example, if you are not going to have serial control of the "production" unit, then you may want to consider adding a simple momentary-contact switch that you can press when you want to "tare" the system. If so, then look at the Button (and, possibly, the Debounce) example.

Thank you Dave for taking the time to respond to my post. I agree that it is clear I need to dive deeper into Arduino programming. However, at this point I managed to solve my initial wish, being able to read multiple load cells / hx711 using manual zero factors. To me this is a good enough basis to use for now and improve along the way.

I worked from Nathan Seidle's (Sparkfun 2014) example and added some extra lines. It works well both at 10Hz and at 80Hz. For the ones who run into the same issue, here's my working code:

#include "HX711.h" //This library can be obtained here http://librarymanager/All#Avia_HX711
 
#define cal_factor_CR 3750 //5189.91 //This value is obtained using the SparkFun_HX711_Calibration sketch
#define zero_factor_CR 44460 //This value is obtained using the SparkFun_HX711_Calibration sketch
 
#define cal_factor_CL 4100
#define zero_factor_CL 298202
 
#define cal_factor_Bf -1100
#define zero_factor_Bf 31313
 
#define cal_factor_Mf -6200
#define zero_factor_Mf -34480
 
 
#define CR_DOUT_PIN  6 //mcu > CR dout pin
#define CR_SCK_PIN  7 //mcu > CR sck pin
 
#define CL_DOUT_PIN  4 //mcu > CL dout pin
#define CL_SCK_PIN  5 //mcu > CL sck pin
 
#define Bf_DOUT_PIN  8 //mcu > Bf dout pin
#define Bf_SCK_PIN  9 //mcu > Bf sck pin
 
#define Mf_DOUT_PIN  10 //mcu > Mf dout pin
#define Mf_SCK_PIN  11 //mcu > Mf sck pin
 
HX711 scaleCR;
HX711 scaleCL;
HX711 scaleBf;
HX711 scaleMf;
 
void setup() {
  Serial.begin(57600);
    
  scaleCR.begin(CR_DOUT_PIN, CR_SCK_PIN);
  scaleCR.set_scale(cal_factor_CR);
  scaleCR.set_offset(zero_factor_CR);
 
  scaleCL.begin(CL_DOUT_PIN, CL_SCK_PIN);
  scaleCL.set_scale(cal_factor_CL);
  scaleCL.set_offset(zero_factor_CL);
 
  scaleBf.begin(Bf_DOUT_PIN, Bf_SCK_PIN);
  scaleBf.set_scale(cal_factor_Bf);
  scaleBf.set_offset(zero_factor_Bf);
 
  scaleMf.begin(Mf_DOUT_PIN, Mf_SCK_PIN);
  scaleMf.set_scale(cal_factor_Mf;
  scaleMf.set_offset(zero_factor_Mf);
 
  Serial.println("Readings:");
}
 
void loop() {
  Serial.print(" CR: ");
  Serial.print(scaleCR.get_units(), 1); //scale.get_units() returns a float
 
  Serial.print(" CL: ");
  Serial.print(scaleCL.get_units(), 1); //scale.get_units() returns a float
 
  Serial.print(" Bf: ");
  Serial.print(scaleBf.get_units(), 1); //scale.get_units() returns a float
 
  Serial.print(" Mf: ");
  Serial.print(scaleMf.get_units(), 1); //scale.get_units() returns a float
 
    Serial.println();
}

BramM

Hi bramm,

I will help you not in much "tangible" level but rather in "system" level / some practical theory.
The biggest error of a load cell is the offset error, yes, the zero or tare error. If you take good load cells (I mean of reputable manufacturers) to environmental conditions of lets say 30 Celcius difference and give a time of e.g. a few days, the offset error might be around 1% of full scale. Another 1% upon that might be the offset error of your ADC (Analog to Digital) converter, if that one is a good quality. Unfortunately the cheap HX711 is in the bottom of specs in the market.
So:

  • Study the load cell datasheet (if you do not have one, you should worry)
  • Calculate your constrains in that error
  • Choose a good ADC
  • Account all those and decide if you have a "go" since there is almost nothing you can do to zero-out the offset error without unloading your scale physically
    A suggestion of my long time in weighing engineering is this one for ADC (at the high end actually, regardless its price)
    "DGT1": MULTIFUNCTION, DIGITAL WEIGHT TRANSMITTER /
    which you can very easily connect with your Arduino using the UART and an RS232 level to TTL level converting circuit. The data are super easy to turn them from text to numerical weight.
    Note I have no affiliation to those guys, no profit from them.
    As you mention " I agree that it is clear I need to dive deeper into Arduino programming ", if you feel like you are on your first steps, I suggest to you this one which I admit I make money of (I wrote it)
    Practical Electronics and Arduino in 8 Hours
    Hope I helped you in the bigger picture / harder problems out there. Your problem is not only the software most probably

Keep on, you can make it!!!!
Jim

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.