Compilation error / variable not declared

I am using the HX711_ADC Library to read the value(s) of four load cells connected in a full bridge running with an UNO R4 WiFi board. After a little troubleshooting and searching, I resolved a couple problems from previous posts on this forum so I have done some homework.

The basic 'Testing' example provided with the library works as expected after some problems were resolved (Yay Me). The 'Calibration' example however has 2 problems, one which I solved but the other I simply am not knowledgeable enough with coding to work out.

I get the following error when attempting to verify the code

C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026017-19192-1x68z0a.p3wb\Calibration\Calibration.ino: In function 'void loop()':
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026017-19192-1x68z0a.p3wb\Calibration\Calibration.ino:83:29: error: 'changeSavedCalFactor' was not declared in this scope
     else if (inByte == 'c') changeSavedCalFactor();  //edit calibration value manually
                             ^~~~~~~~~~~~~~~~~~~~
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026017-19192-1x68z0a.p3wb\Calibration\Calibration.ino: In function 'void calibrate()':
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026017-19192-1x68z0a.p3wb\Calibration\Calibration.ino:176:35: error: a function-definition is not allowed here before '{' token
       void changeSavedCalFactor() {
                                   ^
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026017-19192-1x68z0a.p3wb\Calibration\Calibration.ino:224:7: error: expected '}' at end of input
       }
       ^
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026017-19192-1x68z0a.p3wb\Calibration\Calibration.ino:224:7: error: expected '}' at end of input
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026017-19192-1x68z0a.p3wb\Calibration\Calibration.ino:224:7: error: expected '}' at end of input
exit status 1

Compilation error: 'changeSavedCalFactor' was not declared in this scope

Here is the full code. Not I already commented out a section that referenced the EEPROM since it appears this particular use of code is not compatable with the UNO R4 WiFi.

/*
   -------------------------------------------------------------------------------------
   HX711_ADC
   Arduino library for HX711 24-Bit Analog-to-Digital Converter for Weight Scales
   Olav Kallhovd sept2017
   -------------------------------------------------------------------------------------
*/

/*
   This example file shows how to calibrate the load cell and optionally store the calibration
   value in EEPROM, and also how to change the value manually.
   The result value can then later be included in your project sketch or fetched from EEPROM.

   To implement calibration in your project sketch the simplified procedure is as follow:
       LoadCell.tare();
       //place known mass
       LoadCell.refreshDataSet();
       float newCalibrationValue = LoadCell.getNewCalibration(known_mass);
*/

#include <HX711_ADC.h>
#if defined(ESP8266) || defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif

//pins:
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;
unsigned long t = 0;

void setup() {
  Serial.begin(57600);
  delay(10);
  Serial.println();
  Serial.println("Starting...");

  LoadCell.begin();
  //LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive
  unsigned long stabilizingtime = 2000;  // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
  boolean _tare = false;                 //set this to false if you don't want tare to be performed in the next step
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1)
      ;
  } else {
    LoadCell.setCalFactor(1.0);  // user set calibration value (float), initial value 1.0 may be used for this sketch
    Serial.println("Startup is complete");
  }
  while (!LoadCell.update())
    ;
  calibrate();  //start calibration procedure
}

