XY Plotter/CNC style interpolation project. Need great deal of help

Hello all,

I am working on what is for me a huge project to move an object around on a table from underneath using an XY Plotter.
The set up is basically an object (with a magnet on its bottom), atop a table. Under the table is a hidden XY Plotter bed moving around a corresponding magnet on the plotter's head. I am using two NEMA high torque stepper motors and Arduino.

So far:

  • I have the architecture of the plotter set up (it's a pulley and spool system)
  • I have the two stepper motors spinning
  • I have Arduino able to talk to the motors (using stepper.h and simple code from Tom Igoe)
  • I can get Processing to send signals to Arduino (so that I can test motion through keyboard commands)
  • I can move them around and do simple things. Here's a video of me trying to make it draw a "circle": MFADT Thesis components test - XY Plotter draws a circle on Vimeo
  • I own, but have not installed, 6 limit switches

Here's where I need guidance with:

  1. Interpolation: right now, my code (which is in its current incarnation here: http://breerubinmfadt.tumblr.com/post/19749648817/current-code )is very rudimentary.
    My coding skills are pretty slim and I can kind of suss out how to interpolate by running the motor a few steps one way and then running the other motor, getting pathetic-looking "pixelated" shapes (if you watch the video, you will see how non circular my circle is).
  • 1a.I found Arduino Forum this topic on moving two motors "seemingly" at the same time, but I don't fully understand how to create smoother interpolation.

  • 1b. In addition to moving in one direction, how do I get the code to interpolate into a circular fashion? I want to be able to move the thing around in tight circles

  1. Interrupting the code
    This part relates to the whole project being an interactive piece. At certain points in its routines, I want the routines to be interrupted if a proximity sensor detects a person in the room, and then it will go into other routines. For example, if it's circling casually, and a user enters the room, it stops, appears to think, and then slowly moves "toward" the person in the room. I'm going to do this with OpenCV, so I have to have the computer send 'interrupts' into the routines. At the moment, I have the code running through Processing, so that if I press a key, the motors will spin in a certain routine, but I cannot interrupt them by pressing a key until the routine is done.
  • 2a. How do I make it so that, at any point in a given "routine", the action can be stopped based on a signal?

  • 2b. How do I get the limit switches to also send interrupts?

Anyway, I know there're a lot of questions here, but maybe some of you gurus have answers/guidance for me? That would be super amazing!

The project blog is here, in case you're curious: http://breerubinmfadt.tumblr.com/

Cheers in advance!!!

You might take a look at GRBL which is CNC code for Arduino.

1b/1a: this will help you in creating circles:

for (int i = 0; i < [somenumber]; i++)
  {
    angle = i*2*3.14/100;
    Xpos = 250 + (cos(angle) * Rad);
    Ypos = 250 + (sin(angle) * Rad);
    
//Move x motor to xpos
//move y motor to ypos
//it does this for each point of the circle, so you dont have to run them at the same time
  }

2a. see next line, while loop maybe?
2b. button interrupts: http://arduino.cc/it/Reference/AttachInterrupt

Thanks! Will try it out and let you know!

1a: What you are looking for is called "Bresenham's Algorithm". Google will tell you a lot more, it's one of the most famous algorithms in computer science.

1b: There is also "Bresenham's circle algorithm" but I do not recommend it. Instead, use the code by sirbow2 above to turn the circle into straight lines.

2a: What I usually do is to have a variable called "stop", initially 0, and in every loop which needs it I have the line: if(stop) break;
Then in every loop you need to check whether you need to stop or not, eg if(bigRedStopButtonPressed())stop=1;

2b: Don't use interrupts, instead read the limit switch every time the stepper steps. It won't change at any other time :wink:

sirbow and stinner: Should I be tracking xpos and ypos somehow? Just add to them each time I spin the steppers?

Also, is there a way to interrupt beyond the limit switch? Because I will also have behavior where, when someone interacts with the project, the routine is interrupted. Is there a way to make that break?

that code for the circle gives x/y coordinates, so, you need to keep track of where the stepper is in terms of x/y then subtract the current pos minus the goal position found by the equation, to find how many steps you need to move. So:

 //draw circle at x,y 50,50
CircleXCenter = 50;
 CircleYCenter = 50; 
CurXPos = ??; //where the platform currently is in X
CurYPos = ??; //where the platform currently is in Y

for (int i = 0; i < [somenumber]; i++)
  {
//it does this for each point of the circle, so you dont have to run them at the same time
    angle = i*2*3.14/100;
    Xpos = CircleXCenter + (cos(angle) * Rad);
    Ypos = CircleYCenter + (sin(angle) * Rad);
    if(CurXPos < Xpos)
    {
           MoveXNow = Xpos - CurXPos;
    }
   else
   {
         MoveXNow = CurXPos - Xpos; 
   }
   
    if(CurYPos < Ypos)
    {
          MoveYNow = Ypos - CurYPos;
    }
   else
   {
          MoveYNow = CurYPos - Ypos; 
   }

   step(MoveXNow);
   step(MoveYNow);
  
             //<100, so -1 
   if(i == (somenumber-1)) //we are at end of for loop, save current position.
   {
       CurYPos = Ypos;
       CurXPos =Xpos ; 
   }

  }

2b: Don't use interrupts, instead read the limit switch every time the stepper steps. It won't change at any other time smiley-wink

This is only true in theory. It relies on the assumption that the only possible movement is due to the controller sending a signal to the motor. Unfortunately this is only true 99% of the time.

sirbow2, thanks so much for the recontextualizing of that circle code; I have a hard time interpreting algorithms into code...

I am making a bit of progress, but am still having trouble with the switches. where do I put the logic to check them? I have the code reading the switches, but it doesn't stop the motors. Any ideas?

Also, how do I buy you guys a beer? <3

/* Stepper Motor Controller ;  language: Wiring/Arduino
 This program drives a unipolar or bipolar stepper motor.  by Tom Igoe */
/* significant help from arduino superstars: sirbow2, 
*/

#include <Stepper.h>

#define motorSteps 200     // change this depending on the number of steps
#define motor2Steps 200     // change this depending on the number of steps
// per revolution of your motor


#define motorPin1 2
#define motorPin2 3
#define motorPin3 4
#define motorPin4 5
#define motorPin6 8
#define motorPin7 9
#define motorPin8 10
#define motorPin9 11


int reading = 0;
int previous = LOW;
long time = 0;         // the last time the output pin was toggled
long debounce = 50;   // the debounce time, increase if the output flickers
int state = HIGH;    

//set pin numbers

int xStopMax = A3;
int xStopMin = A2;
int yStopMin = A1;
int yStopMax = A0;


int xPos;
int yPos;
boolean xIs0;
boolean xIsMax;
boolean yIs0;
boolean yIsMax;


// initialize of the Stepper library:
Stepper yAxis(motorSteps, motorPin1,motorPin2, motorPin3, motorPin4); 
Stepper xAxis(motor2Steps, motorPin6,motorPin7, motorPin8, motorPin9); 




void setup() {

  // set the motor speed at 60 RPMS:
  xAxis.setSpeed(60); //x
  yAxis.setSpeed(60); //y

  //set limit switches to analog inputs
  pinMode(xStopMin, INPUT);
  pinMode(xStopMin, INPUT);
  pinMode(xStopMin, INPUT); 
  pinMode(xStopMin, INPUT);

  // Initialize the Serial port:
  Serial.begin(9600);
}

void loop() {
  //check limit switches
  if(digitalRead(xStopMin) == HIGH){
    xIs0 == true;  
  }
  else xIs0 == false;

  if(digitalRead(xStopMax) == HIGH){
    xIsMax == true;  
  }
  else xIsMax == false;

  if(digitalRead(yStopMin) == HIGH){
    yIs0 == true;  
  }
  else yIs0 == false;

  if(digitalRead(yStopMax) == HIGH){
    yIsMax == true;  
  }
  else yIsMax == false;



  char val=0;
  if(Serial.available()) val = Serial.read();

  //keyboard control  
  switch(val){
  case 'N':
    Serial.read();
      moveN(200);
    break;

  case 'S':
    Serial.read();
      moveS(200);
    break;

  case 'E':
    Serial.read();
      moveE(200);
    break;

  case 'W':
    Serial.read();
      moveW(200);
    break; 


    //diagonal (moving motors almost at the same time)      
  case 'J': //NE
    Serial.read();
          moveNE(200);
    break;
  case 'H': //NW
     Serial.read();
          moveNW(200);
    break;

  case 'X': //SE
    Serial.read();
          moveSE(200);
    break;
  case 'Z': //SW
     Serial.read();
          moveSW(200);
    break;

  case 'C': //SW
     Serial.read();
          moveCirc();
    break;

  default:
    Serial.read();
    delay(10);
    break;
  }
}

void moveE(int numSteps){
  //straight up down left right
    for(int s=0; s<numSteps; s++){
      xAxis.step(1);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
  }  
  delay(100);    
}

void moveW(int numSteps){
    for(int s=0; s<numSteps; s++){
      xAxis.step(-1);  
    }
  delay(100);    
}

void moveN(int numSteps){
    for(int s=0; s<numSteps; s++){
      yAxis.step(1);  
    }
  delay(100);    
}  
   
void moveS(int numSteps){
    for(int s=0; s<numSteps; s++){
      yAxis.step(-1);  
    }
  delay(100);    
}    

//diagonals
void moveNE(int numSteps){    
    for(int s=0; s<numSteps; s++)
    {
      yAxis.step(1);
      xAxis.step(1);
    }     
  delay(100);    
}

void moveSE(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      yAxis.step(-1);
      xAxis.step(1);
    }     
  delay(100);    
  }
void moveSW(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      yAxis.step(-1);
      xAxis.step(-1);
    }     
  delay(100);    
  }
