3

Helllo,
I am using the HX711 module and load cell with an arduino uno for force measurements. I am using this library.

I first use the example "Calibration" code for calibration with a 200 g weight. Then I save the calibration constant to the eeprom (choosing yes on the serial monitor). Then the load cell is able to measure weights accurately.

After that I remove the weight from the load cell and run this code after uncommenting the last line of this part of the above code:

LoadCell.begin();
  //LoadCell.setReverseOutput();
  float calibrationValue;
  calibrationValue = 696.0;
#if defined(ESP8266)|| defined(ESP32)
  //EEPROM.begin(512);
#endif
  EEPROM.get(calVal_eepromAdress, calibrationValue); // I have uncommented this

The weights are measured accurately.

But when before powering the arduino, if I keep a weight on the load cell that weight is taken to be 0.

For this I have done the following change to the code:

boolean _tare = false;

But I get the following output on the serial monitor (Note: The following output is obtained on startup when there is/there is no weight on the load cell):

enter image description here

Questions: What is the use of the following line:

calibrationValue = 696.0; // uncomment this if you want to set the calibration value in the sketch

Is it useless for the code I am using above? Because I am using the calibration value from the eeprom.

Q2) Why is it showing -39000 as an output value? And how to correct it?

Alternate Statement: In other words, I want to use the HX711 module with the arduino and a load cell. I will first calibrate it with a known weight and save the calibration value. Before powering up the arduino I will keep a weight on the load cell. After powering up the weight value should be the absolute value instead of making the Weight Null.

EDIT1: I incorporate the changes suggested in the answers by @Edgar Bonet and also make the problem more clear just in case. According to suggestions I have made the corresponding changes to the calibration code. Then I run that and the values are saved to eeprom. Code changes:

const int calVal_eepromAdress = 0;
const int tare_eepromAdress = sizeof(float);

and

#endif
        EEPROM.put(calVal_eepromAdress, newCalibrationValue);
        EEPROM.put(tare_eepromAdress, LoadCell.getTareOffset());
#if defined(ESP8266)|| defined(ESP32)
        EEPROM.commit();

Now, I wish to run the second script and for this to display the correct weights. This should work in all cases regardless of whether a weight has not been kept on the load cell or has been kept and should be independent of the weight that has been kept. To this script I have made the following changes:

const int calVal_eepromAdress = 0;
const int tare_eepromAdress = sizeof(float);

and

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

  LoadCell.begin();
  //LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive
  float calibrationValue; // calibration value (see example file "Calibration.ino")
  float tareValue;
  calibrationValue = 696.0; // uncomment this if you want to set the calibration value in the sketch
  tareValue = 0;
#if defined(ESP8266)|| defined(ESP32)
  //EEPROM.begin(512); // uncomment this if you use ESP8266/ESP32 and want to fetch the calibration value from eeprom
#endif
  EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom
  EEPROM.get(tare_eepromAdress, tareValue);

  unsigned long stabilizingtime = 2000; // preciscion right after power-up 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
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1);
  }
  else {
    LoadCell.setCalFactor(calibrationValue); // set calibration value (float)
    LoadCell.setTareOffset(tareValue);
    Serial.println("Startup is complete");
  }
}

EDIT2:

#if defined(ESP8266)|| defined(ESP32)
        EEPROM.begin(512);
#endif
        EEPROM.put(calVal_eepromAdress, newCalibrationValue);
        EEPROM.put(tare_eepromAdress, LoadCell.getTareOffset());

        Serial.println(newCalibrationValue);
        Serial.println(LoadCell.getTareOffset());

Output:

-206.90
8368790

In the second script:

#if defined(ESP8266)|| defined(ESP32)
  //EEPROM.begin(512); // uncomment this if you use ESP8266/ESP32 and want to fetch the calibration value from eeprom
#endif
  EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom
  EEPROM.get(tare_eepromAdress, tareValue);
  Serial.println(calibrationValue);
  Serial.println(tareValue);

Output:

-206.90
0.00

I am uploading my codes onto Github just in case. They can be found here.

Q) What is happening here?

EDIT3: The following changes make it work like a charm: In the "Calibration" script:

long tareValue = LoadCell.getTareOffset(); // Instead of float tareValue

Similarly in the second script:

long tareValue; // Instead of float tareValue
3
  • Have you checked which value the calibrationValue has before you write to EEPROM and after you read it from EEPROM? Just to check if the storage of the value works correctly. And you need to begin the EEPROM for it to work correctly
    – chrisl
    Jul 15, 2022 at 7:17
  • @chrisl yes, it is being read correctly.
    – Atharva
    Jul 15, 2022 at 8:52
  • see the library example file Persistent_zero_offset.ino.
    – olkal
    Jul 16, 2022 at 15:20

1 Answer 1

4

In order to convert the raw ADC readings to a weight, the library needs two coefficients:

  • a “tare offset”, which is the raw reading when there is no weight on the scale
  • a gain, or “calibration factor”, which is the ratio of a change in the ADC reading to the corresponding change in weight.

The examples provided with the library use the EPPROM to store and retrieve the calibration factor, but not the tare offset. This makes sense as, in common usage, a weight scale is always zeroed at power up, or right after power up. This is usually desirable as one would often place an empty container on the scale which should not affect the displayed weight.

If you do not want to zero the scale at power-up, then you need your sketch to remember the tare offset in addition to the calibration factor. For this, you can use the methods of LoadCell:

// Get the tare offset (raw data value output without
// the scale "calFactor").
long getTareOffset();

// Set new tare offset (raw data value input without
// the scale "calFactor").
void setTareOffset(long newoffset);

Now, to the more specific questions:

What is the use of the following line:

calibrationValue = 696.0;

None. It is just an example. You are supposed to either replace this number with your measured calibration factor, or remove this line and read calibrationValue from the EEPROM.

Why is it showing -39000 as an output value?

Because the tare offset has not been set, so it presumably defaults to zero.


Edit: Answering extra questions in comment.

Do I need to store this value to the eeprom when running the calibration script?

You can store it whenever it is convenient to you. The calibration script seems a good place.

I am not able to get this into code. I read the source files but I am unsure about what changes to make.

What you may try (untested):

  1. right after the line

    const int calVal_eepromAdress = 0;
    

    add this:

    const int tare_eepromAdress = sizeof(float);
    
  2. Right after this:

    EEPROM.put(calVal_eepromAdress, newCalibrationValue);
    

    add this:

    EEPROM.put(tare_eepromAdress, LoadCell.getTareOffset());
    
6
  • Thanks that makes sense. Do I need to store this value to the eeprom when running the calibration script? I am not able to get this into code. I read the source files but I am unsure about what changes to make to the calibration and the second script. Any help is greatly appreciated.
    – Atharva
    Jul 15, 2022 at 9:20
  • I have made the changes you suggested and have added changes to the second script as well. I clarify the changes in the original question. Please have a look
    – Atharva
    Jul 15, 2022 at 10:41
  • Regarding your changes, you should probably set _tare to false in order to avoid setting the tare offset twice. You cal also get rid of the if (LoadCell.getTareTimeoutFlag()) part and unconditionally set both the calibration factor and the tare offset. Jul 15, 2022 at 12:01
  • It's still not working. I get -40000 on the Serial Monitor. I show the changes and the results here.
    – Atharva
    Jul 16, 2022 at 2:51
  • Ok it seems the right value is not being stored for the tare value. I show this in EDIT2 in my post.
    – Atharva
    Jul 16, 2022 at 3:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.