Weight sensor - buzzer problem

Hey guys, I am trying to do a different kinda a digital scale. The things that I have are:
-load cell (10kg)
-HX711
-buzzer
-led
-LCD screen
-button
-Arduino mega

You see what I want is when I put a weight bigger than 100gr I want my led and my buzzer to work. Moreover, while the buzzer is still working I am gonna press the button for 5 seconds, this way the buzzer will stop working BUT the led will keep working. ( If the weight is smaller than 100gr led and the buzzer wont work )

The problems I have:

  • -when I put a weight bigger than 100 my led and buzzer work fine. But I can't seem to find a way to work my button.

  • I do have issues with the calibration, the LCD screen do prints negative numbers. I am pretty sure it's not giving me the correct outcomes. BUT my priority right now is to get the button to work.

And if you have any ideas for me to improve my digital scale please let me know :blush:

Here is my code

#include <HX711_ADC.h>  
#include <Wire.h>
#include <LiquidCrystal_I2C.h> 

HX711_ADC LoadCell(45, 43); 
LiquidCrystal_I2C lcd(0x27, 16,2); 
const int buzzerPin = 41;
const int buttonPin = 39; 

bool buzzerState = false; // Track the state of the buzzer (on/off)
bool buttonPressed = false;
unsigned long buttonPressStartTime = 0;

void setup() 
{
  LoadCell.begin(); 
  LoadCell.start(2000); // load cells gets 2000ms of time to stabilize
  LoadCell.setCalFactor(1000.0); // calibration factor for load cell 
  lcd.begin(); 
  lcd.backlight();
  pinMode(53,OUTPUT);
  pinMode(buzzerPin, OUTPUT);
   pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {

  LoadCell.update(); 
  float i = LoadCell.getData(); 
  lcd.setCursor(0, 0); 
  lcd.print("Weight[g]:"); 
  lcd.setCursor(0, 1); 
  lcd.print(i); 
  if(i>100){
    digitalWrite(53,HIGH);
    digitalWrite(41,HIGH);
    buzzerState = true;
  } else {
    // Turn off LED and buzzer
    digitalWrite(53, LOW);
    digitalWrite(buzzerPin, LOW);
    buzzerState = false;
  }

  // Button functionality
  if (digitalRead(buttonPin) == LOW) {
    // Button is pressed
    if (!buttonPressed) {
      buttonPressed = true;
      buttonPressStartTime = millis();
    }

    // If the button has been pressed for 5 seconds, turn off the buzzer
    if (buttonPressed && (millis() - buttonPressStartTime >= 5000) && buzzerState) {
      digitalWrite(buzzerPin, LOW);
      buzzerState = false;
    }
  } else {
    // Button is released
    buttonPressed = false;
  }
}

THX. From here under the umbrella the code looks plausible.

There is, however, a possibility that contact bounce is messing with your algorithm.

Quick test - throw a delay(20); in to your loop function. It can be the first or the last line of code. This would be an easy if crude test. I think it would remove the bounce issue from the problem.

I'll try to remember later in the lab to take a more careful look.

a7

Hey thanks a lot it worked. I added the delay (20); to beginning of my loop function.
But I do still have a problem. I pressed the button for more than 5 seconds. I did check the seconds that had passed. When it was 5 seconds the buzzer stopped working. After like couple of seconds more I remove my finger from the button and the buzzer started to work again.

How can I make it stop working after I remove my finger from the button? (After I already press the button for 5 seconds)

Your liquid crystal initialization looks like a mix of I2C and SPI.

For example: SPI

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
void setup() {
  lcd.begin(16, 2);
 }

For example: I2C

#include <LiquidCrystal_I2C.h>
#define I2C_ADDR    0x27
#define LCD_COLUMNS 20
#define LCD_LINES   2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
void setup() {
  lcd.init();

its I2C

Okay. I believe that would use:

lcd.init();

Yes. Read your code. The loop comes around again, everything is quiet, but the mass on the scale is still greater then 100, so it kicks the hole thing off again.

What you need to do is to make a flag variable.

The way to handle this is simple bit a bit too much for where I am at just now. Or how sober I am.

I'll check later to see if anyone 'splains how to do something once, and when to reset the fact that you did something so you will be able to do it again.

I'm making it sound harder than it is.

L8R

a7

Thanks a lot, I will be expecting to hear from you :slight_smile:
and if I will find a way to do what are you saying, I will respond with the working version

I really dont think so. "lcd.begin" works for me everytime. Whenever I try to check "lcd.init" it gives me error.
For example:

C:\Users\hp\Desktop\weight\arduino_weight\arduino_weight.ino: In function 'void setup()':
C:\Users\hp\Desktop\weight\arduino_weight\arduino_weight.ino:21:7: error: 'class LiquidCrystal_I2C' has no member named 'init'

exit status 1

Compilation error: 'class LiquidCrystal_I2C' has no member named 'init'

What @alto777 is talking about is "state change detection". You only want to start the buzzer when the scale reading moves from <=100 to >100 and not every time it is >100. I'm not familiar with this hardware but depending on how stable the reading is you could simply save the last reading every time through loop. When the last reading is 100 or less and the current reading is greater than 100 then your "state" has changed. You could add an additional step to make sure the reading stays above 100 for a specific amount of time after the state changes and only then start the buzzer.

L8R first:

OK, I fixed my code. I still don't know what I did wrong, but this shows plain state change detection:

Wokwi_badge Scale Thing


What I got wrong: failure to initialiase a local variable.

Earlier:

@ToddL1962 is correct.

I had a few different things in mind. I'd share some code just now, but I have to admit I have had trouble getting 20 lines of code to do what I mean, not what I wrote. I so hate when that happens.

But "state change detection" is def a way to go.

Perhaps it is better to hold off on code anyway <cough!>. As I was trying to write a simple state change detector, it occurred to me that I'm not sure how to reset the scale.

If you take the weight off, should the beeping and buzzing stop?

If the weight is ~100, then fluctuations in the reading will make the LED flicker and the buzzer make croaking noises. If you are turning them on and off rapidly because the reading is not stable.

So you need to decide exaclty how it will work, not thinking about code at all.

A possibility is that an alarm condition is raised if the weight is over 100, and obtains until the weight goes below, say, 20. With the slight additional idea that the pushbutton held for five seconds will kill the sound but leave the alarm light.

Or the alarm condition persists (with or without sound) until some other reset condition is arrived. Say an additional pushbutton that kills the sound and the LED.

Anyway, you can learn about two things without wasting any time. Good stuff:

One. In the IDE, look at Examples/02.Digital/StateChangeDetection.

and google

 state change detection Arduino

or leave off Arduino. Poke around to see the idea presented in several hundred ways.

Two. google

 hysteresis 

or add on Arduino. Again, poke around - hysteresis is a very few basic concept - we all familiar with it in one way or another, but mightn't have seen it named or exposed formally.

In the case of state change detection, the examples will focus, probably, on a changing digital signal, e.g. "when the switch becomes pressed".

So you have to translate to your circumstances. The digital value you can use to detect the changing state of could just be true or false, is the weight over 100 or not.

@ToddL1962 also mentions maybe waiting a few cycles to be sure that someone is really or has finished putting weight on the pan.

a7

1 Like

you guys suggestions worked thank you very much @ToddL1962 @alto777

I do have 1 more question for you guys. When I power up my project, even tho there is no weight on the load censor lcd screen prints things like "-0.188, 0.200, -0.250" Is there a way to make that outcome 0 until an actual weight is on top of the load censor?

You could cheat and just not publish any numbers you don't want to see.

But this is a scale, is it not calibrated at some point and thereafter report only zero and positive weights on the pan?

In any case, it would be good at this point to post the code you are almost happy with. This will help,us, help others who may be following along and help anyone who comes across this thread in the future with anything like a similar problem.

a7

here is my current code:

#include <HX711_ADC.h> 
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

HX711_ADC LoadCell(45, 43); 

const int buzzerPin = 41;
const int buttonPin = 39; 
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64 

bool buzzerState = false; 
bool buttonPressed = false;
unsigned long buttonPressStartTime = 0;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() 
{
  LoadCell.begin(); 
  LoadCell.start(1000); 
  LoadCell.setCalFactor(-230); setup
 
  pinMode(53,OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
  display.clearDisplay();
}
void loop() {
  // put your main code here, to run repeatedly:
  
  LoadCell.update(); // retrieves data from the load cell
  float i = LoadCell.getData(); // get output value
  float displayWeight = max(0, i);
  display.clearDisplay();
  display.setTextColor(WHITE); 
  display.setTextSize(3.2);
  display.setCursor(15,21);
  display.print(displayWeight);
  display.display();
  if(i>10){
    digitalWrite(53,HIGH);
    digitalWrite(41,HIGH);
    buzzerState = true;
  } else {
    // Turn off LED and buzzer
    digitalWrite(53, LOW);
    digitalWrite(buzzerPin, LOW);
    buzzerState = false;
  }

  // Button functionality
  if (digitalRead(buttonPin) == LOW) {
    // Button is pressed
    if (!buttonPressed) {
      buttonPressed = true;
      buttonPressStartTime = millis();
    }

    // If the button has been pressed for 5 seconds, turn off the buzzer
    if (buttonPressed && (millis() - buttonPressStartTime >= 2000) && buzzerState) {
      digitalWrite(buzzerPin, LOW);
      buzzerState = false;
    }
  } else {
    // Button is released
    buttonPressed = false;
  }
}

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