void moveNW(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      yAxis.step(1);
      xAxis.step(-1);
    } 
    delay(100);    
  }

void moveCirc(){
   //draw circle at x,y 50,50
    int CircleXCenter = 10;
    int CircleYCenter = 10; 
    int CurXPos = xPos; //where the platform currently is in X
    int CurYPos = yPos; //where the platform currently is in Y
    int Rad = 20;
    
    for (int i = 0; i < 200; i++)
      {
    //it does this for each point of the circle, so you dont have to run them at the same time
        int angle = i*2*3.14/100;
        xPos = CircleXCenter + (cos(angle) * Rad);
        yPos = CircleYCenter + (sin(angle) * Rad);
        if(CurXPos < xPos)
         {
               xAxis.step(xPos - CurXPos);
              //movexnow = Xpos - CurXPos;
          }
       else
       {
               xAxis.step(CurXPos - xPos); 
           //MoveXNow = CurXPos - Xpos; 
       }
       
        if(CurYPos < yPos)
        {
               yAxis.step(yPos - CurYPos); 
             //   MoveYNow = Ypos - CurYPos;
        }
       else
       {
               yAxis.step(CurYPos - yPos); 
              //MoveYNow = CurYPos - Ypos; 
       }
    
       //step(MoveXNow);
       //step(MoveYNow);
      
                 //<100, so -1 
       if(i == (200-1)) //we are at end of for loop, save current position.
       {
           CurYPos = yPos;
           CurXPos = xPos ; 
       }
    
      }
      
}

