Weight sensing delayed, data not calculating properly

Hello, I'm doing a project in school and the exhibit for it is the next day. I'm writing to get help with my problem in the system. First of all, when you put the input in the system, the load cell should immediately get the weight and sort it if it's lighter or heavier, but as I am experiencing, it does not. In the coin counting portion, the system is also struggling to calculate even with the limited number of data values. What should I do?
Here's my code for reference:

#include <LiquidCrystal_I2C.h>
#include <HX711_ADC.h>
#include <Wire.h>
#include <Stepper.h>
#include <Servo.h>
#define BUTTON_PIN 12

HX711_ADC LoadCell(2, 3);
int capasensor = A0;
int value;
Servo myservo1;
Servo myservo2;
LiquidCrystal_I2C lcd(0x27, 20, 4);
int IRSensor = A2;
unsigned int buttonStatus = LOW;
const int stepsPerRevolution = 300;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
enum { Start,
       FullBin,
       NotFullBin,
       Metal,
       Paper,
       Plastic,
       CoinCount,
       CoinRelease };
unsigned char RVMState;

void setup() {
  Serial.begin(9600);
  myservo1.attach(5);  //load cell servo
  myservo1.write(180);
  myservo2.attach(13);  //coin servo
  pinMode(BUTTON_PIN, INPUT);
  pinMode(capasensor, INPUT);
  myStepper.setSpeed(30);
  LoadCell.begin();
  LoadCell.start(2000);
  LoadCell.setCalFactor(600);
  lcd.begin();
  lcd.backlight();
  delay(1000);
}
void loop() {
  int binStatus = digitalRead(IRSensor);
  int cycle = 1;
  int data1 = 0;
  int data2 = 0;
  int data3 = 0;
  int data4 = 0;
  int data5 = 0;
  int data6 = 0;
  int data7 = 0;
  int data8 = 0;
  int data9 = 0;
  int data10 = 0;
  int coinCount = 0;
  int coin = 0;
  int pos = 0;
  int count = 0;
  int howmanycoin = 0;
  switch (RVMState) {
    case Start:
      Serial.println("START");
      lcd.setCursor(0, 0);
      lcd.print("Please wait!");
      delay(1000);
      lcd.setCursor(0, 1);
      lcd.print("Checking bins...");
      delay(1000);
      if (digitalRead(IRSensor) == 0) {  //if Irsensor sensed something
        RVMState = FullBin;
        break;
      } else {  //Irsensor did not detect something
        RVMState = NotFullBin;
        break;
      }

    case FullBin:  //Stay until machine turned off
      Serial.println("FullBin");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(">>Bin is Full<<");
      delay(1000);
      lcd.setCursor(0, 1);
      lcd.print("Please empty the");
      delay(1000);
      lcd.setCursor(0, 2);
      lcd.print("bins or contact");
      delay(1000);
      lcd.setCursor(0, 3);
      lcd.print("Customer Service...");
      delay(2000);
      break;

    case NotFullBin:
      lcd.clear();
      Serial.println("NotFullBin");
      lcd.setCursor(0, 0);
      lcd.print(">>Bin is Ready<<");
      delay(500);
      lcd.setCursor(0, 1);
      lcd.print("Please insert trash!");
      delay(500);
      lcd.setCursor(0, 2);
      lcd.print("Press the button");
      delay(500);
      lcd.setCursor(0, 3);
      lcd.print("if d-o-n-e!");
      delay(5000);
      LoadCell.update();
      if (digitalRead(BUTTON_PIN) == HIGH) {  //for counting coins
        Serial.println("pushed");
        RVMState = CoinCount;
        break;
      }
      if (digitalRead(capasensor) == 1) {  //for metal
        RVMState = Metal;
        break;
      }
      if (digitalRead(capasensor) == 0) {    //no metal
        if (abs(LoadCell.getData()) <= 4) {  //no trash
          break;
        }
        if (abs(LoadCell.getData()) > 4) {     //may trash
          if (abs(LoadCell.getData()) > 15) {  //plastic
            Serial.println(abs(LoadCell.getData()));
            RVMState = Plastic;
            break;
          } else {  //paper
            Serial.println(weight);
            RVMState = Paper;
            break;
          }
        }

        case Metal:
          Serial.println("MetalState");
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Please wait");
          delay(1000);
          lcd.setCursor(0, 1);
          lcd.print("a moment...");
          lcd.setCursor(0, 2);
          lcd.print("Weight (g):");
          delay(1000);
          lcd.setCursor(0, 3);
          lcd.print(abs(LoadCell.getData()));
          Serial.println("Metal");
          LoadCell.update();
          if (cycle == 1) {
            data1 = abs(LoadCell.getData());
          }
          if (cycle == 2) {
            data2 = abs(LoadCell.getData());
          }
          if (cycle == 3) {
            data3 = abs(LoadCell.getData());
          }
          if (cycle == 4) {
            data4 = abs(LoadCell.getData());
          }
          if (cycle == 5) {
            data5 = abs(LoadCell.getData());
          }
          if (cycle == 6) {
            data6 = abs(LoadCell.getData());
          }
          if (cycle == 7) {
            data7 = abs(LoadCell.getData());
          }
          if (cycle == 8) {
            data8 = abs(LoadCell.getData());
          }
          if (cycle == 9) {
            data9 = abs(LoadCell.getData());
          }
          if (cycle == 10) {
            data10 = abs(LoadCell.getData());
            cycle = 0;
          }
          cycle = cycle + 1;
          myservo1.write(0);
          delay(15);
          myservo1.write(180);
          delay(15);
          LoadCell.update();
          RVMState = NotFullBin;
          break;

        case Paper:
          Serial.println("PaperState");
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Please wait");
          delay(1000);
          lcd.setCursor(0, 1);
          lcd.print("a moment...");
          LoadCell.update();
          lcd.setCursor(0, 2);
          lcd.print("Weight (g):");
          delay(1000);
          lcd.setCursor(0, 3);
          lcd.print(abs(LoadCell.getData()));
          Serial.println("Paper");
          Serial.println("clockwise");
          if (cycle == 1) {
            data1 = abs(LoadCell.getData());
          }
          if (cycle == 2) {
            data2 = abs(LoadCell.getData());
          }
          if (cycle == 3) {
            data3 = abs(LoadCell.getData());
          }
          if (cycle == 4) {
            data4 = abs(LoadCell.getData());
          }
          if (cycle == 5) {
            data5 = abs(LoadCell.getData());
          }
          if (cycle == 6) {
            data6 = abs(LoadCell.getData());
          }
          if (cycle == 7) {
            data7 = abs(LoadCell.getData());
          }
          if (cycle == 8) {
            data8 = abs(LoadCell.getData());
          }
          if (cycle == 9) {
            data9 = abs(LoadCell.getData());
          }
          if (cycle == 10) {
            data10 = abs(LoadCell.getData());
            cycle = 0;
          }
          cycle = cycle + 1;
          myStepper.step(stepsPerRevolution);
          delay(2000);
          myservo1.write(0);
          delay(15);
          delay(2000);
          myservo1.write(180);
          delay(15);
          Serial.println("counter clockwise");
          myStepper.step(-stepsPerRevolution);
          LoadCell.update();
          RVMState = NotFullBin;
          break;

        case Plastic:
          Serial.println("PlasticState");
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Please wait");
          delay(1000);
          lcd.setCursor(0, 1);
          lcd.print("a moment...");
          lcd.setCursor(0, 2);
          lcd.print("Weight (g):");
          delay(1000);
          lcd.setCursor(0, 3);
          lcd.print(abs(LoadCell.getData()));
          Serial.println("Plastic");
          Serial.println("counter clockwise");
          if (cycle == 1) {
            data1 = abs(LoadCell.getData());
          }
          if (cycle == 2) {
            data2 = abs(LoadCell.getData());
          }
          if (cycle == 3) {
            data3 = abs(LoadCell.getData());
          }
          if (cycle == 4) {
            data4 = abs(LoadCell.getData());
          }
          if (cycle == 5) {
            data5 = abs(LoadCell.getData());
          }
          if (cycle == 6) {
            data6 = abs(LoadCell.getData());
          }
          if (cycle == 7) {
            data7 = abs(LoadCell.getData());
          }
          if (cycle == 8) {
            data8 = abs(LoadCell.getData());
          }
          if (cycle == 9) {
            data9 = abs(LoadCell.getData());
          }
          if (cycle == 10) {
            data10 = abs(LoadCell.getData());
            cycle = 0;
          }
          cycle = cycle + 1;
          myStepper.step(-stepsPerRevolution);
          delay(1000);
          myservo1.write(0);
          delay(15);
          delay(2000);
          myservo1.write(180);
          delay(15);
          Serial.println("clockwise");
          myStepper.step(stepsPerRevolution);
          LoadCell.update();
          RVMState = NotFullBin;
          break;

        case CoinCount:  //adding all weight divided by 15
          Serial.println("CountingCoin");
          coin = data1 + data2 + data3 + data4 + data5 + data6 + data7 + data8 + data9 + data10;
          coinCount = coin / 15;
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Please wait");
          delay(1000);
          lcd.setCursor(0, 1);
          lcd.print("a moment...");
          lcd.setCursor(0, 2);
          lcd.print("Coins:");
          lcd.setCursor(0, 3);
          lcd.print(coinCount);
          Serial.println("coin:");
          Serial.println(coinCount);
          RVMState = CoinRelease;
          break;


        case CoinRelease:  //1 count 1 centavo
          Serial.println("ReleasingCoin");
          howmanycoin = coinCount;
          if (coinCount > 0) {
            for (pos = 0; pos <= 180; pos += 1) {
              myservo2.write(pos);
              delay(15);
            }
            for (pos = 180; pos >= 0; pos -= 1) {
              myservo2.write(pos);
              delay(15);
            }
            coinCount = coinCount - 1;
            Serial.println("Coin: ");
            Serial.println(coinCount);
            delay(2000);
            break;
          } else if (coinCount == 0) {
            for (pos = 0; pos <= 0; pos += 1) {
              myservo2.write(pos);
              delay(1000);
              count = 0;
            }
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Coins obtained");
            delay(1000);
            lcd.setCursor(0, 1);
            lcd.print("(in 25-centavos):");
            delay(1000);
            lcd.setCursor(0, 2);
            lcd.print(howmanycoin);
            delay(1000);
            lcd.setCursor(0, 3);
            lcd.print("Thank you!");
            delay(2000);
            RVMState = Start;
            break;
          }
        default:
          Serial.println("Process Done");
          delay(2000);
          RVMState = Start;
          break;
      }
  }
}