void loop() {
  static boolean newDataReady = 0;
  const int serialPrintInterval = 1;  //increase value to slow down serial print activity

  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
      float i = LoadCell.getData();
      Serial.print("Load_cell output val: ");
      Serial.println(i);
      newDataReady = 0;
      t = millis();
    }
  }

  // receive command from serial terminal
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();       //tare
    else if (inByte == 'r') calibrate();             //calibrate
    else if (inByte == 'c') changeSavedCalFactor();  //edit calibration value manually
  }

  // 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 an 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 == false) {
    LoadCell.update();
    if (Serial.available() > 0) {
      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 loadcell.");
  Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");

  float known_mass = 0;
  _resume = false;
  while (_resume == false) {
    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();                                           //refresh the dataset to be sure that the known mass is measured correct
  float newCalibrationValue = LoadCell.getNewCalibration(known_mass);  //get the new calibration value

  Serial.print("New calibration value has been set to: ");
  Serial.print(newCalibrationValue);
  Serial.println(", use this as calibration value (calFactor) in your project sketch.");
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(calVal_eepromAdress);
  Serial.println("? y/n");

  _resume = false;
  while (_resume == false) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
#if defined(ESP8266) || defined(ESP32)
        EEPROM.begin(512);
#endif
        /*        EEPROM.put(calVal_eepromAdress, newCalibrationValue); //   Added start of comment symbol 01/17/2026    DC
#if defined(ESP8266)|| defined(ESP32)
        EEPROM.commit();
#endif
        EEPROM.get(calVal_eepromAdress, newCalibrationValue);
        Serial.print("Value ");
        Serial.print(newCalibrationValue);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(calVal_eepromAdress);
        _resume = true;

      }
      else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        _resume = true;
      }
    }
  }
*/
        //   Added end of comment symbol 01/17/2026 DC
        Serial.println("End calibration");
        Serial.println("***");
        Serial.println("To re-calibrate, send 'r' from serial monitor.");
        Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
        Serial.println("***");
      }

      void changeSavedCalFactor() {
        float oldCalibrationValue = LoadCell.getCalFactor();
        boolean _resume = false;
        Serial.println("***");
        Serial.print("Current value is: ");
        Serial.println(oldCalibrationValue);
        Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
        float newCalibrationValue;
        while (_resume == false) {
          if (Serial.available() > 0) {
            newCalibrationValue = Serial.parseFloat();
            if (newCalibrationValue != 0) {
              Serial.print("New calibration value is: ");
              Serial.println(newCalibrationValue);
              LoadCell.setCalFactor(newCalibrationValue);
              _resume = true;
            }
          }
        }
        _resume = false;
        Serial.print("Save this value to EEPROM adress ");
        Serial.print(calVal_eepromAdress);
        Serial.println("? y/n");
        while (_resume == false) {
          if (Serial.available() > 0) {
            char inByte = Serial.read();
            if (inByte == 'y') {
#if defined(ESP8266) || defined(ESP32)
              EEPROM.begin(512);
#endif
              EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266) || defined(ESP32)
              EEPROM.commit();
#endif
              EEPROM.get(calVal_eepromAdress, newCalibrationValue);
              Serial.print("Value ");
              Serial.print(newCalibrationValue);
              Serial.print(" saved to EEPROM address: ");
              Serial.println(calVal_eepromAdress);
              _resume = true;
            } else if (inByte == 'n') {
              Serial.println("Value not saved to EEPROM");
              _resume = true;
            }
          }
        }
        Serial.println("End change calibration value");
        Serial.println("***");
      }

Really all I need is to know how and where to declare the variable 'changeSavedCalFactor'. I do not wish to use the EEPROM for this but instead, once I manually obtain the calibration factor, I will put that value in the code (once I figure out how to do that).

If there are any other issues seen here, please do not hesitate to point them out.

The function changeSavedCalFactor() is currently defined inside the calibrate() function , which is not allowed in C++. Functions cannot be nested.

if you indent the code you'll catch such issues probably faster.

You commented out too many }.

1234567 // columns
      void changeSavedCalFactor() {

Look how indented that line is. It should start in column 1 but it starts in column 7. So I suspect there are about 3 missing } before it.

I would also recommend moving your functions so that they are defined before they are first called. The Arduino IDE usually lets you get away with defining them in any order, but that is a special feature to make things easier for beginners. You probably won't find that in other IDEs. Normally with functions, like variables, you must define them before you use them.

Or at least declare them with a function prototype.

That's generally the reason behind the .h (or .hpp) and .cpp file pairs common to C++. The header file (.h) contains all the function prototype declarations and the .cpp file contains the definitions of the implementation of those functions, although that distinction can be a bit blurred sometimes. The compiler first looks at the header and finds the function prototypes have been declared and then looks at the .cpp file to compile their actual implementation. As has been said, using an .ino file "hides" this additional complexity, but the principle in post #4 still applies. The compiler must be "aware" of what the function looks like (either because it has already encountered a prototype of a full definition of the function) before it can be used.

No, that's almost never necessary, and just makes thinks more complex and confusing for beginners. "Declare Define it before you use it" is a simple rule that beginners can understand and should apply to functions just like it does with variables.

... is... your sketch is incomplete and missing close-braces.

I made a few random guesses at where to move the "close comment", and now this compiles... and seems to "work" but that is for you to decide.

/*
   -------------------------------------------------------------------------------------
   HX711_ADC
   Arduino library for HX711 24-Bit Analog-to-Digital Converter for Weight Scales
   Olav Kallhovd sept2017
   -------------------------------------------------------------------------------------
*/

