HX711 and Strain Gauge HW debugging

Hi

I'm developing a scale and I'm not understanding what's wrong.

The components are:

  • ESP32 (supply by USB)
  • HX711 controller (supply by 5v ESP out)
  • 4 Strain Gauges
    • upper right and lower right with black wire
    • upper left and lower left with black wire
    • lower right and lower left with white wire
    • upper right and upper left with white wire
    • E+ red wire from lower right
    • E- red wire from upper left
    • A+ red wire from upper right
    • A- red wire from lower left

I had to solder the strain gauges and HX711 controller to avoid cables issues but now I'm not reading value.

I've checked many times the links between them and they are correct. The values coming from the sensors are 0.

What do I expect reading the voltage for each component?
What do I check to ensure the correct hw setting?

  • I tested the voltage between HX711 VCC and Ground and it was 5v.
  • I tested the voltage between HX711 Data and Ground and it was near 0v
  • I tested the voltage between HX711 E+ and Ground (without Strain Gauges) and it was a bit lower than 5v
  • I tested the voltage between HX711 E- and Ground (without Strain Gauges) and it was a bit lower than 5v
  • I tested the voltage between HX711 A+ and Ground (without Strain Gauges) and it was 0v
  • I tested the voltage between HX711 A- and Ground (without Strain Gauges) and it was 0v
  • Next, I linked the E+, E-,A+, A- with the Strain gauges (in the following order lower right, upper left, upper right, lower left) and I tested the voltage each one and Ground and all is about 0.7 v

Before unsolder and soldering again, I've done it at least 3 times, I'd like to measure the voltage to isolate if there's a problem with the controller or the sensors.

In the beginning, I read value with the same code but there were many issues with the links and for that reason, I started to solder all cables to avoid contact problems.

The code I'm using is reported below (I started from Github example HX711_ADC Calibration.ino and I added 2 led to monitoring the values read)

/*
   -------------------------------------------------------------------------------------
   HX711_ADC
   Arduino library for HX711 24-Bit Analog-to-Digital Converter for Weight Scales
   Olav Kallhovd sept2017
   -------------------------------------------------------------------------------------
*/

/*
   Settling time (number of samples) and data filtering can be adjusted in the config.h file
   For calibration and storing the calibration value in eeprom, see example file "Calibration.ino"

   The update() function checks for new data and starts the next conversion. In order to acheive maximum effective
   sample rate, update() should be called at least as often as the HX711 sample rate; >10Hz@10SPS, >80Hz@80SPS.
   If you have other time consuming code running (i.e. a graphical LCD), consider calling update() from an interrupt routine,
   see example file "Read_1x_load_cell_interrupt_driven.ino".

   This is an example sketch on how to use this library
*/
#include "information_led.h"
#include <HX711_ADC.h>
#if defined(ESP8266)|| defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif



#define SCK_DELAY					1
#define SAMPLES 					32		//default value: 16



//pins:
const int HX711_dout = 4; //mcu > HX711 dout pin
const int HX711_sck = 5; //mcu > HX711 sck pin

//output led
const int LED_RED = 2; //mcu > HX711 dout pin
const int LED_GREEN = 15; //mcu > HX711 sck pin

InformationLed redLed(LED_RED);
InformationLed greenLed(LED_GREEN);

//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);

const int calVal_eepromAdress = 0;
unsigned long t = 0;