ps.
I'm using the absolute value of the load cell data as I am getting negative values instead of positive values, not a good alternative but it works fine as no weight is getting left behind.
Disclaimer:
I'm new in coding and was forced to do it for the project, any help would be great. Thanks!

You've got a lot of delays in there, so "immediately" looks to be a tough call.

I'd junk that code, and start again.

Example sketches in the HX711 library will show how to calibrate the scale (tare). Maybe this is why you have negative weight values.

Most delays are put for good countermeasure from the long wait it takes to update the load cell, and some are just needed for the LCD and motors. Should I remove them all? Whenever I remove them though, the commands woosh and run quickly and I can't keep up, the lcd displays also dont last and come and go after a quick time.

I'm actually using the examples in HX711, the load cell is perfectly calibrated and working too, it resets to zero every time. I believe I messed up in the orientation of the sensor somehow but I don't think it's gonna make much of a difference.

Ah. That makes sense on the negative values.

I read this in the library github:

The HX711 sample rate can be set to 10SPS or 80SPS (samples per second) by pulling pin 15 high (80SPS) or low (10SPS)

[edit] I think you should use type float for raw values returned by the loadcell. Maybe the "negative" values are when the type int is overflowed? This link

1 Like

The negative values aren't really the problem, the load cell still gets the right weight, but on negative value, that's actually why I used the absolute value of it in every case. I just really need to solve how and why there is a delay of some sort, as it sometimes doubles the cycles happening because of it.