/*
   This example file shows how to calibrate the load cell and optionally store the calibration
   value in EEPROM, and also how to change the value manually.
   The result value can then later be included in your project sketch or fetched from EEPROM.

   To implement calibration in your project sketch the simplified procedure is as follow:
       LoadCell.tare();
       //place known mass
       LoadCell.refreshDataSet();
       float newCalibrationValue = LoadCell.getNewCalibration(known_mass);
*/

#include <HX711_ADC.h>
#if defined(ESP8266) || defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif

//pins:
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;
unsigned long t = 0;

void setup() {
  Serial.begin(57600);
  delay(10);
  Serial.println();
  Serial.println("Starting...");

  LoadCell.begin();
  //LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive
  unsigned long stabilizingtime = 2000;  // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
  boolean _tare = false;                 //set this to false if you don't want tare to be performed in the next step
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1)
      ;
  } else {
    LoadCell.setCalFactor(1.0);  // user set calibration value (float), initial value 1.0 may be used for this sketch
    Serial.println("Startup is complete");
  }
  while (!LoadCell.update())
    ;
  calibrate();  //start calibration procedure
}

void loop() {
  static boolean newDataReady = 0;
  const int serialPrintInterval = 1;  //increase value to slow down serial print activity

  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
      float i = LoadCell.getData();
      Serial.print("Load_cell output val: ");
      Serial.println(i);
      newDataReady = 0;
      t = millis();
    }
  }

  // receive command from serial terminal
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();       //tare
    else if (inByte == 'r') calibrate();             //calibrate
    else if (inByte == 'c') changeSavedCalFactor();  //edit calibration value manually
  }

  // 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 an 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 == false) {
    LoadCell.update();
    if (Serial.available() > 0) {
      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 loadcell.");
  Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");

  float known_mass = 0;
  _resume = false;
  while (_resume == false) {
    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();                                           //refresh the dataset to be sure that the known mass is measured correct
  float newCalibrationValue = LoadCell.getNewCalibration(known_mass);  //get the new calibration value

  Serial.print("New calibration value has been set to: ");
  Serial.print(newCalibrationValue);
  Serial.println(", use this as calibration value (calFactor) in your project sketch.");
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(calVal_eepromAdress);
  Serial.println("? y/n");

  _resume = false;
  while (_resume == false) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
#if defined(ESP8266) || defined(ESP32)
        EEPROM.begin(512);
#endif
        /*        EEPROM.put(calVal_eepromAdress, newCalibrationValue); //   Added start of comment symbol 01/17/2026    DC
          #if defined(ESP8266)|| defined(ESP32)
          EEPROM.commit();
          #endif
          EEPROM.get(calVal_eepromAdress, newCalibrationValue);
          Serial.print("Value ");
          Serial.print(newCalibrationValue);
          Serial.print(" saved to EEPROM address: ");
          Serial.println(calVal_eepromAdress);
          _resume = true;

          }
          else if (inByte == 'n') {
          Serial.println("Value not saved to EEPROM");
          _resume = true;
          }
        */
      }
    }
    //   Added end of comment symbol 01/17/2026 DC
    Serial.println("End calibration");
    Serial.println("***");
    Serial.println("To re-calibrate, send 'r' from serial monitor.");
    Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
    Serial.println("***");
  }
}

void changeSavedCalFactor() {
  float oldCalibrationValue = LoadCell.getCalFactor();
  boolean _resume = false;
  Serial.println("***");
  Serial.print("Current value is: ");
  Serial.println(oldCalibrationValue);
  Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
  float newCalibrationValue;
  while (_resume == false) {
    if (Serial.available() > 0) {
      newCalibrationValue = Serial.parseFloat();
      if (newCalibrationValue != 0) {
        Serial.print("New calibration value is: ");
        Serial.println(newCalibrationValue);
        LoadCell.setCalFactor(newCalibrationValue);
        _resume = true;
      }
    }
  }
  _resume = false;
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(calVal_eepromAdress);
  Serial.println("? y/n");
  while (_resume == false) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
#if defined(ESP8266) || defined(ESP32)
        EEPROM.begin(512);
#endif
        EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266) || defined(ESP32)
        EEPROM.commit();
#endif
        EEPROM.get(calVal_eepromAdress, newCalibrationValue);
        Serial.print("Value ");
        Serial.print(newCalibrationValue);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(calVal_eepromAdress);
        _resume = true;
      } else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        _resume = true;
      }
    }
  }
  Serial.println("End change calibration value");
  Serial.println("***");
}

