2

I am making a 50kg weighing scale using HX711 ADC. My project includes Atmega328 along with 74HC595 for driving 5 7segment displays(multiplexed). I am using the function scale.get_units()to fetch the data and the values are very well displayed on the 7segments. The problem I am facing is the readings on the 5th digit (right most 1's) are unstable. Now, if I use scale.read_average(5), my display scanning gets slow. I was wondering if there is a way to average the readings in a loop like the conventional way. I tried it but with no luck! It keeps showing random added numbers. Any help would be highly appriciated. Below is the code inside the loop. Let me know if full code is needed. Thanx in advance!

if (scale.is_ready()) {
 weight = scale.get_units();
 finalWeight = weight * 1000;
}
for (int i = 0; i < 10 ;i++) {
 sum += finalWeight;
}
average = sum / 10;
if (average < 0) {
 break_number(0);
} else {
 break_number(average);
}
display_number();
delay(1);
Edgar Bonet
45.1k4 gold badges42 silver badges81 bronze badges
asked Jun 21, 2023 at 8:07

1 Answer 1

1

First of all, this code:

for (int i = 0; i < 10 ;i++) {
 sum += finalWeight;
}
average = sum / 10;

does not average multiple readings. Instead, it takes the single reading stored in finalWeight, multiplies it by ten (by means of successive additions), then divides it by ten to get back the same value.

If you want to reduce the noise, you have to take multiple readings and average them. The reading-taking code must thus be inside the loop. A simple option may be like this:

void loop() {
 sum = 0;
 for (int i = 0; i < 10; i++) {
 while (!scale.is_ready()) {} // wait for the scale to be ready
 sum += scale.get_units();
 }
 weight = sum / 10; // compute the average
 display(weight); // and display it
}

Note that I have simplified things a bit by removing the scaling factors. You can take this as simple inspiration and adapt to your specific needs.

The code above has one problem though: as the code is blocking while waiting for the scale to be ready, the display is not refreshed. You could fix this by explicitly refreshing the display within the waiting loop:

void loop() {
 sum = 0;
 for (int i = 0; i < 10; i++) {
 while (!scale.is_ready()) { // wait...
 display(weight); // ...while refreshing the display
 }
 sum += scale.get_units();
 }
 weight = sum / 10;
 display(weight);
}

This should work, but I would however suggest instead a third approach: write non-blocking code. This is code that never blocks: instead, if something can be done right now, it does it. If not, it moves along:

void loop() {
 if (scale.is_ready()) { // if something useful can be done NOW:
 sum += scale.get_units();
 count++;
 if (count >= 10) {
 weight = sum / count; // update the value to be displayed
 sum = 0; // reset the averaging variables
 count = 0;
 }
 }
 display(weight); // unconditionally refresh the display
}

This way, your loop() always runs fast, and you can add code that will not be blocked by the stuff you wrote earlier.

Edit: As suggested by chrisl in a comment, a moving average may better serve your needs. I would try the exponentially-weighted version, as it is lightweight and simpler to implement. You may want to explore this path.

answered Jun 21, 2023 at 9:24
2
  • 1
    In addition: Here a moving average might be a good choice, like in the second answer to this question Commented Jun 21, 2023 at 9:26
  • Thanx a lot!! I will try it. Commented Jun 22, 2023 at 3:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.