#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "HX711.h"
// ---------------- LCD Setup ----------------
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ---------------- Keypad Setup ----------------
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','+'}, // '+' used for Spoon Addition
{'4','5','6','T'}, // 'T' = Tare Button
{'7','8','9','U'}, // 'U' = Units Setting
{'C','0','=','O'} // 'O' = Tolerance On/Off
};
byte rowPins[ROWS] = {13, 12, 14, 27};
byte colPins[COLS] = {26, 25, 33, 32};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ---------------- Load Cell Setup ----------------
HX711 scale;
#define DT 4 // HX711 DT pin
#define SCK 5 // HX711 SCK pin
float calibration_factor = -7050.0; // Adjust for your load cell
float targetWeight = 0;
float tolerance = 0.5;
bool toleranceOn = false;
// ---------------- Units ----------------
enum Unit {GRAM, KG, OUNCE, POUND, ML, FLOZ};
Unit currentUnit = GRAM;
const char* unitNames[] = {"g", "kg", "oz", "lb", "ml", "fl oz"};
float unitFactor[] = {1.0, 0.001, 0.035274, 0.00220462, 1.0, 0.033814};
// ml & fl oz require density assumption (for water-like liquids)
// ---------------- Variables ----------------
float cumulativeWeight = 0;
bool spoonAdditionMode = false;
// ---------------- Setup ----------------
void setup() {
Serial.begin(115200);
// LCD init
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Digital Spoon");
delay(2000);
lcd.clear();
lcd.print("Initializing...");
// HX711 init
scale.begin(DT, SCK);
scale.set_scale(calibration_factor);
scale.tare();
lcd.clear();
lcd.print("Ready. Press key");
}
// ---------------- Main Loop ----------------
void loop() {
char key = keypad.getKey();
if (key) {
handleKeypad(key);
}
// Display live reading
float weight = getWeight();
lcd.setCursor(0, 1);
lcd.print(weight, 2);
lcd.print(" ");
lcd.print(unitNames[currentUnit]);
}
// ---------------- Functions ----------------
float getWeight() {
float raw = scale.get_units();
return raw * unitFactor[currentUnit];
}
void handleKeypad(char key) {
switch (key) {
case '+': // Spoon addition
spoonAdditionMode = true;
cumulativeWeight += getWeight();
lcd.clear();
lcd.print("Added Spoon");
delay(1000);
showCumulative();
break;
case 'T': // Tare
scale.tare();
lcd.clear();
lcd.print("Tare Done");
delay(1000);
break;
case 'U': // Change Units
currentUnit = (Unit)((currentUnit + 1) % 6);
lcd.clear();
lcd.print("Unit: ");
lcd.print(unitNames[currentUnit]);
delay(1000);
break;
case 'O': // Toggle Tolerance
toleranceOn = !toleranceOn;
lcd.clear();
if (toleranceOn) lcd.print("Tolerance ON");
else lcd.print("Tolerance OFF");
delay(1000);
break;
case '=': // Finalize / Show result
lcd.clear();
if (spoonAdditionMode) {
showCumulative();
} else {
lcd.print("Final: ");
lcd.print(getWeight(), 2);
lcd.print(" ");
lcd.print(unitNames[currentUnit]);
}
delay(3000);
lcd.clear();
lcd.print("Ready. Press key");
spoonAdditionMode = false;
cumulativeWeight = 0;
break;
case 'C': // Clear / Reset
cumulativeWeight = 0;
lcd.clear();
lcd.print("Cleared");
delay(1000);
lcd.clear();
lcd.print("Ready. Press key");
break;
}
}
void showCumulative() {
lcd.clear();
lcd.print("Total: ");
lcd.print(cumulativeWeight, 2);
lcd.print(" ");
lcd.print(unitNames[currentUnit]);
}