#include <Arduino.h>
#include "HX711.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ---------------- Pin map ----------------
#define HX711_DOUT_PIN 32
#define HX711_SCK_PIN 33
#define RED_LED_PIN 21
#define BTN_PIN 26
#define I2C_SDA_PIN 4
#define I2C_SCL_PIN 15
#define LCD_I2C_ADDR 0x27 // Common I2C address (try 0x3F if no display)
// ---------------- Objects ----------------
HX711 scale;
LiquidCrystal_I2C lcd(LCD_I2C_ADDR, 16, 2);
// ---------------- Inventory params ----------------
float calibration_factor = -7050.0f; // adjust during calibration
const float item_unit_weight_kg = 25.0f; // weight per bag
const int low_stock_threshold_bags = 2; // threshold
unsigned long lastWeightMillis = 0;
// LED blink control
bool lowStockState = false;
unsigned long lastBlinkMillis = 0;
const unsigned long blinkInterval = 500; // ms
bool ledOn = false;
// Button debounce
unsigned long lastBtnMillis = 0;
const unsigned long btnDebounce = 250;
bool lastBtnState = HIGH;
void setup() {
Serial.begin(115200);
delay(200);
// LCD init
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Inventory System");
lcd.setCursor(0,1);
lcd.print("Initializing...");
delay(1500);
lcd.clear();
// HX711 init
scale.begin(HX711_DOUT_PIN, HX711_SCK_PIN);
scale.set_scale(calibration_factor);
scale.tare();
Serial.println("HX711 initialized and tared.");
// LED + button
pinMode(RED_LED_PIN, OUTPUT);
digitalWrite(RED_LED_PIN, LOW);
pinMode(BTN_PIN, INPUT_PULLUP);
Serial.println("Setup complete.");
}
float readFilteredWeightKg(int samples = 5) {
if (!scale.is_ready()) return 0.0;
float w = scale.get_units(samples);
if (fabs(w) < 0.01) w = 0.0;
return w;
}
int getBagsFromWeight(float weightKg) {
int bags = (int) round(weightKg / item_unit_weight_kg);
return (bags < 0 ? 0 : bags);
}
void updateLCD(float weightKg, int bags) {
lcd.setCursor(0,0);
char line1[17];
snprintf(line1, 17, "Wt:%6.1f kg", weightKg);
lcd.print(line1);
lcd.setCursor(0,1);
if (bags <= low_stock_threshold_bags) {
lcd.print("Status: LOW STOCK ");
} else {
char line2[17];
snprintf(line2, 17, "Stock:%2d bag(s) ", bags);
lcd.print(line2);
}
}
void handleLowStockLed(bool low) {
if (low) {
unsigned long now = millis();
if (now - lastBlinkMillis >= blinkInterval) {
lastBlinkMillis = now;
ledOn = !ledOn;
digitalWrite(RED_LED_PIN, ledOn ? HIGH : LOW);
}
} else {
digitalWrite(RED_LED_PIN, LOW);
ledOn = false;
}
}
void loop() {
// Pushbutton simulates RFID scan
bool btnState = digitalRead(BTN_PIN);
if (btnState == LOW && lastBtnState == HIGH && (millis() - lastBtnMillis) > btnDebounce) {
lastBtnMillis = millis();
Serial.println("=== Simulated RFID SCAN ===");
Serial.println("ItemID: RICE_25KG_001");
Serial.print("Timestamp: ");
Serial.println(millis()/1000);
Serial.println("===========================");
}
lastBtnState = btnState;
// Weight reading every 1s
if (millis() - lastWeightMillis > 1000) {
lastWeightMillis = millis();
float weightKg = readFilteredWeightKg(5);
int bags = getBagsFromWeight(weightKg);
updateLCD(weightKg, bags);
Serial.print("Weight: ");
Serial.print(weightKg, 2);
Serial.print(" kg ~ ");
Serial.print(bags);
Serial.println(" bag(s)");
lowStockState = (bags <= low_stock_threshold_bags);
}
handleLowStockLed(lowStockState);
}