Replace serial monitor input with matrix keypad

Hi, im making a project where i input a value and the arduino moves a stepper motor to that location. I'm using a 16x2 LCD for output, and want to add a 4x4 matrix keypad to enter the value instead of in the serial monitor. However, no matter how i try to implement it, it always results in an error.

Below is the code i'm using:


#include <Keypad.h>
#include "AccelStepper.h" 
#include <Wire.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 Setup
AccelStepper stepperX(1, 12, 11);   // 1 = Easy Driver interface
                                  // NANO Pin 2 connected to STEP pin of Easy Driver
                                  // NANO Pin 3 connected to DIR pin of Easy Driver

// Define the Pins used
#define home_switch 10 // Pin 9 connected to Home Switch (MicroSwitch)

// Stepper Travel Variables
long TravelX;  // Used to store the X value entered in the Serial Monitor
int move_finished=1;  // Used to check if move is completed
long initial_homing=-1;  // Used to Home Stepper at startup






void setup() {

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

   Serial.begin(9600);  // Start the Serial monitor with speed of 9600 Bauds
   
   pinMode(home_switch, INPUT_PULLUP);
   delay(5);
   //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperX.setMaxSpeed(800.0);      // 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);
  Serial.print("Stepper is Homing . . . . . . . . . . . ");

  while (digitalRead(home_switch)) {  // Make the Stepper move CCW until the switch is activated   
    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);
   lcd.print("INITIALIZING!");
  delay(250);
  lcd.clear();
  delay(250);
}
 

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;

  while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
    stepperX.moveTo(initial_homing);  
    initial_homing++;
    stepperX.run();
    delay(1);
  }


  stepperX.setCurrentPosition(0);
  lcd.setCursor(0,0);
  lcd.print("HOMING COMPLETED");
  //delay(5000);
  Serial.println("Homing Completed");
  Serial.println("");
  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
lcd.setCursor(0,1);
lcd.print("enter value:");
  Serial.println("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): ");
}

void loop() {
  

while (Serial.available()>0)  {
//motor part

  move_finished=0;  // Set variable for checking move of the Stepper
  
  //TravelX= Serial.parseInt();  // Put numeric value from buffer in TravelX variable
  TravelX= Serial.parseInt();
  if (TravelX < 0 || TravelX > 140250) {  // Make sure the position entered is not beyond the HOME or MAX position
    Serial.println("");
    Serial.println("Please enter a value greater than zero and smaller or equal to 70250.....");
    Serial.println("");
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("invalid value.");
  } else {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Moving to:");
    Serial.print("Moving stepper into position: ");
    lcd.print(TravelX);
    Serial.println(TravelX);
  
  stepperX.moveTo(TravelX);  // Set new moveto position of Stepper
  
  delay(1000);  // Wait 1 seconds before moving the Stepper
  }
  }

  if (TravelX >= 0 && TravelX <= 140250) {

// Check if the Stepper has reached desired position
  if ((stepperX.distanceToGo() != 0)) {
    
    stepperX.run();  // Move Stepper into position
    
  }

// If move is completed display message on Serial Monitor
  if ((move_finished == 0) && (stepperX.distanceToGo() == 0)) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("COMPLETED!");
    Serial.println("COMPLETED!");
    Serial.println("");
     Serial.println("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): ");
     lcd.setCursor(0,1);
     lcd.print("enter value:");
    move_finished=1;  // Reset move variable
    
  }
  }
  //stepperX.stop();
}

where is your attempt to use the keypad?

What is the error You run into?

This is the code implementing the keypad:

#include <Keypad.h>
#include "AccelStepper.h" 
#include <Wire.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 Setup
AccelStepper stepperX(1, 12, 11);   // 1 = Easy Driver interface
                                  // NANO Pin 2 connected to STEP pin of Easy Driver
                                  // NANO Pin 3 connected to DIR pin of Easy Driver

// Define the Pins used
#define home_switch 10 // Pin 9 connected to Home Switch (MicroSwitch)

// Stepper Travel Variables
long TravelX;  // Used to store the X value entered in the Serial Monitor
int move_finished=1;  // Used to check if move is completed
long initial_homing=-1;  // Used to Home Stepper at startup


//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] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad

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

String inputString;
long inputInt;