One way would be to check the relevant end stop before making each step, eg:

 void moveE(int numSteps){
  //straight up down left right
    for(int s=0; s<numSteps; s++){
      if(digitalRead(xStopMax) == HIGH) break; // break out of the loop if arm is already at the end stop      
      xAxis.step(1);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
  }  
  delay(100);    
}

and similar for all the other places the motors are stepped.

I have a hard time interpreting algorithms into code...

i ran into the same issues when attempting to draw circles :stuck_out_tongue:

 //set limit switches to analog inputs
 pinMode(xStopMin, INPUT);
 pinMode(xStopMin, INPUT);
 pinMode(xStopMin, INPUT);
 pinMode(xStopMin, INPUT);

you have "xStopMin" for all those :stuck_out_tongue: should be:

 //set limit switches to DIGITAL inputs
 pinMode(xStopMax, INPUT);
 pinMode(xStopMin, INPUT);
 pinMode(yStopMin, INPUT);
 pinMode(yStopMax, INPUT);

why this?

void moveE(int numSteps){
  //straight up down left right
    for(int s=0; s<numSteps; s++){
      xAxis.step(1);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
  }  
  delay(100);    
}

thats the same as

void moveE(int numSteps){
  //straight up down left right
  xAxis.step(numSteps);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
  delay(100);    
}

right?

these are good though, need the one step at a time :):

//diagonals
void moveNE(int numSteps){    
    for(int s=0; s<numSteps; s++)
    {
      yAxis.step(1);
      xAxis.step(1);
    }     
  delay(100);    
}

for the buttons, just make them interrupts(Arduino Playground - PinChangeInt); this allows you to use A0-5 as interrupts. you also need to debounce them(fix the hardware error in side the switch) Digitalduino: Arduino Software and Hardware Based Button Debouncing i suppose you could just do regular button debouncing in the loop, but that would waste processing time each loop, whereas interrupts wouldn't.

let me know if you need help with this.

for checking switch status and stoppign the steppers when need be try this:

void moveE(int numSteps){
  //straight up down left right
int s = 0;
while(xMinBtn ==false && xMaxBtn ==false && s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
{
      xAxis.step(1);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
      s++;
  }  
  delay(100);    
}

Stimmer: the code worked fairly well with the if statements;
Also thanks for catching the blurry-eyed mistake I made with setting the input pins (or not)

sirbow2: I tried the while loop you gave me in the last post, but the limit switches didn't seem to stop the turning of the motor. Any ideas? I only changed it for the E (moving East) code, and JUST IN CASE I messed up on my order, tried all four switches, but nothing stopped the motor from trying to spin.

/* Stepper Motor Controller ;  language: Wiring/Arduino
 This program drives a unipolar or bipolar stepper motor.  by Tom Igoe */
/* significant help from arduino forum superstars: sirbow2, stimmer
*/

#include <Stepper.h>

#define motorSteps 200     // change this depending on the number of steps
#define motor2Steps 200     // change this depending on the number of steps
// per revolution of your motor


#define motorPin1 2
#define motorPin2 3
#define motorPin3 4
#define motorPin4 5
#define motorPin6 8
#define motorPin7 9
#define motorPin8 10
#define motorPin9 11


int reading = 0;
int previous = LOW;
long time = 0;         // the last time the output pin was toggled
long debounce = 50;   // the debounce time, increase if the output flickers
int state = HIGH;    

//set pin numbers

int xStopMax = A1;
int xStopMin = A0;
int yStopMin = A2;
int yStopMax = A3;



int xPos;
int yPos;
boolean xIs0;
boolean xIsMax;
boolean yIs0;
boolean yIsMax;


// initialize of the Stepper library:
Stepper yAxis(motorSteps, motorPin1,motorPin2, motorPin3, motorPin4); 
Stepper xAxis(motor2Steps, motorPin6,motorPin7, motorPin8, motorPin9); 




void setup() {

  // set the motor speed at 60 RPMS:
  xAxis.setSpeed(60); //x
  yAxis.setSpeed(60); //y

  //set limit switches to analog inputs
  pinMode(xStopMin, INPUT);
  pinMode(xStopMax, INPUT);
  pinMode(yStopMin, INPUT); 
  pinMode(yStopMax, INPUT);

  // Initialize the Serial port:
  Serial.begin(9600);
}

void loop() {
  //check limit switches
  if(digitalRead(xStopMin) == HIGH){
    xIs0 == true;  
    Serial.println("xMin");
  }
  else xIs0 == false;

  if(digitalRead(xStopMax) == HIGH){
    xIsMax == true;  
    Serial.println("xMax");
  }
  else xIsMax == false;

  if(digitalRead(yStopMin) == HIGH){
    yIs0 == true;  
    Serial.println("yMin");
   }
  else yIs0 == false;

  if(digitalRead(yStopMax) == HIGH){
    yIsMax == true;  
    Serial.println("yMax");
  }
  else yIsMax == false;



  char val=0;
  if(Serial.available()) val = Serial.read();

  //keyboard control  
  switch(val){
  case 'N':
    Serial.read();
      moveN(200);
    break;

  case 'S':
    Serial.read();
      moveS(200);
    break;

  case 'E':
    Serial.read();
      moveE(200);
    break;

  case 'W':
    Serial.read();
      moveW(200);
    break; 


    //diagonal (moving motors almost at the same time)      
  case 'J': //NE
    Serial.read();
          moveNE(200);
    break;
  case 'H': //NW
     Serial.read();
          moveNW(200);
    break;

  case 'X': //SE
    Serial.read();
          moveSE(200);
    break;
  case 'Z': //SW
     Serial.read();
          moveSW(200);
    break;

  case 'C': //SW
     Serial.read();
          moveCirc();
    break;
  
  case 'Q': //reset to 0,0 
     Serial.read();
         while(xStopMin != true && yStopMin != true);
         moveN(100);
         break;
         moveE(100);
     break;

  default:
    Serial.read();
    delay(10);
    break;
  }
}
//movement functions

  //first, straight up down left right
void moveE(int numSteps){
  int s = 0;
  while(xIs0 ==false && xIsMax ==false && s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
  {
        xAxis.step(-1);
        s++;
    }  
    delay(100);    
}

void moveW(int numSteps){
    for(int s=0; s<numSteps; s++){
      if(digitalRead(xStopMax) == HIGH) break;
      else xAxis.step(1);  
    }
  delay(100);    
}

void moveN(int numSteps){
    for(int s=0; s<numSteps; s++){
      if(digitalRead(yStopMin) == HIGH) break;
      else yAxis.step(-1);  
    }
  delay(100);    
}  
   
void moveS(int numSteps){
    for(int s=0; s<numSteps; s++){
      if(digitalRead(yStopMax) == HIGH) break;
       else yAxis.step(1);  
    }
  delay(100);    
}    

//diagonals
void moveNE(int numSteps){    
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMax) == HIGH || digitalRead(yStopMax) == HIGH) break;
      else{
        yAxis.step(-1);
       xAxis.step(-1);
      }
    }     
  delay(100);    
}

