#include <LiquidCrystal.h>
#include "HX711.h"
#include <math.h> // Needed for exp()
// HX711 pins
#define DT A0
#define SCK A1
// LCD: RS, E, D4, D5, D6, D7
LiquidCrystal lcd(PB0, PB1, PB10, PB11, PB12, PB13);
// Pins for input/output
const int tareButtonPin = PA2;
const int ledPin = PA3;
// HX711 object
HX711 scale;
// Calibration factor
float calibration_factor = 0.3779;
// Offset for drift correction
float offset_correction = 0;
// Exponential scaling parameters
float max_display_weight = 5000.0; // grams (max expected)
float exp_factor = 0.0008; // curve steepness
void setup() {
Serial.begin(9600);
pinMode(tareButtonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
lcd.begin(16, 2);
lcd.print("Weighing Scale");
delay(1500);
lcd.clear();
// HX711 init
scale.begin(DT, SCK);
scale.set_scale(calibration_factor);
scale.tare();
// Capture baseline offset
offset_correction = scale.get_units(10);
lcd.setCursor(0, 0);
lcd.print("Taring...");
delay(1500);
lcd.clear();
Serial.println("Scale ready.");
}
float getWeight() {
float raw = scale.get_units(5); // Average of 5 readings
raw -= offset_correction; // Apply offset
// Dead zone for noise
if (raw < 0.5 && raw > -0.5) raw = 0;
// Exponential scaling (compress large weights, boost small ones)
if (raw > 0) {
raw = max_display_weight * (1.0 - exp(-exp_factor * raw));
}
return raw;
}
void loop() {
// Tare button
if (digitalRead(tareButtonPin) == LOW) {
lcd.setCursor(0, 0);
lcd.print("Taring... ");
scale.tare();
offset_correction = scale.get_units(10);
delay(1500);
lcd.clear();
}
float weight = getWeight();
// LCD Display
lcd.setCursor(0, 0);
lcd.print("Weight: ");
lcd.setCursor(8, 0);
lcd.print(weight, 1);
lcd.print(" g");
// LED indicator
if (weight <= 0.5) {
digitalWrite(ledPin, LOW);
} else {
digitalWrite(ledPin, HIGH);
}
// Debug serial
Serial.print("Weight: ");
Serial.print(weight, 2);
Serial.println(" g");
delay(500);
}