hi guys, my project is a sensitive digital scale. After I power up my project I randomly put something that is 6gr(it could be 22gr too the number doesn't matter) on the scale. And then I am gonna press a button for 5 seconds. after i remove my finger from it the OLED screen is gonna display "6gr reference weight". So from now on if I remove the weight from the scale or put something lighter or heavier than reference weight, for 1 minute a led will blink. after that 1 minute if the reference weight isn't on the scale the buzzer will work for a minute too. For shutting the buzzer the user must press the button for 3 seconds or the scale must have the reference weight.
Components:
-load cell 10kg
-HX711
-Button (for determining the reference weight and shutting the buzzer )
-On/off button
-Buzzer
-OLED screen
-Arduino nano
Problem:
It doesn't get the reference weight when I press the button for 5 seconds so I can't even tell if my code for led and buzzer work?
I recently worked on a similar project to this. But can seem to find my way through coding on this one
Here is my code I know its a mess:
#include <HX711_ADC.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
HX711_ADC LoadCell(10, 9);
const int buzzerPin = 12;
const int buttonPin = 5;
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
bool referenceSet = false;
bool buzzerState = false;
bool buttonPressed = false;
unsigned long buttonPressStartTime = 0;
unsigned long lastWeightChangeTime = 0;
const long LED_BLINK_INTERVAL = 60000; // 1 minute in milliseconds
const long BUZZER_INTERVAL = 60000; // 1 minute in milliseconds
float referenceWeight = 0.0; // User-defined reference weight
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
LoadCell.begin();
LoadCell.start(2000);
LoadCell.setCalFactor(-230);
pinMode(7, OUTPUT); // LED pin
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();
display.setTextSize(1.2);
display.setTextColor(BLACK, WHITE);
display.setCursor(0, 5);
display.println(" Put the");
display.println(" reference");
display.println(" weight");
display.display();
// Wait for the user to set the reference weight
while (!referenceSet) {
LoadCell.update();
float weight = max(0, LoadCell.getData());
display.setTextSize(2);
display.setCursor(20, 30);
display.print(weight);
display.display();
if (digitalRead(buttonPin) == LOW) {
referenceWeight = weight;
referenceSet = true;
delay(1000); // Wait for a moment to release the button
}
}
display.clearDisplay();
display.setTextSize(1.2);
display.setTextColor(BLACK, WHITE);
display.setCursor(3, 5);
display.println(" Reference");
display.println(" weight");
display.setTextSize(2);
display.setCursor(20, 30);
display.print(referenceWeight);
display.display();
delay(2000);
}
void loop() {
LoadCell.update();
float weight = max(0, LoadCell.getData());
display.clearDisplay();
display.setTextSize(1.2);
display.setTextColor(BLACK, WHITE);
display.setCursor(3, 5);
display.println(" Project ");
display.println();
display.setTextColor(WHITE);
display.setTextSize(3.2);
display.setCursor(15, 21);
display.print(weight);
display.display();
// Check if the weight is within the tolerance range of the reference weight (e.g., 0.5g)
if (abs(weight - referenceWeight) <= 0.5) {
digitalWrite(7, LOW); // Turn off LED
digitalWrite(buzzerPin, LOW); // Turn off buzzer
buzzerState = false;
lastWeightChangeTime = millis();
} else {
// Check if the weight has changed and start the timer
if (weight != referenceWeight) {
lastWeightChangeTime = millis();
}
// Check if the weight has been out of range for more than 1 minute and activate LED and buzzer
if (millis() - lastWeightChangeTime >= LED_BLINK_INTERVAL) {
digitalWrite(7, HIGH); // Turn on LED
if (!buzzerState) {
digitalWrite(buzzerPin, HIGH); // Turn on buzzer
buzzerState = true;
}
}
// Button functionality
if (digitalRead(buttonPin) == LOW) {
// Button is pressed
if (!buttonPressed) {
buttonPressed = true;
buttonPressStartTime = millis();
}
// If the button has been pressed for 3 seconds, turn off the buzzer
if (buttonPressed && (millis() - buttonPressStartTime >= 3000) && buzzerState) {
digitalWrite(buzzerPin, LOW);
buzzerState = false;
lastWeightChangeTime = millis(); // Reset the timer to prevent immediate activation of the buzzer
digitalWrite(7, LOW); // Turn off LED
}
} else {
// Button is released
buttonPressed = false;
}
}
Sure I (and very very likely the other quoted users) know of ways to the solution. Though my understanding of this forum is not for delivering ready to use code.
You have posted a pretty good description of the wanted functionality.
As in most applications you need to execute multiple tasks in "parallel"
This requires non-blocking timing.
And your application overall can be solved with a state-machine.
If you have any specific questions ask them here in the forum.
Read the linked tutorials and then ask specific questions.
hey, thanks a lot for the sources. I have been looking into them for the past few days. I solved the referenced weight issue. When I press the button for 3 seconds it captures the weight.
I do have a specific question for you. I tried one of your sources about the led blinking but I couldn't implement on it in my code, I mean in my opinion my code seems fine but when I run it nothing happens.
When I press the button for 3 seconds it captures the referenced weight, when I put something heavier than the referenced weight on top of the scale the led isnt blinking even tho I believe I code it right. Maybe I made a mistake with a curly bracelet? I am not sure. I can't seem to fix it. Can you help me please? I have been working on this for days
Heres the part about the led:
if (referenced && displayWeight > itWeight) {
// Blink the LED and turn on the buzzer if current weight is greater
static unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 500) { // Blink every 500ms
previousMillis = currentMillis;
digitalWrite(7, !digitalRead(7)); // Toggle the LED state
}
}
else {
digitalWrite(7, LOW); // Turn off the LED
}
and the code itself:
#include <HX711_ADC.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
HX711_ADC LoadCell(10, 9); // parameters: dt pin 6, sck pin 7;
const int buttonPin = 5;
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
int ledPin = 7;
bool manualBuzzerOff = false;
bool buttonPressed = false;
bool referenced = false; // To indicate if the reference weight is captured
unsigned long buttonPressStartTime = 0;
float itWeight = 0; // Variable to store the reference weight
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup()
{
LoadCell.begin();
LoadCell.start(2000);
LoadCell.setCalFactor(-230);
pinMode(7,OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(2000);
display.clearDisplay();
}
void loop() {
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(36,21);
display.print(displayWeight,1);
// Button functionality
if (digitalRead(buttonPin) == LOW) {
// Button is pressed
if (!buttonPressed) {
buttonPressed = true;
buttonPressStartTime = millis();
}
// If the button has been pressed for 3 seconds, capture the reference weight
if (buttonPressed && (millis() - buttonPressStartTime >= 3000)) {
itWeight = displayWeight;
referenced = true; // Indicate that reference weight is captured
buttonPressed = false;
}
}
else {
// Button is released
if (buttonPressed && referenced) {
// Display referenced weight on OLED
display.clearDisplay();
display.setTextSize(1.2);
display.setTextColor(WHITE);
display.setCursor(0, 5);
display.println("Referenced weight=");
display.print(itWeight, 1);
display.display();
delay(3000);
}
buttonPressed = false;
referenced = false; // Reset the reference weight flag
}
// Compare the current weight to the "it weight" and control the LED
if (referenced && displayWeight > itWeight) {
// Blink the LED and turn on the buzzer if current weight is greater
static unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 500) { // Blink every 500ms
previousMillis = currentMillis;
digitalWrite(7, !digitalRead(7)); // Toggle the LED state
}
}
else {
digitalWrite(7, LOW); // Turn off the LED
}
}
Hi, thank you for taking your time to respond to me. HX711_ADC LoadCell(10, 9); // parameters: dt pin 6, sck pin 7; that comment is not valid. I forgot to delete it after changing the pins.
I deleted this line from my code buttonPressed = false; and it worked. When I put something heavier than referenced weight the led blinks.
This is like the first step of my project I still need to figure out the 2nd and 3rd:
if I remove the weight from the scale or put something lighter or heavier than reference weight, for 1 minute a led will blink.
After that 1 minute if the reference weight isn't on the scale the buzzer will work for a minute too.
For shutting the buzzer the user must press the button for 3 seconds or the scale must have the reference weight.*
I know, not where you come from. I know not what your mother calls them. I know there are other valid, legal, proper, popular and widely used names for those common characters.
I do think, however, that when the subject is C or C++, that the real names (!) should be used.
For what you call your 2nd and 3rd step in your project there is only one step to learn
learning how state-machines work
all in all you have more than two conditions. Whenever you have more than two conditions that make up sequences
a good way to write code for such sequences is to use a state-machine
Your process is
set reference weight
if any weight is on the scale
check if a button is pressed for 5 seconds which means take a snapshot of time and
measure how much time goes by while the button is pressed down
when button is pressed down for more than 5 seconds use this weight as reference weight
and show message on display
operation after defining reference-weight
check if reference-weight is on the scale
if a different weight is measured make a snapshot of time
and measure how much time goes by while weight is different
if more than one minute has passed by
switch on LED
if more than two minutes have passed by make snapshot of time and
turn on buzzer
check if more than 1 minute has passed by since buzzer was switched on
if more than 1 minute have passed by switch buzzer of
all in all 7 different things. You could say 7 different states.
You can code this by using many many if-elseif-elseifelseifelseif-elses
creating a big mess where to set which flag-variable true or false
Or you learn how state-machines work and once you have learned it
you never will go back to if-elseif-elseif-elseif-
The state-machine will be very easy to modify and very easy to maintain
once you have understood the basic principle.
You have avoided to already use a state-machine.
I really recommend that you are learning it