Loadcell with HX711

I am using the HX711 Library to obtain readings from a Loadcell.
This works great and I get accurate readings.
I am using a Serial Event routine that calls a sub routing "getMass()" to read the value from the HX711.
This works great when there is a weight on the loadcell when getMass() is called, but does not read any value if the weight is placed on the loadcell after getMass() is called.
I need to be able to call getMass() and then place the weight on the loadcell.
How can I create a "loop" (or similar) within the getMass() code that will allow me to accomplish this.

My Code:

void getMass(){
    float myVal = scale.get_units(10);
    massScale = myVal + .5;
    massScale = round(massScale);
    
    if (massScale > .5){
    Serial.println(myVal);
    Serial.println(massScale);
    }
}

Please post your complete program so that the function can be seen in context.

Why not call getMass(), or the relevant part of it, only when there is a weight on the load cell ?

Here is my complete sketch:

#include "HX711.h"


String stringSerial = "";         // a string to hold incoming Serial data
boolean stringSerialComplete = false;  // whether the string is complete

HX711 scale(A1, A0);
int massScale;

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  stringSerial.reserve(200);
  
  scale.set_scale(232.f);  // this value is obtained by calibrating the scale with known weights
  scale.tare();	
}

void loop() // run over and over
{
// Serial Input Data
  if (stringSerialComplete) {
//    Serial.println(stringSerial);  // Debug
      
      if (stringSerial.startsWith("b")) {  // Start Scale
        getMass(); 
      }
      
      if (stringSerial.startsWith("c")) {  // Calibrate Scale
        scale.set_scale(); 
        scale.tare();
        scale.get_units(10);
        Serial.println(scale.get_units(10), 1);
      }
      
      stringSerial = "";
      stringSerialComplete = false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    stringSerial += inChar;
    if (inChar == '\n') {
      stringSerialComplete = true;
    }
  }
}

void getMass(){
    float myVal = scale.get_units(10);
    massScale = myVal + .5;
    massScale = round(massScale);
    
    if (massScale > .5){
    Serial.println(myVal);
    Serial.println(massScale);
    }
}

Why not call getMass(), or the relevant part of it, only when there is a weight on the load cell ?

That would be perfect

That would be perfect

Then why not do it ? Read the load cell each time through loop() then, if the value it returns varies significantly call a function to measure the weight. Do you even need serial input to start the measurement ?

While you are refactoring the code, remove the serialEvent() function and just check if serial input is available.

You will almost certainly be better off not using Strings as well as you are only looking to recognise when a 'c' has been entered in order to calibrate the scale. Does it actually calibrate it or just set the tare weight ?

Then why not do it ? Read the load cell each time through loop() then, if the value it returns varies significantly call a function to measure the weight

How - I am a novice when it comes to programming.

Do you even need serial input to start the measurement ?

Yes, the final sketch will communicate with an Android Tablet which will send serial data to tell the Arduino what function to fulfill - later there will additional peripherals performing various functions.

remove the serialEvent() function

Ok, will do.

You will almost certainly be better off not using Strings as well as you are only looking to recognise when a 'c' has been entered in order to calibrate the scale. Does it actually calibrate it or just set the tare weight ?

This function "c" is only used once on the initial setup calibration and sets the tare.

Some pseudo code for you

declare and initialise variables
set pin modes etc

start of loop()
  previous weight equals current weight
  read the load cell
  if the weight is significantly higher than last time it was read
    call the function to read the weight
  end if

  if serial characters available
    call the function to evaluate them
  end if
end of loop()

function to get weight
  //code here
end of function

function to deal with serial input
  read serial input
  parse serial input
  act on serial input if appropriate
end of function

Thanks UKHeliBob, I have the following sketch that works:

#include "HX711.h"


String stringSerial = "";         // a string to hold incoming Serial data
boolean stringSerialComplete = false;  // whether the string is complete

HX711 scale(A1, A0);
int massNew;
int massOld;
int massFinal;

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  stringSerial.reserve(200);
  
  scale.set_scale(232.f);  // this value is obtained by calibrating the scale with known weights
  scale.tare();	
}

void loop() // run over and over
{
    massOld = massNew;
    float myVal = scale.get_units(5);
    massNew = myVal + .5;
    massNew = round(massNew);
   
    if (massNew > massOld){
      getMass();
    }

  if (stringSerialComplete) {
      
    // I don't require this anymore - scale control is "automatic"
//      if (stringSerial.startsWith("b")) {  // Start Scale
//        getMass();  
//      }
      
      if (stringSerial.startsWith("c")) {  // Calibrate Scale
        scale.set_scale(); 
        scale.tare();
        scale.get_units(10);
        Serial.println(scale.get_units(10), 1);
      }
      
      stringSerial = "";
      stringSerialComplete = false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    stringSerial += inChar;
    if (inChar == '\n') {
      stringSerialComplete = true;
    }
  }
}

void getMass(){
    float myVal = scale.get_units(5);
    massFinal = myVal + .5;
    massFinal = round(massFinal);
    
    if (massFinal > 3){  // I need this as there is a slight drift from 0 to 3 that seems temperature related
      if (massFinal == massNew){
        Serial.print("Mass Final: ");
        Serial.println(massFinal);
      }
    }

}

I don't know if there is anything that needs "cleaning-up"?

Declan:
I am using a Serial Event routine that calls a sub routing “getMass()” to read the value from the HX711.
This works great when there is a weight on the loadcell when getMass() is called, but does not read any value if the weight is placed on the loadcell after getMass() is called.

Well, no. If your operator hits the “read the weight!” button, and they haven’t put the weight on the scale yet, of course the scale is going to read zero!

Sounds like what you need is to keep reading that scale until the weight is a) nonzero and b) has settled down to a consistent value.

enum State {
  IDLE = 0,
  READING = 1,
  DISPLAYING = 2
} state = IDLE;

void loop() {
  switch(state) {
  case IDLE:
    if we have a serial event,
    state = READING;
    break;

  case READING:
    if it's been less than 10ms since we last read the weight
      do nothing
    else
      read the weight, 
      stuff it into a rolling buffer of (say) 20 readings
      if all the values in the rolling buffer are above minimum weight and within tolerance of one another
        put the weight on the display
        state = DISPLAYING;
      end if;
    end if;
    break;

  case DISPLAYING:
    read the weight.
    if the weight is much less than the display weight
      clear the display
      state = IDLE;
    end if;
  }
}

Thanks Paul, but my programming knowledge doesn't allow me to turn your pseudo code into real code :confused: