Arduino Uno, HX711, and load cell accuracy factors/equation

Hello all, I am pretty new to Arduino, and am working on a fairly complex project, the hardware is working, more of a variable is my code I think. I will attach a link to explain what I am doing. I am getting close to having the project working, but am having some hiccups on accuracy. I have a load cell (with no data sheet) and I am pretty close on my Cal factor, but the issue I am running into is my load cell will read +/- 5lbs of known weight @ 150-175 lbs one time(which is totally acceptable for me). I remove the load, and I check it again and then I read (normally) 20-40 lbs heavy of the known weight @150-175lbs. I can scale the load in this manner, 6 times, and its a crapshoot which way it will go every time. I also am having an issue with it going back to "0". The sketch I am using is a generic code that I have slightly modified. It seems to take a reading once a second, and therefore the reading is very unstable. I am wondering how to go about making code or logic that it will update the LCD readout once every 5 seconds, but take a reading every second, throw out the outliers/ extremes, and average the rest. I cant have the readout as sensitive as it is now, but need it to show me changes in load fairly quickly.

Recap:

Problem 1: Load cell accuracy - inconsistent load reading from one test to the next

Problem 2: Code to make the readings more stable

The load cell is designed for this exact use on a planter, and I am designing a system that will read the "margin"(see downforce attachment). The hard part is the planter will be moving through the field and as everyone knows, load cells do not particularly like constant changes in load. I am "recreating" a system that is used on newer planters, but mine is too old and the retrofit would be too costly, therefore I am building one myself. My parameters do not need to be accurate, only consistent, as the readout is only telling me the margin is "X", and now it is "Y". There is no magic number, only telling me what it is as row unit weight and soil condition change. If you have any questions on the system/use I will try to explain better.

// Include libraries needed
#include <HX711.h>
#include <Wire.h>  
#include <LiquidCrystal_I2C.h>

//SetHX711 pins
#define DOUT 3
#define CLK 2

//Create HX711 Object
HX711 scale; 

float calibration_factor = -750; // Add Cal factor here 

//Set I2C Address
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int SW = 7;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.backlight();
  scale.begin(DOUT, CLK);
  scale.set_scale(calibration_factor);
  scale.tare();
  Serial.println("Readings:");   
  lcd.setCursor(0,0); //First line
  lcd.print("Roseland Farms");
  lcd.setCursor(0,1); //Second line
  lcd.print("MarginMonitor V1");
  delay(4000) ;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("John Deere");
  lcd.setCursor(0,1);
  lcd.print("7200 12R30");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Initializing....");
  long zero_factor = scale.read_average();
  Serial.print("Zero factor: ");
  Serial.println(zero_factor);
  delay(2000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Ready...");
  delay(4000);
  lcd.clear(); // Need to clear before void loop or LCD will flicker  
}
void loop()
{
  Serial.print("Reading: ");
  Serial.print(scale.get_units(), 1); //scale.get_units() returns a float
  Serial.print(" lbs"); //You can change this to kg but you'll need to refactor the calibration_factor
  Serial.println();
  lcd.setCursor(0,0);
  lcd.print("Margin");
  lcd.setCursor(0,1);
  lcd.print("Reading: ");
  lcd.print(scale.get_units(),1); 
  lcd.setCursor(12,2);
  lcd.print("LBS");
  Serial.print("Reading: "); 
  Serial.print(scale.get_units(), 1); //scale.get_units() returns a float
  Serial.print(" lbs"); 
  Serial.println();
  
}

Downforce.jpg

I am wondering how to go about making code or logic that it will update the LCD readout once every 5 seconds, but take a reading every second, throw out the outliers/ extremes, and average the rest.

Use the "blink without delay" (BWOD) method to update your LCD every x seconds. You could also use that technique to take a weight sample every second, but I'd start out by taking a sample every time through loop() and trying a moving average. You'll have to decide what constitutes an outlier and whether or not to include the value in the average (e.g., you may decide to reject values outside of the range (ax, bx), where x is the current average, a is a number less than 1, and b is a number greater than 1. Looking at a plot of real data may help you select a and b.)

