Trying to input value from keypad then run to that position with stepper

The short story of what I am trying to do is build a cheap alternative rotaty indexer for one of the cnc mills at our shop. We don’t need super accuracy because it is for a specific project that is +/-.5 degrees on the hole position around a coupling. I’ve been drilling and tapping these holes long hand on a bridgeport after all of the cnc work is done and it SUCKS. So… i’ve modified a manual rotary table so that it has less than 1 arc min of backlash and I adapted a stepper motor to the input shaft. Now I just have to make the damn thing work. The mill is pre-wired for a haas style indexer as such: it has four pins, two in and two out, when prompted with a M-code a relay actuates and the enable pins send a continuous 24V signal via the output pins and continues to do so until the machine receives a “finish” signal from the input pins (just a relay that closes momentarily letting the machine know it has completed a move). The controller I am building utilizes an arduino mega, a 3 x 4 keypad, and two 8-digit 7-segment displays (max 7219 ic’s). The plan is to enter a value in degrees which will be displayed on the “incremental” display, move the motor said distance everytime it gets the signal from the mill, then output the absolute position to the “absolute” display. So far I am successful at entering a value and getting it to display properly on the incremental display (ive been gradually testing each function as I go) but when I throw the motor into the mix everything goes haywire. The display gets f#*ked up and the motor doesn’t budge. I’ve tested the motor with example codes to make sure it is wired correctly so that’s not the issue. Anyhow, here’s the code so far.

/* Stepper is 200steps/rev geared 90:1 
 */
#include <AccelStepper.h>
#include <Keypad.h>
#include <LedControl.h>

LedControl lc2 = LedControl (21,20,19,1);
LedControl lc = LedControl(12,11,10,1); //one ic on pins 10 11 12
unsigned long delaytime = 100;  //delay between readings for led display
AccelStepper stepper(1,8,9); //initiate stepper, pin8=step pin9=dir 

#define triggerPin 50
#define brakePin 17
#define finPin 18

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'-','0','#'}
};
byte rowPins[ROWS] = {36,25,22,23}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {28,27,26}; //connect to the column pinouts of the keypad
//row and column pinouts weren't very easy to locate, it's from an old phone...

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  digitalWrite(brakePin, LOW);
  digitalWrite(finPin, LOW);
  pinMode(triggerPin, INPUT_PULLUP);
  lc.shutdown(0,false);
  lc.setIntensity(0,8);
  lc.clearDisplay(0);
  stepper.setMaxSpeed(3500);
  stepper.setAcceleration(3500);
  Serial.begin(9600);  
}

int getDegrees() //get stepper increment in degrees
//and return when # key is pressed
{
  int num = 0;
  char key = keypad.getKey();
  while(key != '#') 
  {
    switch (key) 
    {
    case NO_KEY:
      break;

    case '0': 
    case '1': 
    case '2': 
    case '3': 
    case '4':
    case '5': 
    case '6': 
    case '7': 
    case '8': 
    case '9':

      Serial.print(key);
      num = num * 10 + (key - '0');
      break;

    }
    if (key=='-'){
      num = num * -1;
    }
    key = keypad.getKey();
  }
  if (-3600 > num || num > 3600){
    return 3600;
  }
  else {  
    return num;
  }
}

void degreePrint() //print stepper move increment in degrees on led display
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = getDegrees();

  if(d<0) 
  {
    negative=true;
    d=d*-1;
  }
  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;
  if(negative) 
  {
    lc.setChar(0,3,'-',false);
  }
  else 
  {
    lc.setChar(0,3,' ',false);
  }
  lc.setDigit(0,0,1,false);
  lc.setRow(0,1,0x15);
  lc.setChar(0,2,'c',false);
  lc.setDigit(0,4,(byte)thousands,false);
  lc.setDigit(0,5,(byte)hundreds,false);
  lc.setDigit(0,6,(byte)tens,true);
  lc.setDigit(0,7,(byte)ones,false);
  delay(delaytime);
}