void moveSE(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMax) == HIGH) break;
      
     else{yAxis.step(-1);
      xAxis.step(1);
  }
}     
  delay(100);    
  }
void moveSW(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMin) == HIGH || digitalRead(yStopMin)) break;
      yAxis.step(-1);
      xAxis.step(-1);
    }     
  delay(100);    
  }
void moveNW(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMin) == HIGH) break;
      if(digitalRead(yStopMax) == HIGH) break;
      yAxis.step(-1);
      xAxis.step(1);
      
    } 
    delay(100);    
  }

void moveCirc(){
   //draw circle at x,y 50,50
    int CircleXCenter = 10;
    int CircleYCenter = 10; 
    int CurXPos = xPos; //where the platform currently is in X
    int CurYPos = yPos; //where the platform currently is in Y
    int Rad = 20;
    
    for (int i = 0; i < 200; i++)
      {
    //it does this for each point of the circle, so you dont have to run them at the same time
        int angle = i*2*3.14/100;
        xPos = CircleXCenter + (cos(angle) * Rad);
        yPos = CircleYCenter + (sin(angle) * Rad);
        if(CurXPos < xPos)
         {
               xAxis.step(xPos - CurXPos);
              //movexnow = Xpos - CurXPos;
          }
       else
       {
               xAxis.step(CurXPos - xPos); 
           //MoveXNow = CurXPos - Xpos; 
       }
       
        if(CurYPos < yPos)
        {
               yAxis.step(yPos - CurYPos); 
             //   MoveYNow = Ypos - CurYPos;
        }
       else
       {
               yAxis.step(CurYPos - yPos); 
              //MoveYNow = CurYPos - Ypos; 
       }
    
       //step(MoveXNow);
       //step(MoveYNow);
      
                 //<100, so -1 
       if(i == (200-1)) //we are at end of for loop, save current position.
       {
           CurYPos = yPos;
           CurXPos = xPos ; 
       }
    
      }
      
}

Also, I tried the arduino example debounce code, but the logic has it set the switch to high only once when it's been hit; I need it to be persistent, just in case the arm is still hitting the switch.

Thanks!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

ALSO:

I am having trouble keeping track of xPos and yPos. I am trying to keep track of them when I step my motor.
Any ideas?

/* Stepper Motor Controller ;  language: Wiring/Arduino
 This program drives a unipolar or bipolar stepper motor.  by Tom Igoe */
/* significant help from arduino forum superstars: sirbow2, stimmer
*/

#include <Stepper.h>

#define motorSteps 200     // change this depending on the number of steps
#define motor2Steps 200     // change this depending on the number of steps
// per revolution of your motor


#define motorPin1 2
#define motorPin2 3
#define motorPin3 4
#define motorPin4 5
#define motorPin6 8
#define motorPin7 9
#define motorPin8 10
#define motorPin9 11


int reading = 0;
int previous = LOW;
long time = 0;         // the last time the output pin was toggled
long debounce = 50;   // the debounce time, increase if the output flickers
int state = HIGH;    

//set pin numbers

int xStopMax = A1;
int xStopMin = A0;
int yStopMin = A3;
int yStopMax = A2;



int xPos;
int yPos;
boolean xIs0;
boolean xIsMax;
boolean yIs0;
boolean yIsMax;


// initialize of the Stepper library:
Stepper yAxis(motorSteps, motorPin1,motorPin2, motorPin3, motorPin4); 
Stepper xAxis(motor2Steps, motorPin6,motorPin7, motorPin8, motorPin9); 




void setup() {

  // set the motor speed at 60 RPMS:
  xAxis.setSpeed(60); //x
  yAxis.setSpeed(60); //y

  //set limit switches to analog inputs
  pinMode(xStopMin, INPUT);
  pinMode(xStopMax, INPUT);
  pinMode(yStopMin, INPUT); 
  pinMode(yStopMax, INPUT);
  
  xPos = 0;
  yPos = 0;

  // Initialize the Serial port:
  Serial.begin(9600);
}

