Help with matrix keypad input and AccelStepper

I'm making a machine where I input a value with a matrix keypad and the arduino moves a stepper correspondingly . This is to be used for a crosscut saw where a large stepper moves sheet material toward the saw by rack pinion and a step down gear with limit switches at the rack ends.
The code bellow works but I would like it to repeat so if I entered 200 then pressed # once the stepper had moved I could simply press # again to repeat the move and the value entered would remain displayed on the 16x2 LCD until * is pressed and a new value could be entered.
Also how do I add a limit switch at the end to stop the thing going too far .
Any Help would be much appreciated.

[code]
#include <Keypad.h>
#include <AccelStepper.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
AccelStepper stepperX(1, 10, 11);   // 1 = Easy Driver interface

const byte home_switch =  12;

// Stepper Travel Variables
long TravelX;  // Used to store the X value provided by the user
bool moveComplete = true;

//keypad setup
const int ROW_NUM = 4; //four rows
const int COLUMN_NUM = 4; //four columns

char keys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte pin_rows[ROW_NUM]      = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );

String keypadInput;

void lcdEnterValue() {
  lcd.clear();
  lcd.print(F("enter value:"));
  lcd.setCursor(0, 1);

}


bool readKeypad(long& newDestination) {
  long userInput = 0;
  char key = keypad.getKey();
  if (key) {
    if (key >= '0' && key <= '9') {     // only act on numeric keys
      keypadInput += key;               // append new character to input string
      lcd.print(key);

    } else if (key == '#') {
      if (keypadInput.length() > 0) {
        userInput = keypadInput.toInt();
        keypadInput = "";               // clear input


        if (userInput < 0 || userInput > 2400) {  // Make sure the position entered is not beyond the HOME or MAX position
          lcd.clear();
          lcd.print(F("invalid value."));
          delay(3000);
          lcdEnterValue();
          return false;
        } else {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print(F("Moving to:"));
          lcd.print(userInput);
          Serial.print(F("Moving stepper into position: "));
          Serial.println(userInput);
          delay(1000);  // Wait 1 seconds before moving the Stepper
          newDestination = userInput;
          return true;
        }



      }
    }
  }
  return false;
}

void homing() {
  //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperX.setMaxSpeed(1000);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(800.0);  // Set Acceleration of Stepper

  // Start Homing procedure of Stepper Motor at startup
  lcd.setCursor(0, 0);
  lcd.print(F("HOMING"));
  Serial.print(F("Stepper is Homing"));

  long initial_homing = -1; // Used to Home Stepper at startup

  while (digitalRead(home_switch) == HIGH) {
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperX.run();  // Start moving the stepper
    delay(1);
  }

  stepperX.setCurrentPosition(0);   // Set the current position as zero for now
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homing = 1;
  delay(15);                        // anti-bounce

  while (digitalRead(home_switch) == LOW) {
    stepperX.moveTo(initial_homing);
    initial_homing++;
    stepperX.run();
    delay(1);
  }

  stepperX.setCurrentPosition(0);

  lcd.clear();
  lcd.print(F("HOMING OK"));
  Serial.println(F("Homing OK"));

}

void setup() {
  pinMode(home_switch, INPUT_PULLUP);
  Serial.begin(115200);

  keypadInput.reserve(10);  // avoid dynamic allocation
  keypadInput == "";        // empty the String

  lcd.init();               // initialize the lcd
  lcd.clear();
  lcd.backlight();

  homing();

  stepperX.setMaxSpeed(1000.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperX.setAcceleration(500.0);  // Set Acceleration of Stepper

  // Print out Instructions on the Serial Monitor at Start
  lcdEnterValue();
}

void loop() {

  if (readKeypad(TravelX)) {
    stepperX.move(TravelX * 44.4); // Set new moveto position of Stepper
    moveComplete = false;
  }

  // Check if the Stepper has reached desired position
  if ((stepperX.distanceToGo() != 0)) {
    stepperX.run();  // Move Stepper if needed
  } else {
    if (!moveComplete) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("COMPLETED!");
      Serial.println("COMPLETED!");
      delay(2000);
      lcdEnterValue();
      moveComplete = true;
    }
  }
}
[/code]

the reason it does not repeat is because you test the length of the input when you get the #