long stepperMove()
{
  int stepDeg;
  stepDeg = getDegrees()*5;
  while (digitalRead(triggerPin) == LOW);
  {
    digitalWrite(brakePin, HIGH);
    delay(delaytime);
    stepper.move(stepDeg);
    stepper.run();
    delay(delaytime);
    digitalWrite(finPin, HIGH);
    delay(500);
    return stepper.currentPosition();
  }
}
void printPos()
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = stepperMove()/5;
  Serial.println(d);

  if(d<0) {
    negative=true;
    d=d*-1;
  }

  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;

  if(negative) 
  {
    lc2.setChar(0,3,'-',false);
  }
  else {
    lc2.setChar(0,3,' ',false);
  }
  lc2.clearDisplay(0);
  lc2.setChar(0,0,'a',false);
  lc2.setChar(0,1,'b',false);
  lc2.setDigit(0,2,5,false);
  lc2.setDigit(0,4,(byte)thousands,false);
  lc2.setDigit(0,5,(byte)hundreds,false);
  lc2.setDigit(0,6,(byte)tens,true);
  lc2.setDigit(0,7,(byte)ones,false); 
}

void loop()
{
  degreePrint();
  stepperMove();
  printPos();
}

rvaindustrial: I've tested the motor with example codes to make sure it is wired correctly so that's not the issue. Anyhow, here's the code so far.

It could still be a wiring issue. Your code will be activating pins that the example code does not. Try running your routine without the LCD display (comment out all those sections) and see if it works. Try running it without the input device (start it up with some default values to get motion) and see if it works. Rinse and repeat until you find the problem.

I'm not a hardware expert but if you post a schematic and/or pictures of your hardware, some of the more knowledgable folks here can check for issues.

I have ran several test programs with the motor pins in the same locations and the hardware setup is working just fine. I modified the code to isolate the keypad and the stepper and I still can’t get any movement. Here’s what I have so far

/* Stepper is 200steps/rev geared 90:1 
 */
#include <AccelStepper.h>
#include <Keypad.h>
#include <LedControl.h>

LedControl lc2 = LedControl (21,20,19,1);
LedControl lc = LedControl(12,11,10,1); //one ic on pins 10 11 12
unsigned long delaytime = 100;  //delay between readings for led display
AccelStepper stepper(1,2,3); //initiate stepper, pin8=step pin9=dir 

#define triggerPin 50
#define brakePin 17
#define finPin 18

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'-','0','#'}
};
byte rowPins[ROWS] = {36,25,22,23}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {28,27,26}; //connect to the column pinouts of the keypad
//row and column pinouts weren't very easy to locate...

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  digitalWrite(brakePin, LOW);
  digitalWrite(finPin, LOW);
  pinMode(triggerPin, INPUT);
  lc.shutdown(0,false);
  lc.setIntensity(0,8);
  lc.clearDisplay(0);
  stepper.setMaxSpeed(3000);
  stepper.setAcceleration(3000);
  Serial.begin(9600);  
}

