0
\$\begingroup\$

How do you make a load cell's amp HX711 measure both positive and negative values, or how do you set the center value for it? The main point is how to set the reference voltage (?) or something else so it can work like a joystick axis set it the center position, and work with an only lc or an extra one added, only one is preferable, say like a simple POT here.

That's a code for it.

#include <HX711.h>
#include <Joystick.h>
#define calibration_factor 400// Change this value to give accurate reading with your known mass.
#define DOUT  1
#define CLK  0
HX711 scale;
/*
Please check out our YouTube video series, Make your own loadcell pedals for sim racing
 
www.gpsimrigs.com
 
www.facebook.com/gpracesim
  */
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
  JOYSTICK_TYPE_MULTI_AXIS, 4, 3,
  false, false, true, false, false, false,
  false, true, true, true, false);
 
 
 
int brake = 0;
int lastBrakeValue = 0;
 
void setup() {
  // Ranges are 1023 by default
   Joystick.setBrakeRange(0, 1023);
  
 
  Joystick.begin();
  Serial.begin(38400);
 
  scale.begin(DOUT, CLK);
  scale.set_scale(calibration_factor);
  scale.tare();
}
void loop() {
 
//Displays reading in Serial Monitor
 
    Serial.println (brake);
brake = scale.get_units(); // if the value is inverted put a - sign in front like -scale.get
 
   if (brake < 0 or brake < 1) {
    brake = 0;
  }
 
   if (lastBrakeValue != brake) {
     Joystick.setBrake(brake);
     lastBrakeValue = brake;
  }
}
\$\endgroup\$
4
  • 1
    \$\begingroup\$ As you can see in fig 1 of the datasheet, inputs are differential. You need just setting the "middle point". Be aware that sensitivity is "high" +/- 20mV or +/- 40 mV. And you have inputs A and B. \$\endgroup\$
    – Antonio51
    Commented Dec 22, 2021 at 12:16
  • \$\begingroup\$ Antonio51, how to do it? Extra resistors in the lc white green wires? Or tweaks in hx711? \$\endgroup\$
    – Sieben
    Commented Dec 22, 2021 at 12:23
  • 1
    \$\begingroup\$ 4 (?) Extra resistors are to be added to the "bridge", so that voltages are in the middle of the power supply voltage. \$\endgroup\$
    – Antonio51
    Commented Dec 22, 2021 at 12:28
  • \$\begingroup\$ Sound good! Don't you know how much shall be placed, just around at least? And shall they be placed on both of A&B channels. Or shall be put just to power line on red wire? Thanks! \$\endgroup\$
    – Sieben
    Commented Dec 22, 2021 at 12:32

2 Answers 2

2
\$\begingroup\$

Sorry, but adding any components to the schematics is fighting a problem that does not exist.

Not to mention introducing additional components with their own thermal characteristics, on top of thermal drifts in the chip and load cells. This can only be justified if you add very complex schematics with thermistor, carefully calibrated for compensation.

HX711 already provides you with differential output, the only problem is that the combination of the chip with load cell has quite huge offset.

So, all you have to do is take a reading in the neutral position and then subtract it every time you read later. Or better yet, take several readings and calculate an average, for better precision.

When you do this all positive values would mean pressure applied in one direction, all negative values would be for other direction.

However keep in mind that many load cells will not return exactly to the center position when pressure removed. The usual way to deal with this is to have "dead zone" in your software, where any input is treated as zero.

UPDATE

Here is some primitive code I've used before to read two load cells with one chip. All you have to do is call Update() function often enough to keep reading data. You don't need any additional components for second load cell. Connect it as shown in the datasheet only use INB+, INB- inputs, there should not be much cross-talk between the channels.

#define GAIN_A_128  1   // Gain 128 (channel A) +/- 20mV @5V
#define GAIN_B_32   2   // Gain 32 (channel B) +/- 80mV @5V
#define GAIN_A_64   3   // Gain 64 (channel A) +/- 40mV @5V

int32_t value_a = 0;
int32_t value_b = 0;
bool current_ch = false;    // channel a = true, channel b = false

int ReadAndSetGain(int gain)
{
    // read chip data
    int ret = 0;
    // pulse clock pin 24 times to read the data as 2's complement value
    for (int i = 0; i < 24; i++)
    {
        gpio_set(clk_out_pin, true);
        gpio_set(clk_out_pin, false);
        ret = (ret << 1) + (gpio_get(data_in_pin) ? 1 : 0);
    }
    // set the channel and gain factor for next reading using clock pin
    for (int i = 0; i < gain; i++)
    {
        gpio_set(clk_out_pin, true);
        gpio_set(clk_out_pin, false);
    }
    // propagate sign bit
    if (ret & 0x800000) ret |= 0xFF000000;
    return ret;
}