It seems to take a reading once a second.

The HX711 is capable of taking either 10 or 80 samples per second, depending on how the PCB board is designed, provided the other code in loop() doesn't slow it down. (Often the boards are designed to allow the user to change the rate from 10 to 80 or vice versa.) If you use the BWOD technique and only print to serial or the LCD every five seconds, the HX711 could take up to several hundred readings between prints.

inconsistent load reading from one test to the next

I wonder if friction / stiction is an issue in your tests.

This load cell is a few years used from another machine. I opted to use it due to it's price of free, while I get the code built. I would get a new one like it when actually implementing the system. And I would probably use two load cells for more samples. As far as the accuracy, it would show -0.1 to 0.8 lbs with no weight. I will add a picture of how it works tonight. but from the fulcrum point it will actually read negative, but the "zero_scale" should have taken that out i would have thought. Again, I am new to the coding, how would I make or view a data sheet of what it actually sees besides the serial monitor? And how do i implement the "blinkwithoutdelay" method? A sample of the coding would be enough, I could play with it from there.

Regarding BWOD...any of the first few google hits on that subject ought to get you started. Or this...
https://forum.arduino.cc/index.php?topic=503368.0

You didn't answer the implied question about friction possibly making your test results inconsistent. Your image of the mechanism is not helpful. It is not clear how you are conducting your tests. Are there pivot points or sliding surfaces with friction that could affect your tests?

Regarding visualizing your data:

If you are driving down a row and expecting relatively constant values, then you could get a feel for the range by just showing on the LCD the current average, and max and min to-date. That would be the simplest approach.

Alternatively, there are lots of other ways to skin the cat:

If you can use a laptop with the Arduino IDE while doing "real work," then you can inject the data directly into Excel using PLX-DAQ. Or, you could print to the serial monitor and then cut/paste from the serial monitor into a plotting program (such as Excel), or you could use the Arduino IDE's serial plotter tool and watch the most recent 500 samples stream by "live."

If a laptop isn't available and you have an Android phone or tablet, you could try the Android app "ArduinoDroid" and see if you can cut/paste data from its serial monitor (never tried it myself).

If you can't use a laptop or a 'droid, then you could save the data to a microSD card and play with the numbers later. MicroSD card breakout board+ : ID 254 : $7.50 : Adafruit Industries, Unique & fun DIY electronics and kits

Or, if wifi is available in a test field, you could ditch the UNO, use an ESP8266, and stream the data to, say, ThingSpeak. Or save to the ESP's large internal memory (called SPIFFS).

Or, you could use a pair of radios (e.g., RFM96, or 315 MHz, or 434 MHz) to transmit the data to another Arduino that can print the data on your desktop computer's serial monitor or into Excel via PLX-DAQ.

Or, use a bluetooth module to stream the data to your phone or tablet.

For a beginner the sd card approach may be easiest.

As far as the friction of some sort, I do not believe that to be an issue, or at least not enough to make that much of a difference. The load cell picture is attached. The red dot is the pivot point, the load is applied at the green arrow, and the "tee handle" at the yellow arrows fits into notches to keep from pivoting.

Thanks, but it is not clear how the load cell is loaded in your tests or during normal operation.

I'm guessing that the "H" shaped piece at the right end (what you are calling the "tee" handle) is not touching and free to move relative to the large flat green plate below it, and that something not shown pushes or pulls on the "H" in a direction parallel to the "web" of the "H". Guessing.

Need more context to understand the system. Post more close-up photos of the area around the load cell (similar to the one you posted but from different angles), overall photos showing the entire mechanism from different angles, and photos of the system with a test load.

And please read and follow the guidance in the following link on how to embed photos in your post so every interested viewer doesn't have to download them one by one: Simple guide for inserting images in a post - Website and Forum - Arduino Forum Like this:

BTW, pinning down a range outside of which you exclude outliers may be difficult (and perhaps not worth doing), since I bet running a disk (or whatever it is) at depth through soil will generate a large range of values due to varying soil properties and soil-machine interaction dynamics; that is, it may be difficult to decide what is an outlier and what is a "normal" value. It would be interesting to see some test data.