long getDegrees() //get stepper increment in degrees
//and return when # key is pressed
{
  int num = 0;
  char key = keypad.getKey();
  while(key != '#') 
  {
    switch (key) 
    {
    case NO_KEY:
      break;

    case '0': 
    case '1': 
    case '2': 
    case '3': 
    case '4':
    case '5': 
    case '6': 
    case '7': 
    case '8': 
    case '9':

      Serial.print(key);
      num = num * 10 + (key - '0');
      break;

    }
    if (key=='-'){
      num = num * -1;
    }
    key = keypad.getKey();
  }
  if (-3600 > num || num > 3600){
    return 3600;
  }
  else {  
    return num;
  }
}
/*
void degreePrint() //print stepper move increment in degrees on led display
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = getDegrees();

  if(d<0) 
  {
    negative=true;
    d=d*-1;
  }
  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;
  if(negative) 
  {
    lc.setChar(0,3,'-',false);
  }
  else 
  {
    lc.setChar(0,3,' ',false);
  }
  lc.setDigit(0,0,1,false);
  lc.setRow(0,1,0x15);
  lc.setChar(0,2,'c',false);
  lc.setDigit(0,4,(byte)thousands,false);
  lc.setDigit(0,5,(byte)hundreds,false);
  lc.setDigit(0,6,(byte)tens,true);
  lc.setDigit(0,7,(byte)ones,false);
  delay(delaytime);
}
*/
long stepperMove()
{ 
  if (stepper.distanceToGo() != 0){
    delay(500);
    long degMove = getDegrees()*5;
    stepper.moveTo(stepper.currentPosition()+degMove);
  }
    stepper.run();
      
    long newPos = stepper.currentPosition();
    Serial.println(newPos);
    return newPos;
}
/*
void printPos()
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = stepperMove()/5;
  Serial.println(d);

  if(d<0) {
    negative=true;
    d=d*-1;
  }

  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;

  if(negative) 
  {
    lc2.setChar(0,3,'-',false);
  }
  else {
    lc2.setChar(0,3,' ',false);
  }
  lc2.clearDisplay(0);
  lc2.setChar(0,0,'a',false);
  lc2.setChar(0,1,'b',false);
  lc2.setDigit(0,2,5,false);
  lc2.setDigit(0,4,(byte)thousands,false);
  lc2.setDigit(0,5,(byte)hundreds,false);
  lc2.setDigit(0,6,(byte)tens,true);
  lc2.setDigit(0,7,(byte)ones,false); 
}
*/
void loop()
{
  stepperMove();
}

I spent some time looking over your code and don't see any obvious problems. The only suggestion I can make is to start peppering your code with serial.print("I'm doing this now") type comments so you can watch where you code is going and where's it's getting stuck in a loop or skipping something it shouldn't skip.

For example I like to put "entering function x" and "leaving function x" as well as "variable=x" whenever critical variables are changed or used. With any luck a bad variable value or infinite loop will quickly become apparent by watching the serial output.

I took your advice, added a few serial.prints and managed to track it down!!! For some reason having the moveTo in the loop was tripping things up, I completely re-did the stepper function using a blocking move command and left it outside of the loop. Now the loop just reads the input signal and prints the coordinates. Thanks for the help!!!

Here’s what I ended up with:

/* Stepper is 200steps/rev geared 90:1 
 */
#include <AccelStepper.h>
#include <Keypad.h>
#include <LedControl.h>

LedControl lc2 = LedControl (21,20,19,1);
LedControl lc = LedControl(12,11,10,1); //one ic on pins 10 11 12
unsigned long delaytime = 100;  //delay between readings for led display
AccelStepper stepper(1,2,3); //initiate stepper, pin8=step pin9=dir 

#define triggerPin 13
#define brakePin 17
#define finPin 18

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'-','0','#'}
};
byte rowPins[ROWS] = {36,25,22,23}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {28,27,26}; //connect to the column pinouts of the keypad
//row and column pinouts weren't very easy to locate...

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  digitalWrite(brakePin, LOW);
  digitalWrite(finPin, LOW);
  pinMode(triggerPin, INPUT);
  lc.shutdown(0,false);
  lc.setIntensity(0,8);
  lc.clearDisplay(0);
  Serial.begin(115200);  
}

long getDegrees() //get stepper increment in degrees
//and return when # key is pressed
{
  int num = 0;
  char key = keypad.getKey();
  while(key != '#') 
  {
    switch (key) 
    {
    case NO_KEY:
      break;

    case '0': 
    case '1': 
    case '2': 
    case '3': 
    case '4':
    case '5': 
    case '6': 
    case '7': 
    case '8': 
    case '9':

      
      num = num * 10 + (key - '0');
      break;

    }
    if (key=='-'){
      num = num * -1;
    }
    key = keypad.getKey();
  }
  if (-3600 > num || num > 3600){
    return 3600;
  }
  else {  
    return num;
  }
}