void calibrate() {
  Serial.println("***");
  Serial.println("Start calibration:");
  Serial.println("Place the load cell an a level stable surface.");
  Serial.println("Remove any load applied to the load cell.");
  Serial.println("Send 't' from serial monitor to set the tare offset.");

  boolean _resume = false;
  while (_resume == false) {
    LoadCell.update();
    if (Serial.available() > 0) {
      if (Serial.available() > 0) {
        char inByte = Serial.read();
        if (inByte == 't') LoadCell.tareNoDelay();
      }
    }
    if (LoadCell.getTareStatus() == true) {
      Serial.println("Tare complete");
      _resume = true;
    }
  }

  Serial.println("Now, place your known mass on the loadcell.");
  Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");

  float known_mass = 0;
  _resume = false;
  while (_resume == false) {
    LoadCell.update();
    if (Serial.available() > 0) {
      known_mass = Serial.parseFloat();
      if (known_mass != 0) {
        Serial.print("Known mass is: ");
        Serial.println(known_mass);
        _resume = true;
      }
    }
  }

  LoadCell.refreshDataSet(); //refresh the dataset to be sure that the known mass is measured correct
  float newCalibrationValue = LoadCell.getNewCalibration(known_mass); //get the new calibration value

  Serial.print("New calibration value has been set to: ");
  Serial.print(newCalibrationValue);
  Serial.println(", use this as calibration value (calFactor) in your project sketch.");
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(calVal_eepromAdress);
  Serial.println("? y/n");

  _resume = false;
  while (_resume == false) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
#if defined(ESP8266)|| defined(ESP32)
        EEPROM.begin(512);
#endif
        EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
        EEPROM.commit();
#endif
        EEPROM.get(calVal_eepromAdress, newCalibrationValue);
        Serial.print("Value ");
        Serial.print(newCalibrationValue);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(calVal_eepromAdress);
        _resume = true;

      }
      else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        _resume = true;
      }
    }
  }

  Serial.println("End calibration");
  Serial.println("***");
  Serial.println("To re-calibrate, send 'r' from serial monitor.");
  Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
  Serial.println("***");
}

void changeSavedCalFactor() {
  float oldCalibrationValue = LoadCell.getCalFactor();
  boolean _resume = false;
  Serial.println("***");
  Serial.print("Current value is: ");
  Serial.println(oldCalibrationValue);
  Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
  float newCalibrationValue;
  while (_resume == false) {
    if (Serial.available() > 0) {
      newCalibrationValue = Serial.parseFloat();
      if (newCalibrationValue != 0) {
        Serial.print("New calibration value is: ");
        Serial.println(newCalibrationValue);
        LoadCell.setCalFactor(newCalibrationValue);
        _resume = true;
      }
    }
  }
  _resume = false;
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(calVal_eepromAdress);
  Serial.println("? y/n");
  while (_resume == false) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
#if defined(ESP8266)|| defined(ESP32)
        EEPROM.begin(512);
#endif
        EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
        EEPROM.commit();
#endif
        EEPROM.get(calVal_eepromAdress, newCalibrationValue);
        Serial.print("Value ");
        Serial.print(newCalibrationValue);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(calVal_eepromAdress);
        _resume = true;
      }
      else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        _resume = true;
      }
    }
  }
  Serial.println("End change calibration value");
  Serial.println("***");
}

void setup() {
  Serial.begin(115200); delay(1000);
  Serial.println();
  Serial.println("Starting...");

  LoadCell.begin();
  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() || LoadCell.getSignalTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1);
  }
  else {
    LoadCell.setCalFactor(1.0); // user set calibration value (float), initial value 1.0 may be used for this sketch
    Serial.println("Startup is complete");
  }
  while (!LoadCell.update());
  calibrate(); //start calibration procedure
}

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.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
      float i = LoadCell.getData();

      Serial.print("Load_cell output val: ");
      Serial.print(" ");
      Serial.println(i);

      if( isnan(i) ){

        Serial.println(digitalRead(HX711_dout));
        redLed.SwitchON();
        greenLed.SwitchOFF();

      }else{

        redLed.SwitchOFF();
        greenLed.SwitchON();
      }

      newDataReady = 0;
      t = millis();
    }
  }

  //receive command from serial terminal
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay(); //tare
    else if (inByte == 'r') calibrate(); //calibrate
    else if (inByte == 'c') changeSavedCalFactor(); //edit calibration value manually
  }

  // check if last tare operation is complete
  if (LoadCell.getTareStatus() == true) {
    Serial.println("Tare complete");
  }

}

  1. With a 3.3v microcontroller, you should use an HX711 (like SparkFun's...link below) that can use different VCC (5v) and VDD (3.3v).

  2. The voltage between E- and ground should be zero, with and without the strain gauges. Since you measured a bit less than 5v, you may have a defective HX711.

  3. The voltage between E+ and ground should be about 4.3v, with and without the gauges, not "a bit less than 5v." You may have a defective unit.

  4. With the strain gauges properly wired, A+ and A- should be about half of 4.3v under no load.

  5. Regarding wiring: a "picture" is worth a 1000 words. Draw a schematic. And carefully read this website: https://www.hbm.com/en/7163/wheatstone-bridge-circuit/

https://learn.sparkfun.com/tutorials/load-cell-amplifier-hx711-breakout-hookup-guide/all

1 Like

Some (green) HX711 boards have have no ground plane,
and that leaves E- not connected to ground (design fault).
E+ should be between 4.25volt and 4.3volt (exactly), and E- should be 0volt (ground).
As DaveEvans already explained, you must use a special HX711 board with two supplies if you use a 3.3volt processor (ESP32).
Sparkfun has one, or you can try to mod one yourself.
Leo..

1 Like

Hi, @marzianoumano
Welcome to the forum.
Thanks for using code tags. :+1:

Can you please post your circuit diagram, a hand drawn circuit will be fine.
Noting the colour and connection of your gauges.

It will be work a thousand words when it comes to understanding your project.

Can you please also post picture(s) of your project?
So we can see your component layout.

Soldering your strain gauge bridge was a good idea to ensure solid readings. :+1:

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

You give too few facts about your problem :frowning:

Do you want to form a Wheatstone bridge from 4 strain gauges? That would never give absolute weight. Cable colors are not helpful in understanding what you do, please provide some graphic.

OK, I understand it's necessary to post an image about that :smiley: (I've done with KiCad if you tell me a better tool I really appreciate that)

