// Scale for https://forum.arduino.cc/t/how-do-you-get-a-weight-value-stored-in-the-eeprom/1113399/11
#define CodeVersion "Code-Version 010"
// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
#define dbg(myFixedText, variableName) \
Serial.print(F(#myFixedText " " #variableName "=")); \
Serial.println(variableName);
#define dbgi(myFixedText, variableName, timeInterval) \
{ \
static unsigned long intervalStartTime; \
if (millis() - intervalStartTime >= timeInterval) { \
intervalStartTime = millis(); \
Serial.print(F(#myFixedText " " #variableName "=")); \
Serial.println(variableName); \
} \
}
#define dbgc(myFixedText, variableName) \
{ \
static long lastState; \
if (lastState != variableName) { \
Serial.print(F(#myFixedText " " #variableName " changed from ")); \
Serial.print(lastState); \
Serial.print(F(" to ")); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
#define dbgcf(myFixedText, variableName) \
{ \
static float lastState; \
if (lastState != variableName) { \
Serial.print(F(#myFixedText " " #variableName " changed from ")); \
Serial.print(lastState); \
Serial.print(F(" to ")); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *
#include <HX711_ADC.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <U8g2lib.h>
#if defined(ESP8266) || defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define Y_POS_0 0
#define X_POS_0 0
#define Y_POS_10 10
#define X_POS_10 10
#define TEXT_SIZE_SMALL 1
#define TEXT_SIZE_MED 2
#define TEXT_SIZE_LARGE 3
#define LONG_DELAY 4000
#define MED_DELAY 2000
#define SHORT_DELAY 1000
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
//Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
//pins:
//OLED USES I2C -> ON ARDUINO UNO: SCL @ A5, SDA @ A4
const int HX711_dout = 4; //mcu > HX711 dout pin
const int HX711_sck = 5; //mcu > HX711 sck pin
//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);
const int calVal_eepromAdress = 0;
const int tareOffsetVal_eepromAdress = 4;
unsigned long t = 0;
void PrintFileNameDateTime() {
Serial.println(CodeVersion);
Serial.println(F("Code running comes from file "));
Serial.println(F(__FILE__));
Serial.print(F(" compiled "));
Serial.print(F(__DATE__));
Serial.print(F(" "));
Serial.println(F(__TIME__));
}
void HX711_setup() {
//SETUP LOAD CELLS
LoadCell.begin();
Serial.println(F("LoadCell.begin() done"));
//LoadCell.setReverseOutput();
float calibrationValue;
//20.9 // calibration value (see example file "Calibration.ino")
#if defined(ESP8266) || defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom
Serial.println(F("EEPROM.get(calVal_eepromAdress done"));
dbg("1:", calVal_eepromAdress);
dbg("2:", calibrationValue);
if (calibrationValue == 0.0) {
calibrationValue = 1.0;
Serial.println(F("calibrationValue == 0.0 set to 1.0"));
}
dbg("nan", isnan(calibrationValue));
if ((isnan(calibrationValue) == 1)) {
Serial.println(F("calibrationValue nan set to 2.0"));
calibrationValue = 2.0*10.500/50;
}
dbg(F("finally"), calibrationValue);
//restore the zero offset value from eeprom:
long tare_offset = 0;
EEPROM.get(tareOffsetVal_eepromAdress, tare_offset);
Serial.println(F("EEPROM.get(tareOffsetVal_eepromAdress, tare_offset) done"));
dbg("3:", tareOffsetVal_eepromAdress);
dbg("4:", tare_offset);
if (tare_offset == 0) {
tare_offset = 10;
}
dbg("finally", tare_offset);
LoadCell.setTareOffset(tare_offset);
Serial.println(F("LoadCell.setTareOffset(tare_offset) done"));
unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
LoadCell.start(stabilizingtime, false);
if (LoadCell.getTareTimeoutFlag()) {
Serial.println(F("Timeout, check MCU>HX711 wiring and pin designations"));
while (1)
;
} else {
LoadCell.setCalFactor(calibrationValue); // set calibration value (float)
Serial.println(calibrationValue);
Serial.println(F("HX771-Startup is complete"));
}
}
void OLED_Setup() {
//SETUP OLED
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
;
}
/*
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
; // Don't proceed, loop forever
}
*/
Serial.println(F("if (!display.begin( done"));
// Clear the buffer
display.clearDisplay();
Serial.println(F("display.clearDisplay() done"));
// Draw a single pixel in white
Serial.println(F("start printing to display"));
display.clearDisplay();
display.setTextSize(TEXT_SIZE_SMALL);
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(Y_POS_0, X_POS_0); // Start at top-left corner
display.println(F("watermelons 2023")); //customize your own start screen message
display.println(F("\nInitializing"));
display.display();
Serial.println(F("printing to display done"));
delay(SHORT_DELAY);
}
void setup() {
Serial.begin(115200);
Serial.println(F("Serial.begin(115200) done delay(2000)"));
delay(2000);
Serial.println();
Serial.println(F("Starting..."));
PrintFileNameDateTime();
OLED_Setup();
HX711_setup();
Serial.println(F("exiting setup()"));
}
void setDisplayParameters(int cursorPosY, int cursorPosX, int textSize) {
//Serial.println( F("entering setDisplayParameters()") );
display.clearDisplay();
display.setTextSize(textSize);
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(cursorPosY, cursorPosX); // Starting point of display
//Serial.println( F("exiting setDisplayParameters()") );
}
void displayWeightInLBs(float weightInGrams, int cursorPosY, int cursorPosX, int size, int delayTime) {
//Serial.println( F("entering displayWeightInKGs()") );
setDisplayParameters(cursorPosY, cursorPosX, size);
float weight = weightInGrams / 453.592;
if (weight < 0) {
weight = 0.00;
}
String weightInKGs = String(weight);
display.println(weightInKGs);
display.display();
//delay(delayTime);
//Serial.println(F("exiting displayWeightInKGs()") );
}
void loop() {
//GET VALUES FROM LOAD CELLS
float value = 0.0;
static boolean newDataReady = 0;
const int serialPrintInterval = 2000; //increase value to slow down serial print activity
// Check for user input from the serial monitor
if (Serial.available() > 0) {
char input = Serial.read();
if (input == 't') {
LoadCell.tare();
Serial.print("Tare complete with:");
Serial.print(LoadCell.getTareOffset());
Serial.print(" Calibration:");
Serial.println(LoadCell.getCalFactor(),5);
}
if (input == 'w') {
long tare_offset = LoadCell.getTareOffset();
EEPROM.put(calVal_eepromAdress, LoadCell.getCalFactor());
EEPROM.put(tareOffsetVal_eepromAdress, LoadCell.getTareOffset());
Serial.println("Tare and calibration written to EEPROM");
}
}
// check for new data/start next conversion:
uint8_t updateResult;
updateResult = LoadCell.update();
if (updateResult) {
dbgi(F("LCUupdated"), updateResult, 1000);
newDataReady = true;
} else {
dbgi(F("LCUdidnt"), updateResult, 1000);
}
// get smoothed value from the dataset:
if (newDataReady) {
if (millis() - t >= serialPrintInterval) {
float value = LoadCell.getData();
//Serial.print( F("Load_cell output val: ") );
Serial.println(value);
//DISPLAY VALUE ON THE OLED
displayWeightInLBs(value, Y_POS_10, X_POS_10, TEXT_SIZE_LARGE, SHORT_DELAY);
newDataReady = false;
t = millis();
}
}
}