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.
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]
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.
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]