void degreePrint() //print stepper move increment in degrees on led display
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = getDegrees();

  if(d<0) 
  {
    negative=true;
    d=d*-1;
  }
  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;
  if(negative) 
  {
    lc.setChar(0,3,'-',false);
  }
  else 
  {
    lc.setChar(0,3,' ',false);
  }
  lc.setDigit(0,0,1,false);
  lc.setRow(0,1,0x15);
  lc.setChar(0,2,'c',false);
  lc.setDigit(0,4,(byte)thousands,false);
  lc.setDigit(0,5,(byte)hundreds,false);
  lc.setDigit(0,6,(byte)tens,true);
  lc.setDigit(0,7,(byte)ones,false);
  delay(delaytime);
}

long stepperMove(){

  if (digitalRead(triggerPin == HIGH)){
    Serial.println("Start Signal High");
  digitalWrite(brakePin, HIGH); //releases brake in preparation for move
  delay(500);
    Serial.println("Brake Off");
  
    stepper.setMaxSpeed(3000);
    stepper.setAcceleration(3000);  
    
    if (stepper.distanceToGo() == 0){
    stepper.runToNewPosition(stepper.currentPosition()+getDegrees()*5);
    }
    stepper.run(); 
    digitalWrite(finPin, HIGH);  // sends finish signal which also cancels trigger signal
    Serial.println("Move Completed");
    long newPos = stepper.currentPosition();
    return newPos;
   }
}

void printPos()
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = stepperMove()/5;
  Serial.println(d);

  if(d<0) {
    negative=true;
    d=d*-1;
  }

  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;

  if(negative) 
  {
    lc2.setChar(0,3,'-',false);
  }
  else {
    lc2.setChar(0,3,' ',false);
  }
  lc2.clearDisplay(0);
  lc2.setChar(0,0,'a',false);
  lc2.setChar(0,1,'b',false);
  lc2.setDigit(0,2,5,false);
  lc2.setDigit(0,4,(byte)thousands,false);
  lc2.setDigit(0,5,(byte)hundreds,false);
  lc2.setDigit(0,6,(byte)tens,true);
  lc2.setDigit(0,7,(byte)ones,false); 
}

void loop()
{
  digitalRead(triggerPin);
  degreePrint();
  printPos();
}

Awesome!! I'm an amateur/hobby machinist myself so I know how much it sucks to stand there pulling handles manually. Have fun watching the machine make chips. :)

Just incase anyone views this thread in the future for a similar project I’ll update a few changes I made to the program to get it exactly where I wanted it. I had to assign a global variable that is modified by the getDegrees() function, before that I had to evoke said function everytime I needed to make a move. So now the loop reads the trigger and looks at the value of the global variable that stores the value of the move increment in order to determine whether or not to run the keypad function. I also added an lcd screen to monitor the program from the unit.
Here it is:

/* Stepper is 200steps/rev geared 90:1 
 */
#include <AccelStepper.h>
#include <Keypad.h>
#include <LedControl.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LedControl lc2 = LedControl (9,8,7,1); //9:DataIn 8:Clk 7:Cs
LedControl lc = LedControl(12,11,10,1); //12:DataIn 11:Clk 10:Cs
unsigned long delaytime = 100;  //delay between readings for led display
AccelStepper stepper(1,2,3); //initiate stepper, pin2=step pin3=dir 

const int triggerPin = 50;
const int brakePin = 17;
const int finPin = 18;
const int setPin = 46;
long degVar;
int goSignal;
int setMove;
long newPos;

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'-','0','#'}
};
byte rowPins[ROWS] = {36,25,22,23}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {28,27,26}; //connect to the column pinouts of the keypad
//row and column pinouts weren't very easy to locate...

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal_I2C lcd(0x3F,2,1,0,4,5,6,7);


