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.
#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 ?
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.
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;
}
}