#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HX711_ADC.h>
// Pin definitions for HX711
const int HX711_dout = 4; // HX711 data pin
const int HX711_sck = 5; // HX711 clock pin
// HX711 constructor
HX711_ADC LoadCell(HX711_dout, HX711_sck);
// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C // OLED I2C address
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // Initialize OLED
// Calibration value for HX711
const int calVal_eepromAdress = 0;
unsigned long t = 0;
void setup() {
Serial.begin(115200); // Start serial communication
delay(10);
Serial.println("Starting...");
// Initialize HX711 load cell
LoadCell.begin();
unsigned long stabilizingtime = 2000;
boolean _tare = true; // Tare the load cell
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
while (1); // Wait forever if HX711 fails
} else {
LoadCell.setCalFactor(1.0); // Calibration factor
Serial.println("Startup is complete");
}
// Initialize OLED
Wire.begin(21, 22); // SDA, SCL pins for ESP32
if (!display.begin(SSD1306_PAGEADDR, OLED_ADDR)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Stay here if initialization fails
}
display.clearDisplay(); // Clear display buffer
display.setTextSize(1); // Set text size
display.setTextColor(SSD1306_WHITE); // Set text color
display.setCursor(0, 0); // Set cursor position
calibrate(); // Start calibration procedure
}
void loop() {
static boolean newDataReady = 0;
const int serialPrintInterval = 0; // Print interval (increase to slow down output)
// Check for new data from HX711
if (LoadCell.update()) newDataReady = true;
if (newDataReady) {
if (millis() > t + serialPrintInterval) {
float weight = LoadCell.getData(); // Get weight from load cell
Serial.print("Load_cell output val: ");
Serial.println(weight);
// Convert weight to points
int points = weightToPoints(weight);
Serial.print("Converted points: ");
Serial.println(points);
// Display data on OLED
display.clearDisplay();
display.setCursor(0, 0); // Reset cursor
display.print("Weight: ");
display.print(weight, 2); // Display weight with 2 decimal places
display.println(" kg");
display.print("Points: ");
display.println(points); // Display converted points
display.display(); // Update OLED display
newDataReady = 0;
t = millis();
}
}
// Handle serial commands
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay(); // Tare load cell
else if (inByte == 'r') calibrate(); // Start calibration
else if (inByte == 'c') changeSavedCalFactor(); // Edit calibration factor
}
// Check if last tare operation is complete
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}
}
void calibrate() {
Serial.println("***");
Serial.println("Start calibration:");
Serial.println("Place the load cell on a level stable surface.");
Serial.println("Remove any load applied to the load cell.");
Serial.println("Send 't' from serial monitor to set the tare offset.");
boolean _resume = false;
while (!_resume) {
LoadCell.update();
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
_resume = true;
}
}
Serial.println("Now, place your known mass on the load cell.");
Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");
float known_mass = 0;
_resume = false;
while (!_resume) {
LoadCell.update();
if (Serial.available() > 0) {
known_mass = Serial.parseFloat();
if (known_mass != 0) {
Serial.print("Known mass is: ");
Serial.println(known_mass);
_resume = true;
}
}
}
LoadCell.refreshDataSet();
float newCalibrationValue = LoadCell.getNewCalibration(known_mass);
Serial.print("New calibration value: ");
Serial.println(newCalibrationValue);
Serial.println("End calibration");
Serial.println("***");
}
void changeSavedCalFactor() {
float oldCalibrationValue = LoadCell.getCalFactor();
boolean _resume = false;
Serial.println("***");
Serial.print("Current value is: ");
Serial.println(oldCalibrationValue);
Serial.println("Send new value from serial monitor.");
float newCalibrationValue;
while (!_resume) {
if (Serial.available() > 0) {
newCalibrationValue = Serial.parseFloat();
if (newCalibrationValue != 0) {
Serial.print("New calibration value: ");
Serial.println(newCalibrationValue);
LoadCell.setCalFactor(newCalibrationValue);
_resume = true;
}
}
}
}
int weightToPoints(float weight) {
// Convert weight (kg) to points
if (weight >= 0 && weight <= 100) {
return (int)(weight * 10); // Example: 1 kg = 10 points
} else {
return 0; // Out of range
}
}