Need help with the code structure

I wrote the code that is made to call certain functions to make my project run sequentially. My problem comes after the code reaches the end of loopLoadCell(End of program.) I want the whole code to restart and start from the beginning. How can I achieve this?

#include <HX711_ADC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Stepper.h>
#include <SoftwareSerial.h>
#include <PN532_SWHSU.h>
#include <PN532.h>
SoftwareSerial SWSerial(3, 2); // RX, TX

const int HX711_dout = 4;
const int HX711_sck = 5;
const int BUTTON_PIN = A0; // Change to analog pin A0
const int numReadings = 10;

HX711_ADC LoadCell(HX711_dout, HX711_sck);

PN532_SWHSU pn532swhsu(SWSerial);
PN532 nfc(pn532swhsu);
String tagId = "None", dispTag = "None";
byte nuidPICC[4];

float readings[numReadings];
int index = 0;
String unitType = "grams";

// Define the I2C address of the LCD module (usually 0x27 or 0x3F, depending on your module)
#define LCD_I2C_ADDRESS 0x27

// Define the number of columns and rows for your LCD (usually 16x2)
#define LCD_COLUMNS 16
#define LCD_ROWS 2

// Define the number of steps per revolution for your stepper motor
const int stepsPerRevolution = 341.3; // Change this according to your motor's specifications

// Create an LCD object with the specified I2C address and dimensions
LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, LCD_COLUMNS, LCD_ROWS);

// Initialize the stepper motor object with the number of steps and the motor pins
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11); // Change the pin numbers to match your setup

bool hasRun = false;             // Flag to control loop execution
bool loadCellStarted = false;    // Flag to track if LoadCell has started
bool measureFilteredValue = false; // Flag to indicate when to measure and display filtered value
float lastFilteredValue = 0.0;   // Store the last filtered value
bool stopStartUpFunction = false; // Flag to stop StartUpFunction when setupRfid starts
bool stopSetupStartup = false;    // Flag to stop setupStartup when setupRfid starts
bool specificTagScanned = false;  // Initialize a flag to false
bool End = false;


void setupRfid() {
  Serial.begin(9600);

  //  Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (!versiondata) {
    Serial.print("Didn't Find PN53x Module");
    while (1); // Halt
  }

  // Configure board to read RFID tags
  nfc.SAMConfig();
  //Serial.println("Waiting for an ISO14443A Card ...");

  stopSetupStartup = true; // Set the flag to stop setupStartup
}

void startupRfid() {
  boolean success;
  uint8_t uid[] = {0, 0, 0, 0, 0, 0, 0};  // Buffer to store the returned UID
  uint8_t uidLength;                       // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
  lcd.setCursor(0, 0);
  lcd.print("Please use your");
  lcd.setCursor(0, 1);
  lcd.print("Rfid TAG!");
  if (success) {
    Serial.print("UID Length: ");
    Serial.print(uidLength, DEC);
    Serial.println(" bytes");
    Serial.print("UID Value: ");
    for (uint8_t i = 0; i < uidLength; i++) {
      nuidPICC[i] = uid[i];
      Serial.print(" "); Serial.print(uid[i], DEC);
    }
    Serial.println();
    tagId = tagToString(nuidPICC);
    dispTag = tagId;
    Serial.print(F("tagId is : "));
    Serial.println(tagId);
    Serial.println("");
    delay(1000);  // 1 second halt


    stopStartUpFunction = true; // Set the flag to stop StartUpFunction
  }
}

String tagToString(byte id[4]) {
  String tagId = "";
  for (byte i = 0; i < 4; i++) {
    if (i < 3) tagId += String(id[i]) + ".";
    else tagId += String(id[i]);
  }
  return tagId;

  
}

void setupLoadCell() {
  Serial.begin(9600);
  delay(10);
  Serial.println();
  Serial.println("Starting...");

  pinMode(BUTTON_PIN, INPUT_PULLUP);  // Set the button pin as an input with pull-up resistor
  pinMode(A1, OUTPUT);

  LoadCell.begin();
  float calibrationValue = 230.90;
  LoadCell.setCalFactor(calibrationValue);

  unsigned long stabilizingTime = 2000;
  boolean doTare = true;
  LoadCell.start(stabilizingTime, doTare);

  if (LoadCell.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1);
  } else {
    Serial.println("Startup is complete");
  }
}

void loopLoadCell() {
  static boolean newDataReady = false;
  const int serialPrintInterval = 1000;
  float filteredValue = 0.0;
  static unsigned long previousMillis = 0;
  static unsigned long alertStartTime = 0;
  static boolean showAlert = false;
  static boolean alertDisplayed = false;  // Flag to track if the alert has been displayed

  int buttonState = digitalRead(BUTTON_PIN);

  if (buttonState == LOW) {
    if (!loadCellStarted) {
      // Start LoadCell function on the first click
      loadCellStarted = true;
      Serial.println("Starting LoadCell...");
      delay(500);
    } else if (!measureFilteredValue) {
      // On the second click, print the last value of filtered value on the LCD
      measureFilteredValue = true;
      Serial.println("Button pressed. Measuring last filtered value.");
      delay(500);
    }
  } else {
    // Reset flags when the button is released
    loadCellStarted = false;
    measureFilteredValue = false;
  }

  if (LoadCell.update()) {
    newDataReady = true;
  }

  if (newDataReady || (millis() - previousMillis) >= serialPrintInterval && !End) {
    float rawValue = LoadCell.getData();

    readings[index] = rawValue;
    index = (index + 1) % numReadings;
    filteredValue = calculateMovingAverage();

    if (filteredValue > 1.5) {
      // Record the start time when the value becomes more than 0.5
      if (!showAlert) {
        alertStartTime = millis();
        showAlert = true;
      }

      // Check if 1.5 seconds have passed since the alert started
      if (millis() - alertStartTime >= 2000) {
        // Clear the alert flag to stop displaying the message

      } else {
        // Display the alert message on the LCD only if it hasn't been displayed before
        if (!alertDisplayed) {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Press red button:");
          lcd.setCursor(0, 1);
          lcd.print("to finish");
          digitalWrite(A1, HIGH);
          alertDisplayed = true;  // Set the flag to indicate it has been executed
        }
      }
    }

    if (measureFilteredValue) {
      // Only display the filtered value when the alert is not active
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Weight:");
      lcd.setCursor(0, 1);
      lcd.print(filteredValue, 1);
      digitalWrite(A1, LOW);
      setupStartup();
      if (filteredValue >= 3.0 && filteredValue <= 4.0) {
       // Rotate the stepper motor here
       myStepper.step(341.3); // Rotate one step in one direction (adjust as needed)
       myStepper.step(-341.3);
       digitalWrite(8, LOW);
       digitalWrite(9, LOW);
       digitalWrite(10, LOW);
       digitalWrite(11, LOW);
       lcd.clear();
       lcd.setCursor(0, 0);
       lcd.print("Thanks for");
       lcd.setCursor(0, 1);
       lcd.print("using machine");
       
    
      }else{
        myStepper.step(-341.3); // Rotate one step in one direction (adjust as needed)
        myStepper.step(341.3);
        digitalWrite(8, LOW);
        digitalWrite(9, LOW);
        digitalWrite(10, LOW);
        digitalWrite(11, LOW);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Thanks for");
        lcd.setCursor(0, 1);
        lcd.print("using machine");
        delay(1000);
      }
    }

    newDataReady = false;
    previousMillis = millis();
    
    End = true;
  }

  if (LoadCell.getTareStatus()) {
    Serial.println("Tare complete");
  }
  setupStartup();
  StartUpFunction();
}

float calculateMovingAverage() {
  float sum = 0.0;
  for (int i = 0; i < numReadings; i++) {
    sum += readings[i];
  }

  return sum / numReadings;
}

void setupStartup() {
  if (!stopSetupStartup) { // Check if the flag to stop setupStartup is not set
    // Set the speed (rpm) of the stepper motor
    myStepper.setSpeed(55);  // Adjust the speed as needed

    // Initialize the I2C communication
    Wire.begin();

    // Initialize the LCD
    lcd.init();

    // Turn on the backlight (if your LCD module has backlight control)
    lcd.backlight();
  }
}

void StartUpFunction() {
  if (!hasRun && !stopStartUpFunction) {  // Check if the loop hasn't run yet and stopStartUpFunction is false
    lcd.print("Loading...");
    myStepper.step(stepsPerRevolution);
    myStepper.step(-stepsPerRevolution);
    myStepper.step(-stepsPerRevolution);
    myStepper.step(stepsPerRevolution);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    hasRun = true;  // Set the flag to indicate that the loop has run
  }
}


void setup() {
  setupStartup();
  if (!stopSetupStartup) { // Check if the flag to stop setupStartup is not set
    setupRfid();
  }
  setupLoadCell();
}

void loop() {
  StartUpFunction();
  if (!stopStartUpFunction) {
    startupRfid();
  }

 if (tagId == "105.108.54.24"  && !specificTagScanned) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Hello");
    lcd.setCursor(0, 1);
    lcd.print("Svetoslav");
    delay(1500);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Throw your");
    lcd.setCursor(0, 1);
    lcd.print("Garbige");
    specificTagScanned = true;  // Set the flag to true to indicate it has been executed
  }else{
    if(tagId == "115.142.89.237"  && !specificTagScanned) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Hello");
    lcd.setCursor(0, 1);
    lcd.print("User");
    delay(1500);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Throw your");
    lcd.setCursor(0, 1);
    lcd.print("Garbige");
    specificTagScanned = true;  // Set the flag to true to indicate it has been executed
    }
  }
  loopLoadCell();  // Start the loopLoadCell function
  

  // You can add other tasks or code here if needed
}

Make ALL the stuff you do in setup() a function and call it from both setup() and from loop().

at the end of loopLoadCell it's going to hit the end of the loop function and then it will repeat the loop function. SO whatever you want repeated, put it in the loop function.

When the end of the loop() function is reached the code in the loop() function is repeated

Are you saying that you want the code in setup() to be repeated when the loop() function ends ?

If so, then why ?
If you really want to do that then put the code now in setup() at the start of the loop() function so that it is repeated, but please explain your reason for doing it

In the current version, I made several voids, calling them in a certain order in void loop();
The problem is that when you get to the end of the program, that is, where the LCD screen says Thanks for using the machine, the code does not start from the beginning

Hello svetoslav_26

I assume that you have written the programme by yourself, then it is quite easy to find the error.

There's a trick to figuring out why something isn't working:

Use a logic analyzer to see what happens.
Put Serial.print statements at various places in the code to see the values of variables and determine whether they meet your expectations.

Have a nice day and enjoy coding in C++.

A void is an empty region of space. You made several functions and those functions returned the void type so they had the void keyword in front of them.

You actually have the setup code repeated at the end of the looopLoadCell function. I don't know how wise it is to repeat some of that setup code. Some of that should be done only once.

But then there are several flags throughout your code that seem to have been put there to intentionally force the program to only run once.

For instance the first line of StartUpFunction checks a flag called hasRun and then sets it to true at the end of the function. So this can only run once unless something else is setting hasRun back to false.

There's also one called End but I don't see where it gets used.

Please explain what you mean by "the beginning"

If you want the loop() function to start again immediately after

                lcd.print("Thanks for");
                lcd.setCursor(0, 1);
                lcd.print("using machine");
                delay(1000);

then add return; after the delay() and it will do just that, but you may need to set the value of some variables before the return; to get the sketch into a state where loop() can run again sensibly

it looks like your code needs RFID tag to start, but after first reading the program doesn't read tag again and, thus, not started.

In general, there is no consistent logic in your code. Procedures and functions in C serve to organize code, rather than calling them randomly from one another, completely masking the logical structure of the program.

Also, most of your startup code, such as display initialization(lcd.begin() or Serial port init, does not need to be called again at the end of the loop(). They need to be placed inside the setup() and called only once.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.