Results...

Starting...
Startup is complete
***
Start calibration:
Place the load cell an a level stable surface.
Remove any load applied to the load cell.
Send 't' from serial monitor to set the tare offset.
Tare complete
Now, place your known mass on the loadcell.
Then send the weight of this mass (i.e. 100.0) from serial monitor.
Known mass is: 200.00
New calibration value has been set to: 0.00, use this as calibration value (calFactor) in your project sketch.
Save this value to EEPROM adress 0? y/n
End calibration

This is the code as loaded from the example and I performed an Auto Format before posting. Without a better knowledge of the syntax at this point, I'm not up to speed on the indenting format yet. Will come with time though to be honest, this currently is a one off project to create a control box to use with several sets of load cells that I will have mounted under honey bee hives to I can monitor weight over time. I may delve into other projects later as time allows as I do see other useful opportunities.

Looking at the code, I can see this now. Learning the syntax and indentation approach is slow going.

I copied this code into a new blank sketch window. The original error is gone but I now get an error referring to the EEPROM. I had read a post somewhere in this forum that made it sound like the EEPROM function was not compatible with the UNO R4 WiFi but I don't know if that is accurate or not.

Since I have no intent of using the EEPROM to store or retrieve the calibration code, can that feature of this sketch be removed entirely so it only asks for a manual input ?

Using the code you provided, here is the error I got back

C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026018-19192-1ep01vy.affq\sketch_jan18a\sketch_jan18a.ino: In function 'void changeSavedCalFactor()':
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026018-19192-1ep01vy.affq\sketch_jan18a\sketch_jan18a.ino:207:9: error: 'EEPROM' was not declared in this scope
         EEPROM.put(calVal_eepromAdress, newCalibrationValue);
         ^~~~~~
C:\Users\Doug Curtis\AppData\Local\Temp\.arduinoIDE-unsaved2026018-19192-1ep01vy.affq\sketch_jan18a\sketch_jan18a.ino:207:9: note: suggested alternative: 'EIDRM'
         EEPROM.put(calVal_eepromAdress, newCalibrationValue);
         ^~~~~~
         EIDRM
exit status 1

Compilation error: 'EEPROM' was not declared in this scope

A copy/paste will not create those errors. Editing will.

Yes, removing EEPROM calls is fine... but first, you need to make a program compile.

You are using an ESP8266?

I removed the "comment block" completely, and this one runs also (I do not have an ESP8266)...

/*
   -------------------------------------------------------------------------------------
   HX711_ADC
   Arduino library for HX711 24-Bit Analog-to-Digital Converter for Weight Scales
   Olav Kallhovd sept2017
   -------------------------------------------------------------------------------------
*/

/*
   This example file shows how to calibrate the load cell and optionally store the calibration
   value in EEPROM, and also how to change the value manually.
   The result value can then later be included in your project sketch or fetched from EEPROM.

   To implement calibration in your project sketch the simplified procedure is as follow:
       LoadCell.tare();
       //place known mass
       LoadCell.refreshDataSet();
       float newCalibrationValue = LoadCell.getNewCalibration(known_mass);
*/

#include <HX711_ADC.h>
#if defined(ESP8266) || defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif

//pins:
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;
unsigned long t = 0;

void setup() {
  Serial.begin(57600);
  delay(10);
  Serial.println();
  Serial.println("Starting...");

  LoadCell.begin();
  //LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive
  unsigned long stabilizingtime = 2000;  // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
  boolean _tare = false;                 //set this to false if you don't want tare to be performed in the next step
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1)
      ;
  } else {
    LoadCell.setCalFactor(1.0);  // user set calibration value (float), initial value 1.0 may be used for this sketch
    Serial.println("Startup is complete");
  }
  while (!LoadCell.update())
    ;
  calibrate();  //start calibration procedure
}