else if (key == '#') {
      if (keypadInput.length() > 0) {

as keypadInputis empty, you don't proceed.

try to actually proceed with the previous value if the keypadInput is empty.

else if (key == '#') {
      if (keypadInput.length() > 0) {
        userInput = keypadInput.toInt();
        keypadInput = "";               // clear input
      }
      if (userInput < 0 || userInput > 2400) {  // Make sure the position entered is not beyond the HOME or MAX position
        lcd.clear();
        lcd.print(F("invalid value."));
        delay(3000);
        lcdEnterValue();
        return false;
      } else {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(F("Moving to:"));
        lcd.print(userInput);
        Serial.print(F("Moving stepper into position: "));
        Serial.println(userInput);
        delay(1000);  // Wait 1 seconds before moving the Stepper
        newDestination = userInput;
        return true;
      }
    }

if that works, you might want to add a boolean that gets true when a good value has been read and is in userInput so that if you press # without entering a number first it won't work.

I got rid of the clear input line and the repeat part works when pressing # so that helps but obviously can't then input another value.
please could you explain more about the boolean.

    } else if (key == '#') {
      if (keypadInput.length() > 0) {
        userInput = keypadInput.toInt();
        //keypadInput = "";               // clear input

You should be able to input a new value

What’s the new code ?

The code is the same but just the clear input line disabled. the repeat parr works fine but if I try to input a different value it is just joined onto the last value.

[code]
#include <Keypad.h>
#include <AccelStepper.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
AccelStepper stepperX(1, 10, 11);   // 1 = Easy Driver interface

const byte home_switch =  12;

// Stepper Travel Variables
long TravelX;  // Used to store the X value preovided by the user
bool moveComplete = true;

//keypad setup
const int ROW_NUM = 4; //four rows
const int COLUMN_NUM = 4; //four columns

char keys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte pin_rows[ROW_NUM]      = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );

String keypadInput;

void lcdEnterValue() {
  lcd.clear();
  lcd.print(F("enter value:"));
  lcd.setCursor(0, 1);

}


bool readKeypad(long& newDestination) {
  long userInput = 0;
  char key = keypad.getKey();
  if (key) {
    if (key >= '0' && key <= '9') {     // only act on numeric keys
      keypadInput += key;               // append new character to input string
      lcd.print(key);

    } else if (key == '#') {
      if (keypadInput.length() > 0) {
        userInput = keypadInput.toInt();
        //keypadInput = "";               // clear input


        if (userInput < 0 || userInput > 2400) {  // Make sure the position entered is not beyond the HOME or MAX position
          lcd.clear();
          lcd.print(F("invalid value."));
          delay(3000);
          lcdEnterValue();
          return false;
        } else {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print(F("Moving to:"));
          lcd.print(userInput);
          Serial.print(F("Moving stepper into position: "));
          Serial.println(userInput);
          delay(1000);  // Wait 1 seconds before moving the Stepper
          newDestination = userInput;
          return true;
        }



      }
    }
  }
  return false;
}

void homing() {
  //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperX.setMaxSpeed(1000);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(800.0);  // Set Acceleration of Stepper

  // Start Homing procedure of Stepper Motor at startup
  lcd.setCursor(0, 0);
  lcd.print(F("HOMING"));
  Serial.print(F("Stepper is Homing"));

  long initial_homing = -1; // Used to Home Stepper at startup

  while (digitalRead(home_switch) == HIGH) {
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperX.run();  // Start moving the stepper
    delay(1);
  }

  stepperX.setCurrentPosition(0);   // Set the current position as zero for now
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homing = 1;
  delay(15);                        // anti-bounce

  while (digitalRead(home_switch) == LOW) {
    stepperX.moveTo(initial_homing);
    initial_homing++;
    stepperX.run();
    delay(1);
  }

  stepperX.setCurrentPosition(0);

  lcd.clear();
  lcd.print(F("HOMING OK"));
  Serial.println(F("Homing OK"));

}

void setup() {
  pinMode(home_switch, INPUT_PULLUP);
  Serial.begin(115200);

  keypadInput.reserve(10);  // avoid dynamic allocation
  keypadInput == "";        // empty the String

  lcd.init();               // initialize the lcd
  lcd.clear();
  lcd.backlight();

  homing();

  stepperX.setMaxSpeed(1000.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperX.setAcceleration(500.0);  // Set Acceleration of Stepper

  // Print out Instructions on the Serial Monitor at Start
  lcdEnterValue();
}

void loop() {

  if (readKeypad(TravelX)) {
    stepperX.move(TravelX * 44.4); // Set new moveto position of Stepper
    moveComplete = false;
  }

  // Check if the Stepper has reached desired position
  if ((stepperX.distanceToGo() != 0)) {
    stepperX.run();  // Move Stepper if needed
  } else {
    if (!moveComplete) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("COMPLETED!");

      Serial.println("COMPLETED!");
      delay(2000);
      lcdEnterValue();
      moveComplete = true;
    }
  }
}
[/code]

Why did you comment thus out?

Try with


    } else if (key == '#') {
      if (keypadInput.length() > 0) {
        userInput = keypadInput.toInt();
        keypadInput = "";               // clear input
      }
      …

Doing this allows the same repeated value sent to stepper every time # is pressed . not sure what you're suggesting to try as is the same as original code. would it be possible to use another key to clear and then enter a new value so allowing for repeated moves and new ones.

The closing bracket is just after the check on the length

the idea is this

if you receive '#'
  then check if the length is > 0 
     in which case extract the new userInput

proceed with whatever is in userInput

before you had

if you receive '#'
  then check if the length is > 0 
    extract the new userInput
    proceed with the new userInput

Sorry didn't see the bracket adjustment. tried it and makes no difference

[code]
#include <Keypad.h>
#include <AccelStepper.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
AccelStepper stepperX(1, 10, 11);   // 1 = Easy Driver interface

const byte home_switch =  12;

// Stepper Travel Variables
long TravelX;  // Used to store the X value preovided by the user
bool moveComplete = true;

//keypad setup
const int ROW_NUM = 4; //four rows
const int COLUMN_NUM = 4; //four columns

char keys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte pin_rows[ROW_NUM]      = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );

String keypadInput;

void lcdEnterValue() {
  lcd.clear();
  lcd.print(F("enter value:"));
  lcd.setCursor(0, 1);

}


bool readKeypad(long& newDestination) {
  long userInput = 0;
  char key = keypad.getKey();
  if (key) {
    if (key >= '0' && key <= '9') {     // only act on numeric keys
      keypadInput += key;               // append new character to input string
      lcd.print(key);

    } else if (key == '#') {            //   else?
      if (keypadInput.length() > 0) {
        userInput = keypadInput.toInt();
      
        keypadInput = "";               // clear input comment out makes move rep when #
      }

        if (userInput < 0 || userInput > 2400) {  // Make sure the position entered is not beyond the HOME or MAX position
          lcd.clear();
          lcd.print(F("invalid value."));
          delay(3000);
          lcdEnterValue();
          return false;
        } else {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print(F("Moving to:"));
          lcd.print(userInput);
          Serial.print(F("Moving stepper into position: "));
          Serial.println(userInput);
          delay(1000);  // Wait 1 seconds before moving the Stepper
          newDestination = userInput;
          return true;
        }



      
    }
  }
  return false;
}

void homing() {
  //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperX.setMaxSpeed(1000);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(800.0);  // Set Acceleration of Stepper

  // Start Homing procedure of Stepper Motor at startup
  lcd.setCursor(0, 0);
  lcd.print(F("HOMING"));
  Serial.print(F("Stepper is Homing"));

  long initial_homing = -1; // Used to Home Stepper at startup

  while (digitalRead(home_switch) == HIGH) {
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperX.run();  // Start moving the stepper
    delay(1);
  }

  stepperX.setCurrentPosition(0);   // Set the current position as zero for now
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homing = 1;
  delay(15);                        // anti-bounce

  while (digitalRead(home_switch) == LOW) {
    stepperX.moveTo(initial_homing);
    initial_homing++;
    stepperX.run();
    delay(1);
  }

  stepperX.setCurrentPosition(0);

  lcd.clear();
  lcd.print(F("HOMING OK"));
  Serial.println(F("Homing OK"));

}

void setup() {
  pinMode(home_switch, INPUT_PULLUP);
  Serial.begin(115200);

  keypadInput.reserve(10);  // avoid dynamic allocation
  keypadInput == "";        // empty the String

  lcd.init();               // initialize the lcd
  lcd.clear();
  lcd.backlight();

  homing();

  stepperX.setMaxSpeed(1000.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperX.setAcceleration(500.0);  // Set Acceleration of Stepper

  // Print out Instructions on the Serial Monitor at Start
  lcdEnterValue();
}

void loop() {

  if (readKeypad(TravelX)) {
    stepperX.move(TravelX * 44.4); // Set new moveto position of Stepper
    moveComplete = false;
  }

  // Check if the Stepper has reached desired position
  if ((stepperX.distanceToGo() != 0)) {
    stepperX.run();  // Move Stepper if needed
  } else {
    if (!moveComplete) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("COMPLETED!");

      Serial.println("COMPLETED!");
      delay(2000);
      lcdEnterValue();
      moveComplete = true;
    }
  }
}
[/code]

make userInput static so that its value is remembered across calls.

bool readKeypad(long& newDestination) {
  static long userInput = 0;

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