void setup() {
  inputString.reserve(10); // maximum number of digit for a number is 10, change if needed

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

   Serial.begin(9600);  // Start the Serial monitor with speed of 9600 Bauds
   
   pinMode(home_switch, INPUT_PULLUP);
   delay(5);
   //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperX.setMaxSpeed(800.0);      // 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);
  Serial.print("Stepper is Homing . . . . . . . . . . . ");

  while (digitalRead(home_switch)) {  // Make the Stepper move CCW until the switch is activated   
    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);
   lcd.print("INITIALIZING!");
  delay(250);
  lcd.clear();
  delay(250);
}
 

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;

  while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
    stepperX.moveTo(initial_homing);  
    initial_homing++;
    stepperX.run();
    delay(1);
  }


  stepperX.setCurrentPosition(0);
  lcd.setCursor(0,0);
  lcd.print("HOMING COMPLETED");
  //delay(5000);
  Serial.println("Homing Completed");
  Serial.println("");
  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
lcd.setCursor(0,1);
lcd.print("enter value:");
  Serial.println("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): ");
}

void loop() {
  
//keypad part
char key = keypad.getKey();
 if (key) {
   

    if (key >= '0' && key <= '9') {     // only act on numeric keys
      inputString += key;               // append new character to input string
    } else if (key == '#') {
      if (inputString.length() > 0) {
        inputInt = inputString.toInt(); // YOU GOT AN INTEGER NUMBER
        inputString = "";               // clear input
         Serial.println(inputInt);
        // DO YOUR WORK HERE

     
  
 
while (Serial.available()>0)  {
//motor part

  move_finished=0;  // Set variable for checking move of the Stepper
  
  //TravelX= Serial.parseInt();  // Put numeric value from buffer in TravelX variable
  TravelX= inputInt;
  if (TravelX < 0 || TravelX > 140250) {  // Make sure the position entered is not beyond the HOME or MAX position
    Serial.println("");
    Serial.println("Please enter a value greater than zero and smaller or equal to 70250.....");
    Serial.println("");
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("invalid value.");
    delay(10000);
    lcd.clear();
    lcd.print("enter value:");

    
  } else {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Moving to:");
    Serial.print("Moving stepper into position: ");
    lcd.print(TravelX);
    Serial.println(TravelX);
  
  stepperX.moveTo(TravelX);  // Set new moveto position of Stepper
  
  delay(1000);  // Wait 1 seconds before moving the Stepper
  }
  }

  if (TravelX >= 0 && TravelX <= 140250) {

// Check if the Stepper has reached desired position
  if ((stepperX.distanceToGo() != 0)) {
    
    stepperX.run();  // Move Stepper into position
    
  }

// If move is completed display message on Serial Monitor
  if ((move_finished == 0) && (stepperX.distanceToGo() == 0)) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("COMPLETED!");
    Serial.println("COMPLETED!");
    Serial.println("");
     Serial.println("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): ");
     lcd.setCursor(0,1);
     lcd.print("enter value:");
    move_finished=1;  // Reset move variable
    
  }
  }
  //stepperX.stop();
   }
    } else if (key == '*') {
      inputString = "";                 // clear input
    }
  }
}

with this i can enter upto 10 digits, and when i press '"#" on the keypad. the number is displayed in the serial monitor as well. But it isnot being taken as "TravelX" input.

Basically what i want it to do is the motor to move to the number given in the keypad, and should move as soon as i press #

Your line [quote="infiman12, post:4, topic:910724"]

  TravelX= inputInt;

[/quote]

is only done if there is something in the Serial input buffer as you have