// Call this function every 13 ms if HX711 data rate is 80 Hz,
// every 101 ms if data rate is 10 Hz to keep channel values updated.
// Note that default gain after reset is GAIN_A_128, so the channel values
// will be incorrect until after three successful readings.
void Update()
{
    // make sure data is available
    if (gpio_get(data_in_pin)) return;
    if (current_ch) {   // reading channel A
        value_a = ReadAndSetGain(GAIN_B_32);
    } else {            // reading channel B
        value_b = ReadAndSetGain(GAIN_A_64);
    }
    current_ch = !current_ch;
}

You can modify this code to suit your needs, of course. For example, instead of calling Update() periodically, you can read channels only when you need them:

int offset_a = 0;
int offset_b = 0;

int ReadA()
{
    while (current_ch) Update();    // make sure channel A has been read
    return value_a - offset_a;
}

int ReadB()
{
    while (!current_ch) Update();   // make sure channel B has been read
    return value_b - offset_b;
}

// call this in the beginning of a program when sensors are in neutral position
void Tare()
{
    // reset previous offsets
    offset_a = 0;
    offset_b = 0;
    // read and discard to initialize chip gain
    ReadB(); 
    // store current values as new offsets
    offset_a = ReadA();
    offset_b = ReadB();
}
\$\endgroup\$
11
  • \$\begingroup\$ With INA122 people connect together two cells with cross connection of the signal channels. And it works. But INA122 is an analog and HX711 is digit. I tried to do the same but doesn't go also. Also connected each with t's own amp - all the same. Also do the mechanical preload, but it has an impact then on the another axis, because it becomes extra sensitive. And I don't know how to implement the negative readings from all the same cell, if to read it from the zero load position. May some coding help out? \$\endgroup\$
    – Sieben
    Commented Dec 22, 2021 at 17:47
  • 1
    \$\begingroup\$ As far as I remember, it sends data in 2's complement format. It is described in details in the datasheet. Also if you use one chip to read two sensors keep in mind that inputs A and B have different gains, so you need additional division to bring higher gain input to the same scale. \$\endgroup\$
    – Maple
    Commented Dec 22, 2021 at 18:20
  • 1
    \$\begingroup\$ @Sieben I've added small code sample to help you move along \$\endgroup\$
    – Maple
    Commented Dec 23, 2021 at 0:13
  • 1
    \$\begingroup\$ @Sieben You realize that I have no idea what platform you are developing on or even what language. The code samples should be treated as pseudo-code that shows you the logic. It is up to you to adapt it to your framework. \$\endgroup\$
    – Maple
    Commented Dec 23, 2021 at 15:57
  • 1
    \$\begingroup\$ @Sieben any code added to setup function() will be executed once at the beginning of the program. code added to loop() function will be repeated over and over again after that. The blog that you linked to has all you need to understand how to scale output of the load cell (ReadA/ReadB functions in my example) to the desired range. It is basic math, after all. You don't have to achieve that "224" or any special number. You are getting pressure data in some range, and it is entirely up to you how to use it. The rest is pure software domain that is outside of this site purview \$\endgroup\$
    – Maple
    Commented Dec 23, 2021 at 18:14
2
\$\begingroup\$

Example of Schematic to be used, resistors (1k ?) to the adjusted midpoint (+/-) at inputs within 20 or 40 mV (scale). Depends on the joystick used (100 Ohm ?).

EDIT: these resistors are not needed if you don't care about Common Mode input voltage : min=AGND+1.2V and max=AVDD-1.3V. If used, then take same resistors from the same "lot", "paired" if possible, and well "placed". I could use at full scale of measuring, in my case, some uV ...

Using the two inputs (A and B) let one use an x-y joystick, just mounting 2 pots in parallel.

enter image description here

\$\endgroup\$
8
  • \$\begingroup\$ Thank You very much! It's so cool! I will try that. The load cell are those of a beam like tipe for arduino scales for example. \$\endgroup\$
    – Sieben
    Commented Dec 22, 2021 at 12:51
  • 1
    \$\begingroup\$ Ok. I did only use HX711 as a nanoVoltmeter :-) with "noise". Very good as microvoltmeter if one takes a mean of "some" samples. \$\endgroup\$
    – Antonio51
    Commented Dec 22, 2021 at 12:54
  • \$\begingroup\$ as far as i get it, we need a physical access for the load cells on a beam then. And how to make it with this sort of thing, is may be an another story. majju.pk/assets/uploads/2019/03/… \$\endgroup\$
    – Sieben
    Commented Dec 22, 2021 at 13:17
  • 1
    \$\begingroup\$ Is the pcb, one something as this sparkfun.com/products/13879. Anyway, you have access on all pins. Or do you want to use the load cell ... as joystick ? :-) \$\endgroup\$
    – Antonio51
    Commented Dec 22, 2021 at 13:19
  • \$\begingroup\$ Oh, yes. My fault. The pcb is similar. Misunderstood the schematics. ) Like joystick x or y axis. It works but need a center here. \$\endgroup\$
    – Sieben
    Commented Dec 22, 2021 at 13:23

Your Answer

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

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