Created
August 20, 2025 14:52
-
-
Save fxprime/1b4273910dc8d116782fe42df22e8f67 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include "HX711.h" | |
#include <Preferences.h> | |
// HX711 circuit wiring | |
#define LOADCELL_DOUT_PIN 27 | |
#define LOADCELL_SCK_PIN 26 | |
HX711 scale; | |
Preferences preferences; | |
float calibration_factor = 1.0; | |
const int num_samples = 3; | |
float known_weights[num_samples]; | |
long raw_readings[num_samples]; | |
void waitForUserInput(const char* prompt, float* value) { | |
Serial.println(prompt); | |
while (Serial.available()) Serial.read(); // clear buffer | |
while (true) { | |
if (Serial.available()) { | |
String input = Serial.readStringUntil('\n'); | |
input.trim(); | |
*value = input.toFloat(); | |
if (*value > 0) break; | |
Serial.println("Invalid input. Please enter a positive number:"); | |
} | |
delay(100); | |
} | |
} | |
void waitForUserConfirm(const char* prompt) { | |
Serial.println(prompt); | |
Serial.println("Type 'y' and press Enter to continue..."); | |
while (Serial.available()) Serial.read(); // clear buffer | |
while (true) { | |
if (Serial.available()) { | |
String input = Serial.readStringUntil('\n'); | |
input.trim(); | |
if (input.equalsIgnoreCase("y")) break; | |
Serial.println("Please type 'y' and press Enter to confirm."); | |
} | |
delay(100); | |
} | |
} | |
void setup() { | |
Serial.begin(115200); | |
while (!Serial) delay(10); | |
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); | |
preferences.begin("hx711", false); | |
float calib = preferences.getFloat("calib", 0.0); | |
Serial.print("[DEBUG] Read calibration factor from preferences: "); | |
Serial.println(calib, 6); | |
bool hasCalib = calib != 0.0 && !isnan(calib); | |
if (hasCalib) { | |
Serial.print("Found calibration factor in preferences: "); | |
Serial.println(calib, 6); | |
Serial.println("Type 'y' and press Enter to recalibrate, 's' to show raw data, or any other key to skip calibration."); | |
while (Serial.available()) Serial.read(); // clear buffer | |
bool doCalib = false; | |
while (true) { | |
if (Serial.available()) { | |
String input = Serial.readStringUntil('\n'); | |
input.trim(); | |
if (input.equalsIgnoreCase("y")) { | |
doCalib = true; | |
break; | |
} else if (input.equalsIgnoreCase("s")) { | |
Serial.println("\n--- RAW LOADCELL DATA MODE ---"); | |
Serial.println("Press any key to exit raw data mode."); | |
while (true) { | |
if (Serial.available()) { | |
Serial.readStringUntil('\n'); | |
break; | |
} | |
long raw = scale.read(); | |
Serial.print("Raw: "); | |
Serial.println(raw); | |
delay(500); | |
} | |
Serial.println("Exiting raw data mode.\n"); | |
Serial.println("Type 'y' and press Enter to recalibrate, or any other key to skip calibration."); | |
while (Serial.available()) Serial.read(); // clear buffer | |
continue; | |
} else { | |
break; | |
} | |
} | |
delay(100); | |
} | |
if (!doCalib) { | |
Serial.println("Skipping calibration. Using saved calibration factor."); | |
preferences.end(); | |
waitForUserConfirm("Remove all weight from scale. Ready to tare?"); | |
scale.tare(); | |
Serial.println("Tare done."); | |
return; | |
} | |
Serial.println("Proceeding with calibration..."); | |
} else { | |
Serial.println("No calibration factor found. Calibration is required."); | |
Serial.println("Type 's' and press Enter to show raw data for loadcell test, or any other key to continue."); | |
while (Serial.available()) Serial.read(); // clear buffer | |
bool showRaw = false; | |
while (true) { | |
if (Serial.available()) { | |
String input = Serial.readStringUntil('\n'); | |
input.trim(); | |
if (input.equalsIgnoreCase("s")) showRaw = true; | |
break; | |
} | |
delay(100); | |
} | |
if (showRaw) { | |
Serial.println("\n--- RAW LOADCELL DATA MODE ---"); | |
Serial.println("Press any key to exit raw data mode."); | |
while (true) { | |
if (Serial.available()) { | |
Serial.readStringUntil('\n'); | |
break; | |
} | |
long raw = scale.read(); | |
Serial.print("Raw: "); | |
Serial.println(raw); | |
delay(500); | |
} | |
Serial.println("Exiting raw data mode.\n"); | |
} | |
} | |
Serial.println("HX711 scale calibration"); | |
waitForUserConfirm("Remove all weight from scale. Ready to tare?"); | |
scale.tare(); | |
Serial.println("Tare done."); | |
for (int i = 0; i < num_samples; i++) { | |
Serial.print("\nPlace known weight sample #"); | |
Serial.print(i + 1); | |
Serial.println(" on the scale."); | |
waitForUserConfirm("When ready, confirm to take measurement."); | |
raw_readings[i] = scale.get_units(15); // filtered average | |
Serial.print("Raw reading: "); | |
Serial.println(raw_readings[i]); | |
waitForUserInput("Enter the actual weight in grams:", &known_weights[i]); | |
Serial.print("Recorded: "); | |
Serial.print(known_weights[i]); | |
Serial.println(" g"); | |
waitForUserConfirm("Remove the weight and confirm to continue to next sample."); | |
} | |
// Calculate calibration factor (average of all samples) | |
float sum_factor = 0; | |
for (int i = 0; i < num_samples; i++) { | |
if (known_weights[i] > 0) { | |
sum_factor += (float)raw_readings[i] / known_weights[i]; | |
} | |
} | |
calibration_factor = sum_factor / num_samples; | |
Serial.print("\nCalibration factor calculated: "); | |
Serial.println(calibration_factor, 6); | |
waitForUserConfirm("Save calibration factor to preferences?"); | |
bool ok = preferences.putFloat("calib", calibration_factor); | |
Serial.print("[DEBUG] preferences.putFloat returned: "); | |
Serial.println(ok ? "true" : "false"); | |
preferences.end(); // Ensure preferences are saved and closed | |
Serial.print("[DEBUG] Saved calibration factor: "); | |
Serial.println(calibration_factor, 6); | |
Serial.println("Calibration factor saved to preferences."); | |
Serial.println("Restart the device to use the calibrated scale."); | |
} | |
void loop() { | |
// After calibration, you can use the calibration factor as follows: | |
preferences.begin("hx711", false); // open in read/write mode for compatibility | |
float calib = preferences.getFloat("calib", 1.0); | |
Serial.print("[DEBUG] loop() read calibration factor: "); | |
Serial.println(calib, 6); | |
preferences.end(); | |
float calib_abs = fabs(calib); | |
scale.set_scale(calib_abs); | |
float weight = scale.get_units(10); | |
if (calib < 0) weight = -weight; | |
Serial.print("Weight: "); | |
Serial.print(weight, 2); | |
Serial.println(" g"); | |
delay(1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment