Modifying the code to loop

Hello
I need help on modifying this code to loop when lcd.print("CUTTING COMPLETE");
when cutting complete it should ask "REPEAT CUTTING ?" IF YES then its goes to the START
and start the cutting cycle again here is the link of this project https://wokwi.com/projects/344596633107825235
and this is the code

//------------------------------- librarys ----------------------------------

#include <LiquidCrystal.h>
#include <Servo.h>
 
//------------------------------- lcd ----------------------------------
LiquidCrystal lcd(12, 11, 2, 3, 4, 5);
 
//------------------------------- stepper ----------------------------------
#define stepPin 7
#define dirPin 8
 
//------------------------------- servo ----------------------------------
Servo snippers;
#define servo 10
#define openAngle 90
#define closedAngle 0
 
//------------------------------- input ----------------------------------
 
#define leftButton 14
#define rightButton 9
#define upButton 15
#define downButton 6
 
//------------------------------- user settings ----------------------------------
unsigned int wireLength = 0;
unsigned int wireQuantity = 0;
 
//------------------------------- system settings ----------------------------------
int state = 0;
int incrementSpeed = 1;
int previousWireLength = 0;
int previousWireQuantity = 0;
float mmPerStep = 0.305344;
 
 
void setup() {
  Serial.begin(9600);
 
 
  lcd.begin(16, 2); //LCD columns and rows
 
 
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);
 
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
 
  snippers.attach(servo);
 
  snippers.write(openAngle);
   
  delay(1000);
}
 
void loop() {
  if (!digitalRead(rightButton)){
    if(state == 5){
      state = 0;
    }
    else{
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0 && state < 4){
    state -=1;
    delay(200);
    lcd.clear();
  }
 
 
  switch (state){
    case 0:
      homeScreen();
      break;
    case 1:
       chooseWireLength();
       break;
    case 2:
      chooseWireQuantity();
      break;
    case 3:
      confirm();
      break;
    case 4:
      currentlyCutting();
      break;
    case 5:
      finishedCutting();
      break;
  }
 
}
 
 
void homeScreen(){
  lcd.setCursor(0, 0);
  lcd.print("CUTTER");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
void chooseWireLength(){
  wireLength = changeValue(wireLength);
 
  //clear LCD if required
  if(previousWireLength != wireLength){
    lcd.clear();
    previousWireLength = wireLength;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)wireLength + "mm");
  displayNavigation();
}
 
void chooseWireQuantity(){
  wireQuantity = changeValue(wireQuantity);
 
  //clear LCD if required
  if(previousWireQuantity != wireQuantity){
    lcd.clear();
    previousWireQuantity = wireQuantity;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("QUANTITY:" + (String)wireQuantity);
  displayNavigation();
}
 
void confirm(){
  lcd.setCursor(0, 0);
  lcd.print((String)wireLength + "mm x " + (String)wireQuantity + "pcs");
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);
}
 
void currentlyCutting(){
  lcd.setCursor(0, 0);
  lcd.print((String)0 + "/" + (String)wireQuantity);
  lcd.setCursor(0, 1);
  lcd.print("???s");
  int stepsToTake = (int)wireLength/mmPerStep;
  for(int i = 0; i < wireQuantity; i++){
    unsigned long timeForOneCycle = millis();
    digitalWrite(dirPin,HIGH);
    for(int x = 0; x < stepsToTake; x++) {
      digitalWrite(stepPin,HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPin,LOW);
      delayMicroseconds(500);
    }
   
    lcd.setCursor(0, 0);
    lcd.print((String)(i+1) + "/" + (String)wireQuantity);
   
    snippers.write(closedAngle);
    delay(500);
    snippers.write(openAngle);
    delay(500);
 
   
    lcd.setCursor(0, 1);
 
    unsigned long timeRemaining = ((millis() - timeForOneCycle)*(wireQuantity - (i+1)))/1000;
    lcd.print((String)timeRemaining + "s    ");
   
  }
  wireLength = 0;
  wireQuantity = 0;
  state = 5;
}
 
void finishedCutting(){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CUTTING COMPLETE");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
int changeValue(int currentValue){
  if (!digitalRead(upButton)) {
    delay(100);
    currentValue += incrementSpeed;
    
  }
  if (!digitalRead(downButton)) {
    if(currentValue - incrementSpeed >= 0){
      delay(100);
      currentValue -= incrementSpeed;
    
    }
    else{
      currentValue = 0;
    }
  }
  if (!digitalRead(downButton) && !digitalRead(upButton)){
    incrementSpeed = 1;
  }
  return currentValue;
}
 
void displayNavigation(){
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}

Thank you

Your finishedCutting() function should probably ask the question (or call a display function that does) then reset state to 3 if yes, or else to 0 if no.

Your topic does not indicate a problem with IDE 2.x and therefore has been moved to a more suitable category of the forum.

Thank you for your reply,
i think the finishedCutting() function should probably ask the question if yes it repeat the cycle if no its goes to 0, I dont know what will happen when you call a display function to apply the reset

Hi @sarath2020 !

In addition to changing the state to 3 you need either to set the variables wireLength and
wireQuantity to the previous values or move the lines where they are set to zero to a different place.

I have modified your sketch so that it should do what you want (only tested once :wink: )

/*
  Forum: https://forum.arduino.cc/t/modifying-the-code-to-loop/1408241
  Wokwi: https://wokwi.com/projects/443711360924689409

*/


//------------------------------- librarys ----------------------------------

#include <LiquidCrystal.h>
#include <Servo.h>
 
//------------------------------- lcd ----------------------------------
//LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
LiquidCrystal   lcd(12, 11,  2, 3, 4, 5);
 
//------------------------------- stepper ----------------------------------
#define stepPin 7
#define dirPin 8
 
//------------------------------- servo ----------------------------------
Servo snippers;
#define servo 10
#define openAngle 90
#define closedAngle 0
 
//------------------------------- input ----------------------------------
 
#define leftButton 14
#define rightButton 9
#define upButton 15
#define downButton 6
 
//------------------------------- user settings ----------------------------------
unsigned int wireLength = 0;
unsigned int wireQuantity = 0;
 
//------------------------------- system settings ----------------------------------
int state = 0;
int incrementSpeed = 1;
int previousWireLength = 0;
int previousWireQuantity = 0;
float mmPerStep = 0.305344;
 
 
void setup() {
  Serial.begin(9600);
 
 
  lcd.begin(16, 2); //LCD columns and rows
 
 
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);
 
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
 
  snippers.attach(servo);
 
  snippers.write(openAngle);
   
  delay(1000);
}
 
void loop() {
  if (!digitalRead(rightButton)){
    if(state == 5){
      state = 0;
    }
    else{
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0){
    if (state < 4){
       state -=1;
    }
    if (state == 5){
      wireLength = previousWireLength;
      wireQuantity = previousWireQuantity;
      state = 3;
    }
    delay(200);
    lcd.clear();
  }
 
 
  switch (state){
    case 0:
      homeScreen();
      break;
    case 1:
       chooseWireLength();
       break;
    case 2:
      chooseWireQuantity();
      break;
    case 3:
      confirm();
      break;
    case 4:
      currentlyCutting();
      break;
    case 5:
      finishedCutting();
      break;
  }
 
}
 
 
void homeScreen(){
  lcd.setCursor(0, 0);
  lcd.print("CUTTER");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
void chooseWireLength(){
  wireLength = changeValue(wireLength);
 
  //clear LCD if required
  if(previousWireLength != wireLength){
    lcd.clear();
    previousWireLength = wireLength;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)wireLength + "mm");
  displayNavigation();
}
 
void chooseWireQuantity(){
  wireQuantity = changeValue(wireQuantity);
 
  //clear LCD if required
  if(previousWireQuantity != wireQuantity){
    lcd.clear();
    previousWireQuantity = wireQuantity;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("QUANTITY:" + (String)wireQuantity);
  displayNavigation();
}
 
void confirm(){
  lcd.setCursor(0, 0);
  lcd.print((String)wireLength + "mm x " + (String)wireQuantity + "pcs");
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);
}
 
void currentlyCutting(){
  lcd.setCursor(0, 0);
  lcd.print((String)0 + "/" + (String)wireQuantity);
  lcd.setCursor(0, 1);
  lcd.print("???s");
  int stepsToTake = (int)wireLength/mmPerStep;
  for(int i = 0; i < wireQuantity; i++){
    unsigned long timeForOneCycle = millis();
    digitalWrite(dirPin,HIGH);
    for(int x = 0; x < stepsToTake; x++) {
      digitalWrite(stepPin,HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPin,LOW);
      delayMicroseconds(500);
    }
   
    lcd.setCursor(0, 0);
    lcd.print((String)(i+1) + "/" + (String)wireQuantity);
   
    snippers.write(closedAngle);
    delay(500);
    snippers.write(openAngle);
    delay(500);
 
   
    lcd.setCursor(0, 1);
 
    unsigned long timeRemaining = ((millis() - timeForOneCycle)*(wireQuantity - (i+1)))/1000;
    lcd.print((String)timeRemaining + "s    ");
   
  }
  wireLength = 0;
  wireQuantity = 0;
  state = 5;
}
 
void finishedCutting(){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("REPEAT CUTTING?");
  lcd.setCursor(0, 1);
  lcd.print("<YES");
  lcd.setCursor(11, 1);
  lcd.print("NO>");
  delay(100);
}
 
 
int changeValue(int currentValue){
  if (!digitalRead(upButton)) {
    delay(100);
    currentValue += incrementSpeed;
    
  }
  if (!digitalRead(downButton)) {
    if(currentValue - incrementSpeed >= 0){
      delay(100);
      currentValue -= incrementSpeed;
    
    }
    else{
      currentValue = 0;
    }
  }
  if (!digitalRead(downButton) && !digitalRead(upButton)){
    incrementSpeed = 1;
  }
  return currentValue;
}
 
void displayNavigation(){
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}

You can check it out on Wokwi
https://wokwi.com/projects/443711360924689409

I like to recommend

  • to integrate the button control in the different states (check the buttons outside the state machine but handle the buttons separately inside the state functions)
  • to modify the display only when required, not every 100 or 200 ms

That would make the code more readable and make modifications to each state more straightforward.

Good luck!


may be its better to ask the question here instead of "CUTTING COMPLETE" should print
"REPEAT CUTTING ?" if yes it goes to repeat the full cycle again if no goes to "WIRE CUTTER"

Like this

:wink:

Just check the Wokwi online simulation ...

I integrated the code changes to your Wokwi setup here

https://wokwi.com/projects/443714069553327105

yes yes exactly this way but can you switch the yes on the right side of the screen please
so that I can press two time to restart the cycle or with just YES it will start the cycle
I really appreciate your help on this
Best Regards

Give me a few seconds ... :wink:

.... Done ...

// For: https://forum.arduino.cc/t/automatic-wire-cutter-with-servo-and-stepper-motor/1037774
//
// WARNING : The circuit is made by guessing.
//           Even the Fritzing schematic was unreadable.
//
// LCD syntax: LiquidCrystal(rs, enable, d4, d5, d6, d7)
// Pin 14 is A0 ?
// Pin 15 is A1 ?
//


//------------------------------- librarys ----------------------------------

#include <LiquidCrystal.h>
#include <Servo.h>

//------------------------------- lcd ----------------------------------
LiquidCrystal lcd(12, 11, 2, 3, 4, 5);

//------------------------------- stepper ----------------------------------
#define stepPin 7
#define dirPin 8

//------------------------------- servo ----------------------------------
Servo snippers;
#define servo 10
#define openAngle 180
#define closedAngle 0

//------------------------------- input ----------------------------------

#define leftButton 14
#define rightButton 9
#define upButton 15
#define downButton 6

//------------------------------- user settings ----------------------------------
unsigned int wireLength = 0;
unsigned int wireQuantity = 0;

//------------------------------- system settings ----------------------------------
int state = 0;
int incrementSpeed = 1;
int previousWireLength = 0;
int previousWireQuantity = 0;
float mmPerStep = 0.18096;


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

  lcd.begin(16, 2); //LCD columns and rows

  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);

  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  snippers.attach(servo);

  snippers.write(openAngle);

  delay(1000);
}
void loop() {
  if (!digitalRead(rightButton)){
    if(state == 5){
      wireLength = previousWireLength;
      wireQuantity = previousWireQuantity;
      state = 3;
    }
    else{
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0){
    if (state < 4){
       state -=1;
    }
    if (state == 5){
      state = 0;
    }
    delay(200);
    lcd.clear();
  }
 
 
  switch (state){
    case 0:
      homeScreen();
      break;
    case 1:
       chooseWireLength();
       break;
    case 2:
      chooseWireQuantity();
      break;
    case 3:
      confirm();
      break;
    case 4:
      currentlyCutting();
      break;
    case 5:
      finishedCutting();
      break;
  }
 
}
 
 
void homeScreen(){
  lcd.setCursor(0, 0);
  lcd.print("CUTTER");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
void chooseWireLength(){
  wireLength = changeValue(wireLength);
 
  //clear LCD if required
  if(previousWireLength != wireLength){
    lcd.clear();
    previousWireLength = wireLength;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)wireLength + "mm");
  displayNavigation();
}
 
void chooseWireQuantity(){
  wireQuantity = changeValue(wireQuantity);
 
  //clear LCD if required
  if(previousWireQuantity != wireQuantity){
    lcd.clear();
    previousWireQuantity = wireQuantity;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("QUANTITY:" + (String)wireQuantity);
  displayNavigation();
}
 
void confirm(){
  lcd.setCursor(0, 0);
  lcd.print((String)wireLength + "mm x " + (String)wireQuantity + "pcs");
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);
}
 
void currentlyCutting(){
  lcd.setCursor(0, 0);
  lcd.print((String)0 + "/" + (String)wireQuantity);
  lcd.setCursor(0, 1);
  lcd.print("???s");
  int stepsToTake = (int)wireLength/mmPerStep;
  for(int i = 0; i < wireQuantity; i++){
    unsigned long timeForOneCycle = millis();
    digitalWrite(dirPin,HIGH);
    for(int x = 0; x < stepsToTake; x++) {
      digitalWrite(stepPin,HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPin,LOW);
      delayMicroseconds(500);
    }
   
    lcd.setCursor(0, 0);
    lcd.print((String)(i+1) + "/" + (String)wireQuantity);
   
    snippers.write(closedAngle);
    delay(500);
    snippers.write(openAngle);
    delay(500);
 
   
    lcd.setCursor(0, 1);
 
    unsigned long timeRemaining = ((millis() - timeForOneCycle)*(wireQuantity - (i+1)))/1000;
    lcd.print((String)timeRemaining + "s    ");
   
  }
  wireLength = 0;
  wireQuantity = 0;
  state = 5;
}
 
void finishedCutting(){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("REPEAT CUTTING?");
  lcd.setCursor(0, 1);
  lcd.print("<NO");
  lcd.setCursor(11, 1);
  lcd.print("YES>");
  delay(100);
}
 
 
int changeValue(int currentValue){
  if (!digitalRead(upButton)) {
    delay(100);
    currentValue += incrementSpeed;
    
  }
  if (!digitalRead(downButton)) {
    if(currentValue - incrementSpeed >= 0){
      delay(100);
      currentValue -= incrementSpeed;
    
    }
    else{
      currentValue = 0;
    }
  }
  if (!digitalRead(downButton) && !digitalRead(upButton)){
    incrementSpeed = 1;
  }
  return currentValue;
}
 
void displayNavigation(){
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}

See here https://wokwi.com/projects/443716064241995777

yes this is what exactly I expect the outcome for this modification

Thank you EC2021 Farady for you kind help and your time to fix the code

once again Thank you

Best Regards

You may mark the posting that solved your task as "Solution" ...

Thanks, I'm still working on an improved version of your sketch that is more responsive (by removing unnecessary delays) and where the display is only updated on a change ...

Back after dinner ... :wink:

.... Here is the resulting code ...

// Wokwi: https://wokwi.com/projects/443714371674366977
// For: https://forum.arduino.cc/t/automatic-wire-cutter-with-servo-and-stepper-motor/1037774
//
// WARNING : The circuit is made by guessing.
//           Even the Fritzing schematic was unreadable.
//
// LCD syntax: LiquidCrystal(rs, enable, d4, d5, d6, d7)
// Pin 14 is A0 ?
// Pin 15 is A1 ?
//
// Changes by ec2021

//------------------------------- librarys ----------------------------------

#include <LiquidCrystal.h>
#include <Servo.h>

//------------------------------- lcd ----------------------------------
LiquidCrystal lcd(12, 11, 2, 3, 4, 5);

//------------------------------- stepper ----------------------------------
constexpr uint8_t stepPin {7};
constexpr uint8_t dirPin {8};

//------------------------------- servo ----------------------------------
Servo snippers;
constexpr uint8_t  servo {10};
constexpr uint8_t  openAngle {180};
constexpr uint8_t  closedAngle {0};

//------------------------------- input ----------------------------------

constexpr uint8_t  leftButton {14};
constexpr uint8_t  rightButton {9};
constexpr uint8_t  upButton {15};
constexpr uint8_t  downButton {6};

//------------------------------- user settings ----------------------------------
unsigned int wireLength = 0;
unsigned int wireQuantity = 0;

//------------------------------- system settings ----------------------------------
constexpr unsigned long debouncingDelay   {30}; // ms
constexpr unsigned long buttonRepeat     {300}; // ms
enum States {HOME, LENGTH, QUANTITY, CONFIRM, CUTTING, FINISHED };
States state = HOME;
int incrementSpeed = 1;
int previousWireLength = 0;
int previousWireQuantity = 0;
float mmPerStep = 0.18096;
boolean displayChange = true;

class buttonClass {
  private:
    uint8_t pin;
    uint8_t state;
    uint8_t lastState;
    boolean contPressed = false;
    unsigned long lastChange = 0;
    unsigned long changeToLow = 0;
  public:
    void init(uint8_t aPin) {
      pin = aPin;
      pinMode(pin, INPUT_PULLUP);
    };
    boolean continuousPressed() {
      boolean cPress = contPressed;
      contPressed = false;
      return cPress;
    }
    boolean pressed() {
      uint8_t actState = digitalRead(pin);
      if (actState != lastState) {
        lastChange = millis();
        lastState = actState;
      }
      if (state != actState && millis() - lastChange > debouncingDelay) {
        state = actState;
        if (!state) {
          changeToLow = lastChange;
        } else {
          changeToLow = 0;
          contPressed = false;
        }
        return !state;
      }
      if (state == LOW && millis() - changeToLow > buttonRepeat) {
        changeToLow = millis();
        contPressed = true;
      }
      return false;
    }
} buttonLeft, buttonRight, buttonUp, buttonDown;



void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2); //LCD columns and rows
  buttonLeft.init(leftButton);
  buttonRight.init(rightButton);
  buttonUp.init(upButton);
  buttonDown.init(downButton);
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  snippers.attach(servo);
  snippers.write(openAngle);
  delay(1000);
  changeStateTo(HOME);
}

void loop() {
  switch (state) {
    case HOME:
      homeScreen();
      onButtonChangeTo(HOME, LENGTH);
      break;
    case LENGTH:
      chooseWireLength();
      onButtonChangeTo(HOME, QUANTITY);
      break;
    case QUANTITY:
      chooseWireQuantity();
      onButtonChangeTo(LENGTH, CONFIRM);
      break;
    case CONFIRM:
      confirm();
      onButtonChangeTo(QUANTITY, CUTTING);
      break;
    case CUTTING:
      currentlyCutting();
      break;
    case FINISHED:
      finishedCutting();
      onButtonChangeTo(HOME, CONFIRM);
      if (state == CONFIRM) {
        wireLength = previousWireLength;
        wireQuantity = previousWireQuantity;
      }
      break;
  }
}

void clearDisplay() {
  lcd.clear();
  displayChange = true;
}

void changeStateTo(States nextState) {
  state = nextState;
  clearDisplay();
}

void onButtonChangeTo(States left, States right) {
  if (buttonLeft.pressed()) {
    changeStateTo(left);
  };
  if (buttonRight.pressed()) {
    changeStateTo(right);
  };
}


void homeScreen() {
  if  (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("CUTTER");
    lcd.setCursor(11, 1);
    lcd.print("NEXT>");
  }
}

void chooseWireLength() {
  wireLength = changeValue(wireLength);
  //clear LCD if required
  if (previousWireLength != wireLength) {
    previousWireLength = wireLength;
    clearDisplay();
  }

  //Display information on LCD
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("LENGTH: ");
    lcd.print(wireLength);
    lcd.print(" mm");
    displayNavigation();
  }
}

void chooseWireQuantity() {
  wireQuantity = changeValue(wireQuantity);
  //clear LCD if required
  if (previousWireQuantity != wireQuantity) {
    clearDisplay();
    previousWireQuantity = wireQuantity;

  }

  //Display information on LCD
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("QUANTITY: ");
    lcd.print(wireQuantity);
    displayNavigation();
  }
}

int changeValue(int currentValue) {
  if (buttonUp.pressed() || buttonUp.continuousPressed()) {
    currentValue += incrementSpeed;
  }
  if (buttonDown.pressed() || buttonDown.continuousPressed()) {
    if (currentValue >=  incrementSpeed) {
      currentValue -= incrementSpeed;
    }
    else {
      currentValue = 0;
    }
  }
  if (buttonDown.pressed() && buttonUp.pressed()) {
    incrementSpeed = 1;
  }
  return currentValue;
}

void displayNavigation() {
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
}

void confirm() {
  if (wireLength == 0) {
    printError("LENGTH = 0 mm");
    changeStateTo(LENGTH);
    return;
  }
  if (wireQuantity == 0) {
    printError("QUANTITY = 0");
    changeStateTo(QUANTITY);
    return;
  }
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print(wireLength);
    lcd.print(" mm x ");
    lcd.print(wireQuantity);
    lcd.print(" pcs");
    lcd.setCursor(0, 1);
    lcd.print("<BACK");
    lcd.setCursor(10, 1);
    lcd.print("START>");
  }
}

void printError(const char *txt) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("ERROR!");
  lcd.setCursor(0, 1);
  lcd.print(txt);
  delay(2000);

}

void currentlyCutting() {
  lcd.setCursor(0, 0);
  lcd.print(0);
  lcd.print("/");
  lcd.print(wireQuantity);
  lcd.setCursor(0, 1);
  lcd.print("? s");
  int stepsToTake = (int)wireLength / mmPerStep;
  for (int i = 0; i < wireQuantity; i++) {
    unsigned long timeForOneCycle = millis();
    digitalWrite(dirPin, HIGH);
    for (int x = 0; x < stepsToTake; x++) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(500);
    }
    lcd.setCursor(0, 0);
    lcd.print(i + 1);
    lcd.print("/");
    lcd.print(wireQuantity);
    snippers.write(closedAngle);
    delay(500);
    snippers.write(openAngle);
    delay(500);
    lcd.setCursor(0, 1);
    unsigned long timeRemaining = ((millis() - timeForOneCycle) * (wireQuantity - (i + 1))) / 1000;
    lcd.print(timeRemaining);
    lcd.print(" s    ");
  }
  wireLength = 0;
  wireQuantity = 0;
  changeStateTo(FINISHED);
}

void finishedCutting() {
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("REPEAT CUTTING?");
    lcd.setCursor(0, 1);
    lcd.print("<NO");
    lcd.setCursor(11, 1);
    lcd.print("YES>");

  }
}

See on Wokwi: https://wokwi.com/projects/443714371674366977

Main changes:

  • Enumerations for the states
  • Printing to display only after changes
  • Use of a button class
    • to debounce the buttons (which allows to remove unnecessary delays() and increases the responsiveness of the application)
    • to provide a function for button press and
    • another function to handle continuous pressing of buttons (which however depends on the buttonClass::pressed() function)
  • State changes are now handled inside the state machine
  • Error handling when wireLength and/or wireQuantity are zero when calling "confirm()"
  • Replaced the use of String() cast in lcd.print() by separate calls of lcd.print() to avoid the String class use
  • #define replaced by constexpr to avoid that the constants could be changed unintentionally by a later define statement

If you push the up or down button shortly the values will change by +/- 1. If you keep one of the buttons pressed they will start to add +/-1 every "buttonRepeat" ms. I have set it to 300 ms. Thought this might be handy :wink:

Not absolutely necessary but it might be nicer ...

Have fun!
ec2021

oh ok that is interesting to see in action, please use my code to modify because I know its working on my cutter, but on the Wokwi I haven't tested the code

The latest sketch from post #12 is based on your code and Wokwi setup and in the main function of cutting behaves like your code from post #1 ...

Therefore it should directly work in your application ...

your code is looks more professional now, quick question is it possible do a increment of .5 instead of 1 MM 2MM 3MM, to 1.5MM, 2.00MM, 2.5MM, 3.00MM so on, this modification will be very useful when its comes to precision cutting

That's possible: Change the variables concerning the length from int to float and incrementSpeed to 0.5.

My PC is already shut down, you can try yourself or wait until tomorrow... or for another forum member to support... :wink:

I have started my PC late night again :wink:

Here a version with 0.5 mm length increments:

// Wokwi: https://wokwi.com/projects/443737909715353601
// For: https://forum.arduino.cc/t/automatic-wire-cutter-with-servo-and-stepper-motor/1037774
//
// WARNING : The circuit is made by guessing.
//           Even the Fritzing schematic was unreadable.
//
// LCD syntax: LiquidCrystal(rs, enable, d4, d5, d6, d7)
// Pin 14 is A0 ?
// Pin 15 is A1 ?
//
// Changes by ec2021

//------------------------------- librarys ----------------------------------

#include <LiquidCrystal.h>
#include <Servo.h>

//------------------------------- lcd ----------------------------------
LiquidCrystal lcd(12, 11, 2, 3, 4, 5);

//------------------------------- stepper ----------------------------------
constexpr uint8_t stepPin {7};
constexpr uint8_t dirPin {8};

//------------------------------- servo ----------------------------------
Servo snippers;
constexpr uint8_t  servo {10};
constexpr uint8_t  openAngle {180};
constexpr uint8_t  closedAngle {0};

//------------------------------- input ----------------------------------

constexpr uint8_t  leftButton {14};
constexpr uint8_t  rightButton {9};
constexpr uint8_t  upButton {15};
constexpr uint8_t  downButton {6};

//------------------------------- user settings ----------------------------------
float wireLength = 0.0;
unsigned int wireQuantity = 0;

//------------------------------- system settings ----------------------------------
constexpr unsigned long debouncingDelay   {30}; // ms
constexpr unsigned long buttonRepeat     {300}; // ms
enum States {HOME, LENGTH, QUANTITY, CONFIRM, CUTTING, FINISHED };
States state = HOME;
float incrementSpeed = 0.5;
float previousWireLength = 0.0;
int previousWireQuantity = 0;
float mmPerStep = 0.18096;
boolean displayChange = true;

class buttonClass {
  private:
    uint8_t pin;
    uint8_t state;
    uint8_t lastState;
    boolean contPressed = false;
    unsigned long lastChange = 0;
    unsigned long changeToLow = 0;
  public:
    void init(uint8_t aPin) {
      pin = aPin;
      pinMode(pin, INPUT_PULLUP);
    };
    boolean continuousPressed() {
      boolean cPress = contPressed;
      contPressed = false;
      return cPress;
    }
    boolean pressed() {
      uint8_t actState = digitalRead(pin);
      if (actState != lastState) {
        lastChange = millis();
        lastState = actState;
      }
      if (state != actState && millis() - lastChange > debouncingDelay) {
        state = actState;
        if (!state) {
          changeToLow = lastChange;
        } else {
          changeToLow = 0;
          contPressed = false;
        }
        return !state;
      }
      if (state == LOW && millis() - changeToLow > buttonRepeat) {
        changeToLow = millis();
        contPressed = true;
      }
      return false;
    }
} buttonLeft, buttonRight, buttonUp, buttonDown;



void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2); //LCD columns and rows
  buttonLeft.init(leftButton);
  buttonRight.init(rightButton);
  buttonUp.init(upButton);
  buttonDown.init(downButton);
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  snippers.attach(servo);
  snippers.write(openAngle);
  delay(1000);
  changeStateTo(HOME);
}

void loop() {
  switch (state) {
    case HOME:
      homeScreen();
      onButtonChangeTo(HOME, LENGTH);
      break;
    case LENGTH:
      chooseWireLength();
      onButtonChangeTo(HOME, QUANTITY);
      break;
    case QUANTITY:
      chooseWireQuantity();
      onButtonChangeTo(LENGTH, CONFIRM);
      break;
    case CONFIRM:
      confirm();
      onButtonChangeTo(QUANTITY, CUTTING);
      break;
    case CUTTING:
      currentlyCutting();
      break;
    case FINISHED:
      finishedCutting();
      onButtonChangeTo(HOME, CONFIRM);
      if (state == CONFIRM) {
        wireLength = previousWireLength;
        wireQuantity = previousWireQuantity;
      }
      break;
  }
}

void clearDisplay() {
  lcd.clear();
  displayChange = true;
}

void changeStateTo(States nextState) {
  state = nextState;
  clearDisplay();
}

void onButtonChangeTo(States left, States right) {
  if (buttonLeft.pressed()) {
    changeStateTo(left);
  };
  if (buttonRight.pressed()) {
    changeStateTo(right);
  };
}


void homeScreen() {
  if  (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("CUTTER");
    lcd.setCursor(11, 1);
    lcd.print("NEXT>");
  }
}

void chooseWireLength() {
  wireLength = changeLength(wireLength);
  //clear LCD if required
  if (previousWireLength != wireLength) {
    previousWireLength = wireLength;
    clearDisplay();
  }

  //Display information on LCD
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("LENGTH: ");
    lcd.print(wireLength);
    lcd.print(" mm");
    displayNavigation();
  }
}

void chooseWireQuantity() {
  wireQuantity = changeQuantity(wireQuantity);
  //clear LCD if required
  if (previousWireQuantity != wireQuantity) {
    clearDisplay();
    previousWireQuantity = wireQuantity;

  }

  //Display information on LCD
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("QUANTITY: ");
    lcd.print(wireQuantity);
    displayNavigation();
  }
}

int changeQuantity(int currentValue) {
  if (buttonUp.pressed() || buttonUp.continuousPressed()) {
    currentValue += 1;
  }
  if (buttonDown.pressed() || buttonDown.continuousPressed()) {
    if (currentValue >=  1) {
      currentValue -= 1;
    }
    else {
      currentValue = 0;
    }
  }
  return currentValue;
}

float changeLength(float currentValue) {
  if (buttonUp.pressed() || buttonUp.continuousPressed()) {
    currentValue += incrementSpeed;
  }
  if (buttonDown.pressed() || buttonDown.continuousPressed()) {
    if (currentValue >=  incrementSpeed) {
      currentValue -= incrementSpeed;
    }
    else {
      currentValue = 0;
    }
  }
  if (buttonDown.pressed() && buttonUp.pressed()) {
    incrementSpeed = 0.5;
  }
  return currentValue;
}

void displayNavigation() {
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
}

void confirm() {
  if (wireLength == 0) {
    printError("LENGTH = 0 mm");
    changeStateTo(LENGTH);
    return;
  }
  if (wireQuantity == 0) {
    printError("QUANTITY = 0");
    changeStateTo(QUANTITY);
    return;
  }
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print(wireLength);
    lcd.print(" mm x ");
    lcd.print(wireQuantity);
    lcd.print(" pcs");
    lcd.setCursor(0, 1);
    lcd.print("<BACK");
    lcd.setCursor(10, 1);
    lcd.print("START>");
  }
}

void printError(const char *txt) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("ERROR!");
  lcd.setCursor(0, 1);
  lcd.print(txt);
  delay(2000);

}

void currentlyCutting() {
  lcd.setCursor(0, 0);
  lcd.print(0);
  lcd.print("/");
  lcd.print(wireQuantity);
  lcd.setCursor(0, 1);
  lcd.print("? s");
  int stepsToTake = (int)wireLength / mmPerStep;
  for (int i = 0; i < wireQuantity; i++) {
    unsigned long timeForOneCycle = millis();
    digitalWrite(dirPin, HIGH);
    for (int x = 0; x < stepsToTake; x++) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(500);
    }
    lcd.setCursor(0, 0);
    lcd.print(i + 1);
    lcd.print("/");
    lcd.print(wireQuantity);
    snippers.write(closedAngle);
    delay(500);
    snippers.write(openAngle);
    delay(500);
    lcd.setCursor(0, 1);
    unsigned long timeRemaining = ((millis() - timeForOneCycle) * (wireQuantity - (i + 1))) / 1000;
    lcd.print(timeRemaining);
    lcd.print(" s    ");
  }
  wireLength = 0;
  wireQuantity = 0;
  changeStateTo(FINISHED);
}

void finishedCutting() {
  if (displayChange) {
    displayChange = false;
    lcd.setCursor(0, 0);
    lcd.print("REPEAT CUTTING?");
    lcd.setCursor(0, 1);
    lcd.print("<NO");
    lcd.setCursor(11, 1);
    lcd.print("YES>");

  }
}

see also https://wokwi.com/projects/443737909715353601

Not thoroughly tested ...

Good luck!
ec2021

yes this is exactly the end result that I was asking for, Well Done ec2021,
I really appreciate your time and effort to help me on this modification
Bravo!
Once again Thank you
Regards