void setup(){
  lcd.begin (16,2);
  lcd.setBacklightPin(3,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home ();
  pinMode(brakePin, OUTPUT);
  pinMode(finPin, OUTPUT);
  pinMode(triggerPin, INPUT);
  pinMode(setPin, INPUT);
  lc.shutdown(0,false);
  lc.setIntensity(0,8);
  lc.clearDisplay(0); 
}

long getDegrees() //get stepper increment in degrees
//and return when # key is pressed
{
  char key = keypad.getKey();
  while(key != '#') 
  {
    switch (key) 
    {
    case NO_KEY:
      break;

    case '0': 
    case '1': 
    case '2': 
    case '3': 
    case '4':
    case '5': 
    case '6': 
    case '7': 
    case '8': 
    case '9':
    case '-':

      degVar = degVar * 10 + (key - '0');
      lcd.setCursor(0,1);
      lcd.print(degVar);
      break;

    }
    if (key=='-'){
      degVar = degVar * -1;
    }
    key = keypad.getKey();
  }
  if (-3600 > degVar || degVar > 3600){
    return 3600;
  }
  else {  
    return degVar;
  }
}

void degreePrint() //print stepper move increment in degrees on led display
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = degVar;

  if(d<0) 
  {
    negative=true;
    d=d*-1;
  }
  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;
  if(negative) 
  {
    lc.setChar(0,3,'-',false);
  }
  else 
  {
    lc.setChar(0,3,' ',false);
  }
  lc.setDigit(0,0,1,false);
  lc.setRow(0,1,0x15);
  lc.setChar(0,2,'c',false);
  lc.setDigit(0,4,(byte)thousands,false);
  lc.setDigit(0,5,(byte)hundreds,false);
  lc.setDigit(0,6,(byte)tens,true);
  lc.setDigit(0,7,(byte)ones,false);
  delay(delaytime);
}

long stepperMove(){
  
  long newMove = degVar*5; 
  if (goSignal == LOW){
      if (stepper.distanceToGo() == 0);{
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Start Sig. High");
    digitalWrite(brakePin, HIGH); //releases brake in preparation for move
    delay(500);
        lcd.setCursor(0,1);
        lcd.println(" ---Brake Off---");  
    stepper.setMaxSpeed(3000);
    stepper.setAcceleration(3000);  
    stepper.runToNewPosition(stepper.currentPosition()+newMove); // moves stepper by set increment
    stepper.run(); 
    delay(500);
    digitalWrite(finPin, HIGH); // sends finish signal which also cancels trigger signal
        lcd.clear();
        lcd.print("Move Finished");  
    delay(500);
        lcd.clear();
        lcd.print("CurrentPosition:");
    long newPos = stepper.currentPosition()/5;
        lcd.setCursor(0,1);
        lcd.print(newPos);
    delay(500);
    return newPos;
      }
   }
}

void printPos() // print absolute position of indexer
{
  int ones;
  int tens;
  int hundreds;
  int thousands;
  boolean negative = false;
  int d = newPos;

  if(d<0) {
    negative=true;
    d=d*-1;
  }

  ones = d%10;
  d = d / 10;
  tens = d%10;
  d = d / 10;
  hundreds = d%10;
  d = d / 10;
  thousands=d;

  if(negative) 
  {
    lc2.setChar(0,3,'-',false);
  }
  else {
    lc2.setChar(0,3,' ',false);
  }
  lc2.setChar(0,0,'a',false);
  lc2.setChar(0,1,'b',false);
  lc2.setDigit(0,2,5,false);
  lc2.setDigit(0,4,(byte)thousands,false);
  lc2.setDigit(0,5,(byte)hundreds,false);
  lc2.setDigit(0,6,(byte)tens,true);
  lc2.setDigit(0,7,(byte)ones,false); 
}

void loop()
{

  if (degVar == 0){
    lcd.print("Enter Value:");
    getDegrees();
  }
  if (setMove = LOW){
    lcd.print("Enter Value:");
    getDegrees();
  }
  goSignal = digitalRead(triggerPin);
  degreePrint();
  printPos();
}

good day sir.. i got a project and it was quite similar to this.. here's mine i need to control the direction of the stepper motor via inputting the degrees in a 4x4 keypad i am using a unipolar stepper motor and l293 driver ic.. can you help me with the code? thanks!!