@DaveEvans
With a 3.3v microcontroller, you should use an HX711 (like SparkFun's...link below) that can use different VCC (5v) and VDD (3.3v).

I'm using ESP32 LilyGo-T-Call-SIM800 that it has on pin 16 a 5v output. It should be fine, Is it right?

@DaveEvans
The voltage between E- and ground should be zero, with and without the strain gauges. Since you measured a bit less than 5v, you may have a defective HX711.

I've measured more times and it's not always 5v (without the strain gauges) sometimes it's 0v. So I guess HX711 could be defective.

@DaveEvans
The voltage between E+ and ground should be about 4.3v, with and without the gauges, not "a bit less than 5v." You may have a defective unit.

I measured again and it's 4.94v without the gauges.

@DaveEvans
With the strain gauges properly wired, A+ and A- should be about half of 4.3v under no load.

I measured 0v.

Wawa
Some (green) HX711 boards have have no ground plane,

Yes, I have a green HX711.

@DrDiettrich
Do you want to form a Wheatstone bridge from 4 strain gauges?

Yes, I want to form a Wheatsone bridge with 4 strain gauges. Unfortunately, I can't read the value even if I am supposed to have linked it all correctly.

@DrDiettrich
That would never give absolute weight.

What does it mean? I don't understand with "absolute weight".

In the end, I guess my HX711 could be defective and I have not a wiring issue. Are you agree with me? If that is correct I'll buy sparkfun controller as suggested by @DaveEvans

. Regarding wiring: a "picture" is worth a 1000 words. Draw a schematic. And carefully read this website: Wheatstone Bridge Circuit | Strain Gauge | HBM

Thanks for sharing :+1:

Using a strain gauge like this

What is the correct configuration for my use case?

A simple strain gauge has 2 connections and is combined with 3 resistors to a Wheatstone bridge. Your strain gauges with 3 wires seem to be something different - a data sheet is required.

If you combine 4 strain gauges into a single Wheatstone bridge then 2 gauges changing their resistance in sync can leave the bridge voltage unaffected.

You should build a Wheatstone bridge from each strain gauge and use 4 channels (2 HX711) to measure 4 distinct values.

Hi,
Your strain gauges are already half of a wheatstone bridges.

This might help, I know it is a destructible project, but it uses the gauges you are.

This may also be of assistance;

Google;

arduino using multiple strain gauges

Tom... :smiley: :+1: :coffee: :australia:

No, as explained before, the HX711 will output 5volt logic with a common (Chinese) HX711 board, which could damage the I/O of your ESP32 board.

E+ should be 4.3volt with the bridge connected, and E- should be 0.0volt.
A- and A+ should be about half of E+.
As said, it could be a board without ground plane (E- floating).
You should post a link to where you have bought it, or a clear picture of both sides of the board.
Leo..

A note on nomenclature, since using the correct search terms will give better results:

This is a strain gauge:

Screenshot 2021-11-09 210529

This is one type of load cell (which has one or more strain gauges in it):

Screenshot 2021-11-09 210958

Neither type of device give weight (or "absolute weight", whatever that is) directly, but they can be used to determine weight, either by calculation (using principles of mechanics and the strain gauge properties) or by calibration.

:grinning:

Now I understand what you say...

Dave's post resolves my doubts...

Maybe easier to use a "Load Sensor Combinator" for four 3-wire load cells.
Leo..

Hi,

I've just checked the projects posted by @TomGeorge :+1:

  • Arduino Bathroom Scale With 50 Kg Load Cells and HX711 Amplifier
  • 50KG Load CElls with HX711

And thery are exactly the same project that I've done :yum: (The only difference I use ESP32 instead Arduino UNO) - they are using output 5v to supply HX711 and they are connecting the DATA input to Arduino UNO as me.

I little bit confuse :roll_eyes: when @Wawa said

No, as explained before, the HX711 will output 5volt logic with a common (Chinese) HX711 board, which could damage the I/O of your ESP32 board

I don't believe there is a difference between me and them.

  • Could you confirm if that is I supposed it's right? Or there is a difference?

You should post a link to where you have bought it, or a clear picture of both sides of the board.

@Wawa I've bought my load cell here on Amazon

Based on the voltage measured on HX711 controller I think it's clear there's something wrong on it.

  • Are you agree with?
  • What should I do as next step? Should I buy a new HX711 by SparkFun? Should I buy Load Combinator as reported by @Wawa?

PS: I'll be more precise after DaveEvans's explanation...thanks a lot :grinning: :ok_hand: :+1:

  • Yes, there is a difference between your project and those other projects.
  • Yes, you should buy the SparkFun HX711.
  • Yes, you should buy the SparkFun combinator, too.

Because...

As mentioned or implied multiple times already, your ESP32 operates at 3.3 volts and the UNO used in the other projects operates at 5 volts. If you use the standard HX711, it will send 5 volt signals to your ESP32 and probably damage it. The SparkFun HX711 can (and in your case MUST) be configured to send 3.3 volt signals to the ESP32. The combinator is not required...just makes the wiring easy.

If you power the HX711 with 5volt, then the chip will obviously output 5volt signals.
Not very good to shove that 5volt logic into the inputs of a 3.3volt processor that might not be 5volt tolerant.

You must however power the analogue part of the HX711 with 5volt, because it's 4.3volt voltage regulator for the load cell needs it.

The designers of the chip have anticipated this problem, so they have split up the supplies for the analogue and digital parts of the chip. So you can power the analogue (load cell) part of the chip with 5volt, and the digital part (that connects to the ESP32) with 3.3volt.
Chinese designers didn't bother to bring out those two supplies, and just joined them onto one power pin (cheap).

Sparkfun did the right thing, and made the two separate chip supplies available to the user.
So if you are using that Sparkfun board with a 5volt processor, then power AVDD and DVDD both with 5volt.
But if you're using it with a 3.3volt processor, then power AVDD with 5volt and DVDD with 3.3volt.

If you can solder, then you could modify your green board to the Sparkfun standard.
The circuit diagram is on their website.

Hold your green board against a strong light. If you can see the light through it, then it's the board with E- not connected to ground. You must correct this (ground E-) for the board to work.
Only then will E+ be 4.3volt and E- 0volt.

A combinator is just an easier way to connect the four 3-wire load cells.
You can do that also yourself. The diagram is also on the sparkfun site.
Leo..

OK! :ok_hand:

Now it's everything clear!

Thank you so much for your patience. :pray:

Amazing :smiley:

Unfortunately, It's a little bit complex for me to modify my HX711 as sparkfun circuit diagram. Now I'm going to buy HX711 Sparkfun load cell to finish my job.

Anyway I have a curiosity:

Could it make a sense put a voltage divider between green HX711 and ESP32 input in order to have a 3.3v?

There is two-way communication between the HX711 and the ESP.
You could lower the 5volt data line from the HX711 to the ESP with a 1k:2k voltage divider.
But it's not easy to increase the 3.3volt clock from the ESP to the HX711 to 5volt.
Leo..

Does it make a sense put a pullup on SCK?

The pullup resistor between SCK and 5v connected to Hx711 VCC

PS: Probably it's better to do something like this. What do you think about it?