while (Serial.available()>0)  {

so that's a problem

Why don't you put the value directly into TravelX upon validation?

Thank you for your swift response Jacksong. I'm pretty much a noob, so i'm struggling with the code a bit, learning as i go.

How do you propose I do that? Should I put this-

while (TravelX>0) {

Or is there another way to do it?

Update:

Tried that. still the same problem. I can see the entered value in the serial monitor but it's not being taken as TravelX input.

try something like this (typed here based on your code, so mind typos and possible errors). This should give you an idea how you could structure the code. (note I changed the baud rate for the Serial monitor to 115200, adjust your console)

#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, 12, 11);   // 1 = Easy Driver interface

const byte home_switch =  10;

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


//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]      = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {9, 8, 7, 6}; //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);
  Serial.println(F("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): "));
}


bool readKeypad(long& newDestination) {
  long userInput = 0;
  char key = keypad.getKey();
  if (key) {
    if (key >= '0' && key <= '9') {     // only act on numeric keys ==> HOW DO YOU ENTER NEGATIVE VALUES?
      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 > 140250) {  // Make sure the position entered is not beyond the HOME or MAX position
          Serial.println(F("\nPlease enter a value greater than zero and smaller or equal to 70250.....\n"));
          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(800.0);      // 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\n"));

}

void setup() {
  pinMode(home_switch, INPUT_PULLUP);
  Serial.begin(115200);     // don't go slow.

  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.moveTo(TravelX);  // Set new moveto position of Stepper

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

the instructions say you can enter negative value but the code does not support it.

Thank for that. Your code looks really neat and i appreciate that!

However, i seem to get into a loop of "enter value:" and "completed". This happens after the homing part of the program is completed.

Stepper is HomingHoming OK
11:19:37.746 ->
11:19:39.305 -> Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home):
11:19:39.305 -> COMPLETED!
11:19:40.810 -> Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home):
11:19:40.852 -> COMPLETED!
11:19:42.390 -> Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home):
11:19:42.390 -> COMPLETED!

That's the serial monitor input, and i'm getting the same loop in the lcd display as well.

And since its stuck in this loop, i'm not able to check if the keypad is working as its not taking any input from the keypad, possibly cus its stuck in the loop.

makes sense as the distance to go is 0 so you get the message repeated. We need a boolean variable to only display that once. (I added moveComplete that is set to true or false based on activity)

try this

#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, 12, 11);   // 1 = Easy Driver interface

const byte home_switch =  10;

// 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]      = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {9, 8, 7, 6}; //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);
  Serial.println(F("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): "));
}


bool readKeypad(long& newDestination) {
  long userInput = 0;
  char key = keypad.getKey();
  if (key) {
    if (key >= '0' && key <= '9') {     // only act on numeric keys ==> HOW DO YOU ENTER NEGATIVE VALUES?
      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 > 140250) {  // Make sure the position entered is not beyond the HOME or MAX position
          Serial.println(F("\nPlease enter a value greater than zero and smaller or equal to 70250.....\n"));
          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(800.0);      // 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\n"));

}

void setup() {
  pinMode(home_switch, INPUT_PULLUP);
  Serial.begin(115200);     // don't go slow.

  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.moveTo(TravelX);  // 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!");
      lcdEnterValue();
      moveComplete = true;
    }
  }
}
1 Like

That works perfectly, thanks a bunch!

I have a teensy little problem. I want the input to be cleared when i press "*" key on the keypad. Sort of like a backspace incase i press the wrong number. I tried implementing it by adding an else if statement at the end, but that doesn't seem to be working.

#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, 12, 11);   // 1 = Easy Driver interface

const byte home_switch =  10;

// 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]      = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {9, 8, 7, 6}; //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);
  Serial.println(F("Enter Travel distance (Positive for CW / Negative for CCW and Zero for back to Home): "));
}


bool readKeypad(long& newDestination) {
  long userInput = 0;
  char key = keypad.getKey();
  if (key) {
    if (key >= '0' && key <= '9') {     // only act on numeric keys ==> HOW DO YOU ENTER NEGATIVE VALUES?
      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 > 140250) {  // Make sure the position entered is not beyond the HOME or MAX position
          Serial.println(F("\nPlease enter a value greater than zero and smaller or equal to 70250.....\n"));
          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;
        }
        
       }else if (key == '*') {
        keypadInput = "";                 // clear input
    }
    }
  }
  return false;
}

void homing() {
  //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperX.setMaxSpeed(800.0);      // 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\n"));

}

void setup() {
  pinMode(home_switch, INPUT_PULLUP);
  Serial.begin(115200);     // don't go slow.

  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.moveTo(TravelX);  // 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!");
      lcdEnterValue();
      moveComplete = true;
    }
  }
}

I added the below code to the main code:

else if (key == '*') {
keypadInput = ""; // clear input
}

This part adds the user input to the String (the char the user types in) but also prints to the LCD the last character. So when you empty the string you also want to refresh the lcd display by calling lcdEnterValue();

1 Like

Thank you for all your help J-M-L! I finished a basic prototype of my project thanks to you. I'll be working to extend its capabilities.

Great - enjoy !