3

I am reading from loadcell and calculating the average of last 10 readings. But when the load cell reads something more than 3800 g the average gets negative, how? The mass I read are not negative numbers. I have been trying to find my mistake but I am not able to. Any help?

#include "HX711.h"

const int numReadings = 10;
const int LOADCELL_DOUT_PIN = 8;
const int LOADCELL_SCK_PIN = 10;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int mass  =0;
long reading = 0;

HX711 scale;

float a = 0.0088;
float b = 2009.7;


void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop() {
  if (scale.is_ready()) {
    // read from the sensor:
    reading = scale.read();
    // convert to mass  
    mass = int((a*reading)-b);
    // subtract the last reading:
    total = total - readings[readIndex];
   
    Serial.print(int((a*reading)-b));
    readings[readIndex] = mass;
    // add the reading to the total:
    total = total + readings[readIndex];
    // advance to the next position in the array:
    readIndex = readIndex + 1;
  
    // if we're at the end of the array...
    if (readIndex >= numReadings) {
      // ...wrap around to the beginning:
      readIndex = 0;
    }
  
    // calculate the average:
    average = total / numReadings;
    // send it to the computer as ASCII digits
    
    Serial.print("   ");
    Serial.print(average);
    Serial.println("");
    delay(1000);        // delay in between reads for stability
  }
  else{
    Serial.print("loadcell not found!");
  }
}
3
  • 7
    It's called "integer wraparound" - int can only hold between -32768 and +32767 on an 8-bit Arduino.
    – Majenko
    Commented Jun 2, 2021 at 12:50
  • Omg, thank you very much for the help. I was struggling with it
    – animos_be
    Commented Jun 2, 2021 at 12:59
  • 3
    tip, if you know that it only should contain positive numbers, declare as an unsigned integer.
    – Swedgin
    Commented Jun 2, 2021 at 14:53

2 Answers 2

2

Another option would be use 'long' as a variable type for total. Depending on your application, you also might look into an exponentially weighted moving average (EWMA); it can de-emphasize older data points, if that is an issue.

0

As already commented by Majenko, the problem in integer wraparound. One solution would be to get rid of that total variable and calculate every new average based on the previous average and the mass you are replacing in the array, using this formula:

new_average = old_average + (mass - readings[readIndex]) / numReadings

So your code would look like:

  if (scale.is_ready()) {
    // read from the sensor:
    reading = scale.read();
    // convert to mass  
    mass = int((a*reading)-b);

    // calculate the new average:
    new_average = average + (mass - readings[readIndex]) / numReadings;
   
    Serial.print(int((a*reading)-b));
    readings[readIndex] = mass;

    // advance to the next position in the array:
    readIndex = readIndex + 1;
  
    // if we're at the end of the array...
    if (readIndex >= numReadings) {
      // ...wrap around to the beginning:
      readIndex = 0;
    }
  
    // set the average:
    average = new_average;

    // send it to the computer as ASCII digits
    Serial.print("   ");
    Serial.print(average);
    Serial.println("");
    delay(1000);        // delay in between reads for stability
  }

Just don't forget to add a declaration for new_average to the beginning of your code.

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.