void loop() {
  //check limit switches
  if(digitalRead(xStopMin) == HIGH){
    xIs0 == true;  
    xPos = 0;
    Serial.println("xMin");
  }
  else xIs0 == false;

  if(digitalRead(xStopMax) == HIGH){
    xIsMax == true;  
    Serial.println("xMax");
  }
  else xIsMax == false;

  if(digitalRead(yStopMin) == HIGH){
    yIs0 == true;  
    Serial.println("yMin");
    yPos = 0;
    
   }
  else yIs0 == false;

  if(digitalRead(yStopMax) == HIGH){
    yIsMax == true;  
    Serial.println("yMax");
  }
  else yIsMax == false;



  char val=0;
  if(Serial.available()) val = Serial.read();

  //keyboard control  
  switch(val){
  case 'N':
    Serial.read();
      moveN(200);
    break;

  case 'S':
    Serial.read();
      moveS(200);
    break;

  case 'E':
    Serial.read();
      moveE(200);
    break;

  case 'W':
    Serial.read();
      moveW(200);
    break; 



    //diagonal (moving motors almost at the same time)      
  case 'J': //NE
    Serial.read();
          moveNE(200);
    break;
  case 'H': //NW
     Serial.read();
          moveNW(200);
    break;

  case 'X': //SE
    Serial.read();
          moveSE(200);
    break;
  case 'Z': //SW
     Serial.read();
          moveSW(200);
    break;

  case 'C': //SW
     Serial.read();
          moveCirc();
    break;
  
  
  //resets
  case 'Q': //reset to 0,0 
     Serial.read();
         moveN(100);
         moveE(100);
     break;
     


 //debugs
   case 'P':
     Serial.read();
       Serial.print("x position: ");
       Serial.println(xPos);
       Serial.println("y position: ");
       Serial.println(yPos);
    break;

  default:
    Serial.read();
    delay(10);
    break;
  }
}
//movement functions

  //first, str  aight up down left right
void moveE(int numSteps){
  for(int s=0; s<numSteps; s++){
      if(digitalRead(xStopMin) == HIGH) break; // break out of the loop if arm is already at the end stop      
      xAxis.step(1);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
  }  
  xPos += numSteps;
  
}

void moveW(int numSteps){
    for(int s=0; s<numSteps; s++){
      if(digitalRead(xStopMax) == HIGH) break;
      else xAxis.step(-1);  
    }
  xPos += -numSteps;
}

void moveN(int numSteps){
    for(int s=0; s<numSteps; s++){
      if(digitalRead(yStopMin) == HIGH) break;
      else yAxis.step(-1);  
    }
  yPos += -numSteps;
}  
   
void moveS(int numSteps){
    for(int s=0; s<numSteps; s++){
      if(digitalRead(yStopMax) == HIGH) break;
       else yAxis.step(1);  
    }
    yPos += -numSteps ;
}    

//diagonals
void moveNE(int numSteps){    
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMax) == HIGH || digitalRead(yStopMax) == HIGH) break;
      else{
        yAxis.step(-1);
       xAxis.step(1);
      }
    }     
  //////////////delay(100);    
}

void moveSE(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMax) == HIGH) break;
      
     else{yAxis.step(-1);
      xAxis.step(1);
  }
}     
  //////////////delay(100);    
  }
void moveSW(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMin) == HIGH || digitalRead(yStopMin)) break;
      yAxis.step(1);
      xAxis.step(-1);
    }     
  //////////////delay(100);    
  }
void moveNW(int numSteps){
    for(int s=0; s<numSteps; s++)
    {
      if(digitalRead(xStopMin) == HIGH) break;
      if(digitalRead(yStopMax) == HIGH) break;
      yAxis.step(-1);
      xAxis.step(-1);
      
    } 
    //////////////delay(100);    
  }

void moveCirc(){
   //draw circle at x,y 50,50
    int CircleXCenter = 2;
    int CircleYCenter = 2; 
    int CurXPos = xPos; //where the platform currently is in X
    int CurYPos = yPos; //where the platform currently is in Y
    int Rad = 1;
    
    
    
    
    for (int i = 0; i < 360; i++)
      {
    //it does this for each point of the circle, so you dont have to run them at the same time
       float 
       angle = i*2*3.14/360;
        xPos = CircleXCenter + (cos(angle) * Rad);
        yPos = CircleYCenter + (sin(angle) * Rad);
        if(CurXPos < xPos)
         {
           
               xAxis.step(xPos - CurXPos);
              //movexnow = Xpos - CurXPos;
          }
       else
       {
               xAxis.step(xPos - CurXPos); 
           //MoveXNow = CurXPos - Xpos; 
       }
       
        if(CurYPos < yPos)
        {
               yAxis.step(yPos - CurYPos); 
             //   MoveYNow = Ypos - CurYPos;
        }
       else
       {
               yAxis.step(yPos - CurYPos
               ); 
             //MoveYNow = CurYPos - Ypos; 
       }
    
      // step(xAxis);
       //step(yAxis);
      
                 //<100, so -1 
       if(i == (360-1)) //we are at end of for loop, save current position.
       {
           CurYPos = yPos;
           CurXPos = xPos ; 
       }
    
      }
      
}

I tried the while loop you gave me in the last post, but the limit switches didn't seem to stop the turning of the motor.

because its not reading the button value every loop of the while. that code was meant for interrupts.
this could be a quick fix while you get interrupts working:

void moveE(int numSteps){
  //straight up down left right
int s = 0;
while(!digitalRead(xStopMin) && !digitalRead(xStopMax)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
{
      xAxis.step(1);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
      s++;
  }  
  delay(100);    
}

for keeping track of positon these look good:

void moveE(int numSteps){
  for(int s=0; s<numSteps; s++){
      if(digitalRead(xStopMin) == HIGH) break; // break out of the loop if arm is already at the end stop      
      xAxis.step(1);//moves arm AWAY from motors (takes 1800_ at 60 speed) to traverse the whole bed  
  }  
  xPos += numSteps;
  
}

void moveW(int numSteps){
    for(int s=0; s<numSteps; s++){
      if(digitalRead(xStopMax) == HIGH) break;
      else xAxis.step(-1);  
    }
  xPos += -numSteps;
}

maybe xPos -=numSteps; on the last one instead of xPos += -numSteps; but either way they should work...

I am having trouble keeping track of xPos and yPos.

more specific please

Thanks for the reply!

I am having trouble tracking xpos and ypos. For example, I advance the motors a bit to a position, and then I call up a read out of xPos and yPos and it always tells me they are at (0,0)...

I think (am I right?) that I correctly have to ascertain the xPos and yPos in order for the circle code to work, because it relies on knowing where it is?

Here's the current code:

/* Stepper Motor Controller ;  language: Wiring/Arduino
 This program drives a unipolar or bipolar stepper motor.  by Tom Igoe */
/* significant help from arduino forum superstars: sirbow2, stimmer
*/

#include <Stepper.h>

#define motorSteps 200     // change this depending on the number of steps
#define motor2Steps 200     // change this depending on the number of steps
// per revolution of your motor


#define motorPin1 2
#define motorPin2 3
#define motorPin3 4
#define motorPin4 5
#define motorPin6 8
#define motorPin7 9
#define motorPin8 10
#define motorPin9 11


int reading = 0;
int previous = LOW;
long time = 0;         // the last time the output pin was toggled
long debounce = 50;   // the debounce time, increase if the output flickers
int state = HIGH;    

//set pin numbers

int xStopMax = A1;
int xStopMin = A0;
int yStopMin = A3;
int yStopMax = A2;



int xPos;
int yPos;
boolean xIs0;
boolean xIsMax;
boolean yIs0;
boolean yIsMax;


// initialize of the Stepper library:
Stepper yAxis(motorSteps, motorPin1,motorPin2, motorPin3, motorPin4); 
Stepper xAxis(motor2Steps, motorPin6,motorPin7, motorPin8, motorPin9); 




void setup() {

  // set the motor speed at 60 RPMS:
  xAxis.setSpeed(60); //x
  yAxis.setSpeed(60); //y

  //set limit switches to analog inputs
  pinMode(xStopMin, INPUT);
  pinMode(xStopMax, INPUT);
  pinMode(yStopMin, INPUT); 
  pinMode(yStopMax, INPUT);
  
  xPos = 0;
  yPos = 0;

  // Initialize the Serial port:
  Serial.begin(9600);
}

void loop() {
  //check limit switches
  if(digitalRead(xStopMin) == HIGH){
    xIs0 == true;  
    xPos = 0;
    Serial.println("xMin");
  }
  else xIs0 == false;

  if(digitalRead(xStopMax) == HIGH){
    xIsMax == true;  
    Serial.println("xMax");
  }
  else xIsMax == false;

  if(digitalRead(yStopMin) == HIGH){
    yIs0 == true;  
    Serial.println("yMin");
    yPos = 0;
    
   }
  else yIs0 == false;

  if(digitalRead(yStopMax) == HIGH){
    yIsMax == true;  
    Serial.println("yMax");
  }
  else yIsMax == false;



  char val=0;
  if(Serial.available()) val = Serial.read();

  //keyboard control  
  switch(val){
  case 'N':
    Serial.read();
      moveN(200);
    break;

  case 'S':
    Serial.read();
      moveS(200);
    break;

  case 'E':
    Serial.read();
      moveE(200);
    break;

  case 'W':
    Serial.read();
      moveW(200);
    break; 



    //diagonal (moving motors almost at the same time)      
  case 'J': //NE
    Serial.read();
          moveNE(200);
    break;
  case 'H': //NW
     Serial.read();
          moveNW(200);
    break;

  case 'X': //SE
    Serial.read();
          moveSE(200);
    break;
  case 'Z': //SW
     Serial.read();
          moveSW(200);
    break;

  case 'C': //SW
     Serial.read();
          moveCirc();
    break;
  
  
  //resets
  case 'Q': //reset to 0,0 
     Serial.read();
         moveN(100);
         moveE(100);
     break;
     


 //debugs
   case 'P':
     Serial.read();
       Serial.print("x position: ");
       Serial.println(xPos);
       Serial.println("y position: ");
       Serial.println(yPos);
    break;

  default:
    Serial.read();
    delay(10);
    break;
  }
}
//movement functions

  //first, str  aight up down left right
void moveE(int numSteps){
    int s = 0;
    while(!digitalRead(xStopMax)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          xAxis.step(1);
          s++;
      }  
      delay(100);    
    xPos += numSteps;
 }

void moveW(int numSteps){
     int s = 0;
    while(!digitalRead(xStopMin)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          xAxis.step(-1);
          s++;
      }  
      delay(100);    
    xPos -= numSteps;
}

void moveN(int numSteps){
   int s = 0;
    while(!digitalRead(yStopMax)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          yAxis.step(-1);
          s++;
      }  
      delay(100);    
    yPos += numSteps;
}  
   
void moveS(int numSteps){
  int s = 0;
    while(!digitalRead(yStopMin)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          yAxis.step(1);
          s++;
      }  
      delay(100);    
    yPos -= numSteps;
}    

//diagonals
void moveNE(int numSteps){    
  int s=0; 
  while(!digitalRead(xStopMax) && !digitalRead(yStopMin) && s<numSteps); 
    for(int s=0; s<numSteps; s++)
    {
        yAxis.step(-1);
        xAxis.step(1);
      }
   xPos += numSteps;
   yPos -= numSteps;
 }  
 

void moveSE(int numSteps){
   int s=0; 
  while(!digitalRead(xStopMax) && !digitalRead(yStopMax) && s<numSteps); 
    for(int s=0; s<numSteps; s++)
    {
        yAxis.step(1);
        xAxis.step(1);
      }
   xPos += numSteps;
   yPos += numSteps;
 }  
  
  
void moveSW(int numSteps){
  int s=0; 
    while(!digitalRead(xStopMin) && !digitalRead(yStopMax) && s<numSteps); 
      for(int s=0; s<numSteps; s++)
      {
          yAxis.step(1);
          xAxis.step(-1);
        }
   xPos -= numSteps;
   yPos += numSteps;
    }  
void moveNW(int numSteps){
  int s=0; 
    while(!digitalRead(xStopMin) && !digitalRead(yStopMin) && s<numSteps); 
      for(int s=0; s<numSteps; s++)
      {
          yAxis.step(-1);
          xAxis.step(-1);
        }
   xPos -= numSteps;
   yPos -= numSteps;
    }  

void moveCirc(){
   //draw circle at x,y 50,50
    int CircleXCenter = 2;
    int CircleYCenter = 2; 
    int CurXPos = xPos; //where the platform currently is in X
    int CurYPos = yPos; //where the platform currently is in Y
    int Rad = 1;
    
    
    
    
    for (int i = 0; i < 360; i++)
      {
    //it does this for each point of the circle, so you dont have to run them at the same time
       float 
       angle = i*2*3.14/360;
        xPos = CircleXCenter + (cos(angle) * Rad);
        yPos = CircleYCenter + (sin(angle) * Rad);
        if(CurXPos < xPos)
         {
           
               xAxis.step(xPos - CurXPos);
              //movexnow = Xpos - CurXPos;
          }
       else
       {
               xAxis.step(xPos - CurXPos); 
           //MoveXNow = CurXPos - Xpos; 
       }
       
        if(CurYPos < yPos)
        {
               yAxis.step(yPos - CurYPos); 
             //   MoveYNow = Ypos - CurYPos;
        }
       else
       {
               yAxis.step(yPos - CurYPos
               ); 
             //MoveYNow = CurYPos - Ypos; 
       }
    
      // step(xAxis);
       //step(yAxis);
      
                 //<100, so -1 
       if(i == (360-1)) //we are at end of for loop, save current position.
       {
           CurYPos = yPos;
           CurXPos = xPos ; 
       }
    
      }
      
}

Get the debug code for 'P' to show you xIs0 and yIs0. Depending on how those switches are wired/set, you could be setting xPos & YPos to zero on every iteration of loop.

There are some places where you have used == where you should have used =
Where you assign to a variable you need to use = not ==

Change this:

  if(digitalRead(xStopMin) == HIGH){
    xIs0 == true;  
    xPos = 0;
    Serial.println("xMin");
  }
  else xIs0 == false;

to this:

  if(digitalRead(xStopMin) == HIGH){
    xIs0 = true;  
    xPos = 0;
    Serial.println("xMin");
  }
  else xIs0 = false;

and similar for the other end stop checks. (the == in the if is correct)
Look at = - Arduino Reference and http://arduino.cc/en/Reference/If for more info on when to use = or ==

I don't think this is the cause of the problem of xPos and yPos always reading 0, but it can't hurt to fix it.

yes as he says "==" is testing, "=" is setting values:
if(something == something)//testing
value = value2; //setting value equal to value 2

if(digitalRead(xStopMin) == HIGH){
    xIs0 = true;  
    xPos = 0;
    Serial.println("xMin");
  }

you say xPos = 0;, if you accidentally pressed the button,. it may reset the value, but i dont hink this is your issue.

put _Serial.println()_s around where the xPos and yPos value would change and see if they make sense.

stimmer, sirbow, wildbill --- thanks for all your help so far!

I am getting a readout for xpos and ypos, but now that I have fixed the xIs0 == true to xIs0 = true, the switches seem to be seriously misbehaving. I am not sure what's going on, but they seem to constantly read out high.

/* Stepper Motor Controller ;  language: Wiring/Arduino
 This program drives a unipolar or bipolar stepper motor.  by Tom Igoe */
/* significant help from arduino forum superstars: sirbow2, stimmer
*/

#include <Stepper.h>

#define motorSteps 200     // change this depending on the number of steps
#define motor2Steps 200     // change this depending on the number of steps
// per revolution of your motor


#define motorPin1 2
#define motorPin2 3
#define motorPin3 4
#define motorPin4 5
#define motorPin6 8
#define motorPin7 9
#define motorPin8 10
#define motorPin9 11


int reading = 0;
int previous = LOW;
long time = 0;         // the last time the output pin was toggled
long debounce = 50;   // the debounce time, increase if the output flickers
int state = HIGH;    

//set pin numbers

int xStopMax = A1;
int xStopMin = A0;
int yStopMin = A3;
int yStopMax = A2;



int xPos;
int yPos;
boolean xIs0;
boolean xIsMax;
boolean yIs0;
boolean yIsMax;


// initialize of the Stepper library:
Stepper yAxis(motorSteps, motorPin1,motorPin2, motorPin3, motorPin4); 
Stepper xAxis(motor2Steps, motorPin6,motorPin7, motorPin8, motorPin9); 




void setup() {

  // set the motor speed at 60 RPMS:
  xAxis.setSpeed(60); //x
  yAxis.setSpeed(60); //y

  //set limit switches to analog inputs
  pinMode(xStopMin, INPUT);
  pinMode(xStopMax, INPUT);
  pinMode(yStopMin, INPUT); 
  pinMode(yStopMax, INPUT);
  
  xPos = 0;
  yPos = 0;

  // Initialize the Serial port:
  Serial.begin(9600);
}

void loop() {
  //check limit switches
  if(digitalRead(xStopMin) == HIGH){
 
    
    xIs0 = true;  
    xPos = 0;
    Serial.println("xMin");
  }
  else xIs0 = false;

 
 
  if(digitalRead(xStopMax) == HIGH){
    xIsMax = true;  
    Serial.println("xMax");
  }
  else xIsMax = false;

  if(digitalRead(yStopMin) == HIGH){
    yIs0 = true;  
    Serial.println("yMin");
    yPos = 0;
    
   }
  else yIs0 = false;

  if(digitalRead(yStopMax) == HIGH){
    yIsMax = true;  
    Serial.println("yMax");
  }
  else yIsMax = false;



  char val=0;
  if(Serial.available()) val = Serial.read();

  //keyboard control  
  switch(val){
  case 'N':
    Serial.read();
      moveN(200);
    break;

  case 'S':
    Serial.read();
      moveS(200);
    break;

  case 'E':
    Serial.read();
      moveE(200);
    break;

  case 'W':
    Serial.read();
      moveW(200);
    break; 



    //diagonal (moving motors almost at the same time)      
  case 'J': //NE
    Serial.read();
          moveNE(200);
    break;
  case 'H': //NW
     Serial.read();
          moveNW(200);
    break;

  case 'X': //SE
    Serial.read();
          moveSE(200);
    break;
  case 'Z': //SW
     Serial.read();
          moveSW(200);
    break;

  case 'C': //SW
     Serial.read();
          moveCirc();
    break;
  
  
  //resets
  case 'Q': //reset to 0,0 
     Serial.read();
         moveN(100);
         moveE(100);
     break;
     


 //debugs
   case 'P':
     Serial.read();
       Serial.print("x position: ");
       Serial.println(xPos);
       Serial.println("y position: ");
       Serial.println(yPos);
    break;

  default:
    Serial.read();
    delay(10);
    break;
  }
}
//movement functions

  //first, str  aight up down left right
void moveE(int numSteps){
    int s = 0;
    while(!digitalRead(xStopMax)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          xAxis.step(1);
          s++;
      }  
      delay(100);    
     xPos += numSteps;
     Serial.println(xPos);
     Serial.println(yPos);
 }
 

void moveW(int numSteps){
     int s = 0;
    while(!digitalRead(xStopMin)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          xAxis.step(-1);
          s++;
      }  
      delay(100);    
    xPos -= numSteps;
}

void moveN(int numSteps){
   int s = 0;
    while(!digitalRead(yStopMax)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          yAxis.step(-1);
          s++;
      }  
      delay(100);    
    yPos += numSteps;
}  
   
void moveS(int numSteps){
  int s = 0;
    while(!digitalRead(yStopMin)&& s<numSteps)//checks the button each step, also checks to see if it has moved s amount of steps
    {
          yAxis.step(1);
          s++;
      }  
      delay(100);    
    yPos -= numSteps;
}    

//diagonals
void moveNE(int numSteps){    
  int s=0; 
  while(!digitalRead(xStopMax) && !digitalRead(yStopMin) && s<numSteps); 
    for(int s=0; s<numSteps; s++)
    {
        yAxis.step(-1);
        xAxis.step(1);
      }
   xPos += numSteps;
   yPos -= numSteps;
 }  
 

void moveSE(int numSteps){
   int s=0; 
  while(!digitalRead(xStopMax) && !digitalRead(yStopMax) && s<numSteps); 
    for(int s=0; s<numSteps; s++)
    {
        yAxis.step(1);
        xAxis.step(1);
      }
   xPos += numSteps;
   yPos += numSteps;
 }  
  
  
void moveSW(int numSteps){
  int s=0; 
    while(!digitalRead(xStopMin) && !digitalRead(yStopMax) && s<numSteps); 
      for(int s=0; s<numSteps; s++)
      {
          yAxis.step(1);
          xAxis.step(-1);
        }
   xPos -= numSteps;
   yPos += numSteps;
    }  
void moveNW(int numSteps){
  int s=0; 
    while(!digitalRead(xStopMin) && !digitalRead(yStopMin) && s<numSteps); 
      for(int s=0; s<numSteps; s++)
      {
          yAxis.step(-1);
          xAxis.step(-1);
        }
   xPos -= numSteps;
   yPos -= numSteps;
    }  

void moveCirc(){
   //draw circle at x,y 50,50
    int CircleXCenter = 2;
    int CircleYCenter = 2; 
    int CurXPos = xPos; //where the platform currently is in X
    int CurYPos = yPos; //where the platform currently is in Y
    int Rad = 1;
    
    
    
    
    for (int i = 0; i < 360; i++)
      {
    //it does this for each point of the circle, so you dont have to run them at the same time
       float 
       angle = i*2*3.14/360;
        xPos = CircleXCenter + (cos(angle) * Rad);
        yPos = CircleYCenter + (sin(angle) * Rad);
        if(CurXPos < xPos)
         {
           
               xAxis.step(xPos - CurXPos);
              //movexnow = Xpos - CurXPos;
          }
       else
       {
               xAxis.step(xPos - CurXPos); 
           //MoveXNow = CurXPos - Xpos; 
       }
       
        if(CurYPos < yPos)
        {
               yAxis.step(yPos - CurYPos); 
             //   MoveYNow = Ypos - CurYPos;
        }
       else
       {
               yAxis.step(yPos - CurYPos
               ); 
             //MoveYNow = CurYPos - Ypos; 
       }
    
      // step(xAxis);
       //step(yAxis);
      
                 //<100, so -1 
       if(i == (360-1)) //we are at end of for loop, save current position.
       {
           CurYPos = yPos;
           CurXPos = xPos ; 
       }
    
      }
      
}

maybe your switches are HIGH when open and LOW when closed(pressed)