// main.ino
#include <LiquidCrystal_I2C.h> // Library for controlling an I2C LCD
#include <HX711.h> // Library for interfacing with the HX711 load cell amplifier
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 2; // Data pin of the HX711
const int LOADCELL_SCK_PIN = 3; // Clock pin of the HX711
const int RESET_BUTTON_PIN = 5; // Button pin for user interaction
// Calibration factors
long empty_container = 0; // Stores the reading of the empty container
long one_liter_weight = 0; // Stores the reading of the container with 1L water
float calibration_factor = 1.0f; // Derived calibration factor for converting readings to weight
// LCD setup
#define I2C_ADDR 0x27 // I2C address of the LCD
#define LCD_COLUMNS 16 // Number of columns on the LCD
#define LCD_LINES 2 // Number of lines on the LCD
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES); // LCD object
HX711 scale; // HX711 object
void setup() {
Serial.begin(57600); // Initialize serial communication for debugging
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); // Initialize HX711 with the specified pins
lcd.init(); // Initialize the LCD
lcd.backlight(); // Turn on the LCD backlight
pinMode(RESET_BUTTON_PIN, INPUT); // Set the button pin as input
// Calibration phase: Measure the weight of the empty container
lcd.setCursor(0, 0);
lcd.print("Calibrate:");
lcd.setCursor(0, 1);
lcd.print("Place Empty");
Serial.println("Place empty container and press the button.");
// Wait for button press to confirm empty container reading
waitForButtonPress();
while (!scale.is_ready()); // Wait until the scale is ready
empty_container = scale.read(); // Store the reading of the empty container
Serial.println("Empty container weight saved.");
lcd.clear(); // Clear the screen after empty container calibration
// Calibration phase: Measure the weight of the container with 1L water
lcd.print("Add 1L Water"); // Prompt user to place 1L water
lcd.setCursor(0, 1);
lcd.print("Press Button");
Serial.println("Add 1L of water and press the button.");
// Wait for button press to confirm 1L water reading
waitForButtonPress();
while (!scale.is_ready()); // Wait until the scale is ready
one_liter_weight = scale.read(); // Store the reading with 1L water
calibration_factor = one_liter_weight - empty_container; // Calculate the calibration factor
Serial.println("Calibration completed.");
lcd.clear(); // Clear the screen after 1L water calibration
lcd.print("Calib. Done!");
delay(2000);
lcd.clear(); // Clear the screen after showing calibration completion
lcd.setCursor(0, 0);
lcd.print("Ready..."); // Indicate readiness to begin measurement
delay(2000);
lcd.clear(); // Clear the screen after readiness message
}
void loop() {
lcd.setCursor(0, 0); // Set cursor to the top left
lcd.print("Weight:"); // Display the "Weight" label
if (scale.is_ready()) { // Check if the HX711 is ready for a reading
long reading = scale.read(); // Get the raw reading from the HX711
float weight = (float)(reading - empty_container) / calibration_factor; // Calculate the weight
// Check for overload condition
if (weight > 5.0) {
lcd.clear(); // Clear the screen before displaying overload
Serial.println("Weight Overload!"); // Debugging log for overload
lcd.setCursor(0, 1); // Set cursor to the second line
lcd.print("Overload!"); // Display overload warning
}
// Check for warning condition (near the weight limit)
else if (weight >= 4.5) {
lcd.clear(); // Clear the screen before displaying near-limit warning
Serial.println("Warning: Near limit!"); // Debugging log for near-limit warning
// Format and display the weight
char weightStr[16];
dtostrf(weight, 6, 2, weightStr); // Convert float to string with 2 decimals
lcd.setCursor(0, 1);
lcd.print(weightStr);
lcd.print(" kg");
// Display the near-limit warning at the top line
lcd.setCursor(0, 3);
lcd.print("**Near Limit**");
}
// Normal weight display
else {
Serial.print("Weight: ");
Serial.println(weight, 2); // Debugging log for weight
// Format and display the weight
char weightStr[16];
dtostrf(weight, 6, 2, weightStr); // Convert float to string with 2 decimals
lcd.setCursor(0, 1);
lcd.print(" "); // Clear old value
lcd.setCursor(0, 1);
lcd.print(weightStr);
lcd.print(" kg");
}
} else {
lcd.clear(); // Clear the screen before showing error
Serial.println("HX711 not ready."); // Debugging log for error
lcd.setCursor(0, 1);
lcd.print("Error: No HX711"); // Display error on the LCD
}
// Handle reset button press
if (digitalRead(RESET_BUTTON_PIN) == HIGH) {
lcd.clear(); // Clear the screen before starting taring process
lcd.setCursor(0, 1);
lcd.print("Taring..."); // Indicate taring process
delay(1000);
empty_container = scale.read(); // Update the empty container reading for taring
lcd.clear(); // Clear the screen after taring is done
lcd.print("Reset Done"); // Indicate that taring is complete
delay(2000);
lcd.clear(); // Clear the screen after reset message
}
delay(100); // Short delay to prevent rapid updates
}
// Function to wait for the user to press the reset button
void waitForButtonPress() {
while (digitalRead(RESET_BUTTON_PIN) == LOW) {
// Wait for the button to be pressed
}
delay(500); // Debounce delay
}