void loop() {
  static boolean newDataReady = 0;
  const int serialPrintInterval = 1;  //increase value to slow down serial print activity

  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
      float i = LoadCell.getData();
      Serial.print("Load_cell output val: ");
      Serial.println(i);
      newDataReady = 0;
      t = millis();
    }
  }

  // receive command from serial terminal
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();       //tare
    else if (inByte == 'r') calibrate();             //calibrate
    else if (inByte == 'c') changeSavedCalFactor();  //edit calibration value manually
  }

  // 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 an 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 == false) {
    LoadCell.update();
    if (Serial.available() > 0) {
      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 loadcell.");
  Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");

  float known_mass = 0;
  _resume = false;
  while (_resume == false) {
    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();                                           //refresh the dataset to be sure that the known mass is measured correct
  float newCalibrationValue = LoadCell.getNewCalibration(known_mass);  //get the new calibration value

  Serial.print("New calibration value has been set to: ");
  Serial.print(newCalibrationValue);
  Serial.println(", use this as calibration value (calFactor) in your project sketch.");
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(calVal_eepromAdress);
  Serial.println("? y/n");

  _resume = false;
  while (_resume == false) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
#if defined(ESP8266) || defined(ESP32)
        EEPROM.begin(512);
#endif
        EEPROM.put(calVal_eepromAdress, newCalibrationValue); //   Added start of comment symbol 01/17/2026    DC
#if defined(ESP8266)|| defined(ESP32)
        EEPROM.commit();
#endif
        EEPROM.get(calVal_eepromAdress, newCalibrationValue);
        Serial.print("Value ");
        Serial.print(newCalibrationValue);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(calVal_eepromAdress);
        _resume = true;

      }
      else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        _resume = true;
      }
    }
  }
  //   Added end of comment symbol 01/17/2026 DC
  Serial.println("End calibration");
  Serial.println("***");
  Serial.println("To re-calibrate, send 'r' from serial monitor.");
  Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
  Serial.println("***");
}

void changeSavedCalFactor() {
  float oldCalibrationValue = LoadCell.getCalFactor();
  boolean _resume = false;
  Serial.println("***");
  Serial.print("Current value is: ");
  Serial.println(oldCalibrationValue);
  Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
  float newCalibrationValue;
  while (_resume == false) {
    if (Serial.available() > 0) {
      newCalibrationValue = Serial.parseFloat();
      if (newCalibrationValue != 0) {
        Serial.print("New calibration value is: ");
        Serial.println(newCalibrationValue);
        LoadCell.setCalFactor(newCalibrationValue);
        _resume = true;
      }
    }
  }
  _resume = false;
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(calVal_eepromAdress);
  Serial.println("? y/n");
  while (_resume == false) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
#if defined(ESP8266) || defined(ESP32)
        EEPROM.begin(512);
#endif
        EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266) || defined(ESP32)
        EEPROM.commit();
#endif
        EEPROM.get(calVal_eepromAdress, newCalibrationValue);
        Serial.print("Value ");
        Serial.print(newCalibrationValue);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(calVal_eepromAdress);
        _resume = true;
      } else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        _resume = true;
      }
    }
  }
  Serial.println("End change calibration value");
  Serial.println("***");
}

I am aware:
https://forum.arduino.cc/t/organising-code-for-a-large-scale-modular-project/591328/5

Exactly what I said:

As opposed to your original post:

"Declared" vs "Defined". The former is a forward reference, the latter is an implementation (for a function) or a memory allocation (for a variable).

https://www.cprogramming.com/declare_vs_define.html

@gfvalvo you are right, I meant to say "Define it before you use it".

The need to declare something before you define it is rare, and not something beginners should need to do, or think they should need to do. Let's keep things simple!

In your sentence where you say

Defined was the right term to use in your sentence since you were suggesting moving the function’s code (its definition) at the top and not rely on the IDE’s forward declarations.

I disagree. Putting all the function implementations first pushes the setup() and loop() functions further down in the file, obscuring things by forcing you to go hunting for them. IMO, this makes understanding the code more difficult as setup() / loop() are the core structures of any Arduino program and simply scanning through loop() gives you an idea of what’s going on (assuming the functions called from loop() are well-named). I prefer a top-down structure with the main guts at the top. Forward-referencing functions by providing their prototypes first is a simple and effective way to achieve this. And, obviously, doing so is an absolute requirement once you start using separate .h and .cpp files.

Post #12. TL;DR: "Remove the comment block and it compiles."

Just a scroll to the end of the file - it’s easy to find … I would not call that obscure …

I prefer functions first - follows the C++ norm which is a good engineering practice.

Agreed, but if you are doing that, you are out of beginner territory.

Re: your other points, I agree with @J-M-L. The setup() and loop() will be easy to find because they will be at the bottom. And we are not allowed to use a variable before we define it, so why should we be allowed use (call) a function before we define it? Inconsistent rules confuse beginners.