Your code is too long.
Every time you see a variable that is the same as another, except for the last digit, it's time to look at using arrays.
Maybe even simpler than that, since all you appear to be doing is summing for an average, is to do just that - sum 'n' readings, and divide by 'n'.

I'm not really doing an average as I'm using 15 as a constant value and I'm not sure I understand how I can use array sums with my system.

I just read in the HX711 library git...

The library is usually used in blocking mode, i.e. it will wait for the hardware becoming available before returning a reading.

I read this as "if the load-cell is changing..." and found their example of "non-blocking" here.

1 Like

The comments don't really make clear what the intent was

I put your project in a simulator, and have some comments...

  • if the button is not pressed, the program continues to the next object (maybe have the program wait for a button press?)
  • You wait for button press HIGH, rather than LOW, and set the button pin to INPUT... I would set the pin to INPUT_HIGH and wait for button LOW.
  • The delay() statements make the button-pressing difficult to time (must hold the button for five seconds).
  • What action causes the motor to engage?
  • A delay of 15 milliseconds is not long enough to let the servo move before returning it home.
1 Like

For the first comment, the system is supposed to be like that, you should be able to put 10 data values at most and then added later on then divided to 15. Second, the button seems to be working in my project though, but I'll consider that too. Third, the 5 sec delay was added to help with the delay on the reading of the loadcell, but I'll try removing it too. Fourth, the servo motor is supposed to move as it is connected to the chamber which falls down if the object's weight is done getting read. Lastly, the 15 ms also has been working for me and still makes a 180° angle though. Thanks for the feedback!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.