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

Can you give any more detail about how your switches are wired up? Sometimes this problem can be caused if the switch doesn't have a pullup resistor (or pulldown resistor, depending on how it is wired). Do you have a circuit diagram / schematic?

No circuit diagram...

Hmm I haven't put in a resistor; is that my problem? I have these: http://www.electronicsurplus.com/Item/19781/MICRO%20SWITCH%20-%20Switch_%20micro_%20Contacts_%20SPDT_%20-%201052-7325/

with ground and NC (normally closed) wired. Input pin is directly into my arduino...

yeah, you need a resistor to keep the switch pulled down/up so that reading is stable: http://arduino.cc/it/Tutorial/Button

Oooh! Will try that!

A colleague of mine suggested for trying to do interpolation: catmull rom spline

Since I will have the motion all be relative, and the thing has to respond to OpenCV messages. What do you think? Am I going about this incorrectly so far?

Should I use a pull-down for a normally closed switch?

one side of the NC switch to GND the other side to the digital pin and a pullup to 5v(so that when the switch is pressed and becomes open, the pin is 5v(HIGH))

Hey, ok so I will be rewiring my switches tomorrow and will see how it all works out.

I was wondering if you guys could help me in advance with two things:

1- Using the code I have posted so far, where I pulse the stepper motors in order to make the head move in specific directions, how do I make sure that the code changes xPos and yPos only when the motors actually spin? Sometimes, I send a signal through the serial window in Arduino, and Arduino does the math of adding 200 to the xPos, but sometimes it seems that the motor skips signals: I have to hit 'E' and ENTER a few times before the thing moves. I am not sure if the Serial.read happens in cycles or with some kind of delay?

/* Stepper Motor Controller ;  language: Wiring/Arduino
 This program drives a unipolar or bipolar stepper motor.  by Tom Igoe 
 and the Spline library by Kerinin
 */

/* significant help from arduino forum superstars: sirbow2, stimmer
 */
#include <spline.h>
#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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}

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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  

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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}    

//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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  


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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  


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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);

}  


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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  

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 ; 
    }

  }

}
  1. I am thinking of using Spline's library to plot points for the program to follow and have the points sent to Arduino by Processing. Problem is, I looked at the Arduino example code, but really don't know how I am going to make it work. Any advice of how to approach this?

You guys rock so hard!
Thanks!

  1. i ve never really heard of splines library, i might look at it, though.

  2. getting rid of the

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

parts of your code and using interrupts instead. maybe making the switch case part of your code smaller would make it run faster. but serial data is stored in a hardware buffer until Serial.read is called, so it wouldnt matter...i think?

Thanks for the reply;

I increase the xpos and ypos when I step the motor; I guess there's no way for Arduino to know if it actually moved the motor successfully?

Yeah, the spline library looks cool, especially for my purposes, but I am a mega n00b and don't completely understand what's going on....

I guess there's no way for Arduino to know if it actually moved the motor successfully?

good question. id say no? you'd have to us another source of movement feedback, like an encoder, to check that type of stuff?

I guess I will have to be somewhat imprecise about that; for my purposes, that's okay.

Sometimes the motors can't turn the gears, while other times, they run smoothely. My instructor narrowed it down to probably an electrical problem. Today a separate person noticed I have two 6v motors requiring 0.8 Amps using one power source at 1 amp.
Could this be causing the problem?

depends. if you run both at 1/2 speed, that would draw .4 amp each and so only draw .8 total.

try this: run one at half speed and see if it can move its axis alone. then try the other axis at half speed. then try both at half speed. or maybe full speed too, instead of halfspeed.

Changing the speed did nothing :frowning:

BUT NOW I have a brand new problem that I dont know how to solve or how it happened.

I was using my motor with keyboard inputs.
I press W, the motors move in the direction theyre supposed to, same for N, W, and S.
These are the the directions that move straight lines.
However, if I give it "J" or "H" or any of the diagnoal keys two things happen

  1. Neither motor moves
  2. They key input stops responding.
    For example, if I hit "J", which should move in a diagonal direction, nothing happens. If I THEN hit W, the motors don't move; they stop responding altogether and will not move again until I restart either Processing (the keyboard input program) or Arduino's Serial output.

I looked at where those functions are or where they are called... and I have NO idea what happened! :frowning:

Any ideas?

/* Stepper Motor Controller ;  language: Wiring/Arduino
 This program drives a unipolar or bipolar stepper motor.  by Tom Igoe 
 and the Spline library by Kerinin
 */

/* significant help from arduino forum superstars: sirbow2, stimmer
 */
#include <spline.h>
#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 xStopMin = A0;
int xStopMax = A1;
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() {

  PMS:
  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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}

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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  

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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}    

//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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  


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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  


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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);

}  


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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}  

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 think its getting stuck in this line:
while(!digitalRead(xStopMax) && !digitalRead(yStopMin) && s<numSteps); until you press the stop button nothing will happen; it will loop on that line. "s<numSteps" will always be true since "int s=0;" right above it, unless numSteps would happen to be 0

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;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}

also, as far as i know that while syntax is incorrect for what you are trying to do and the for was wrong.

-the 's' int was declared separately for the for loop than the moveNE function/while loop
-the while line wouldnt work because: you had a ';' at the end so its kind of like a function and so it would only check once before the for loop(first thing i mentioned in this post).

look here:

void moveNE(int numSteps){    
  int s=0; 
  while(!digitalRead(xStopMax) && !digitalRead(yStopMin) && s<numSteps) //checks for stop switches and numStep count each step of steppers.
  { 
    yAxis.step(-1);
    xAxis.step(1);
    s++;
  }

  xPos += numSteps;
  yPos -= numSteps;

  //check where we are
  Serial.print("x position: ");
  Serial.println(xPos);
  Serial.print("y position: ");
  Serial.println(yPos);
}

sorry if those explanation are bad, its kinda hard to write out.

OOOOOOOOOOOOOOOOH!

That makes sense!
Also a very useful note about steps = 0 crashing arduino. This is going up in a show for two weeks and it is imperative that NOTHING crashes it :slight_smile:

Thanks so much for all the help so far, guys! I really owe a huge chunk of my master's thesis working (here's hoping it does!) to your volunteering help!

I have gotten the impression that my 6V 1amp radio shack power adapter isn't cutting the mustard.
The motors each (of which there are 2) require 6V and 0.8 amps.

If I use something like this: TigerDirect Sunset would 20 amps of power blow anything up?
Also, would I be able to make it work with a 12 v and a voltage regulator? Will I blow up my LD29 ICs?

I don't want to set the student gallery on fire >.>

blow anything up

lol, you dont understand current :stuck_out_tongue: the power supply COULD supply 20amps max, but the steppers only draw .8A each, so the PSU will give each stepper .8A(at 6v...if you go past recommended voltage, the current draw will increase)

yes it would work, but converting 12v to 6v could generate a lot of heat, maybe better to find a 6v "native" PSU? you could get a second adapter and wire them in parallel to get 6v 2A O.O :slight_smile: as a quick fix

Thanks Sirbow; it seems a lot of the PS go upwards of 10V :frowning:

I don't totally understand current, despite engineering classes as a teen, physics, and constant explanations as an adult. I think in the back of my mind, I keep hearing "IT'S GONNA BLOW! IT'S GONNA BLOW"

I will try to find a 6V more than 2 Amp PS

Sirbow and Stimmer (and other people that have helped)

You guys have helped me on this project SOOOOOOOOOOOOOOO much!

In the next two or three weeks, I hope to get things running, and will probably be back on this forum with new issues, BUT I wanted to make sure I can include you on my super duper long list of Thank You's for my MFA project. That said, if you're cool with that, PM me with the preferred way I should list you on the soon-to-appear thank you page on my thesis blog: http://breerubinmfadt.tumblr.com/
Otherwise, I'll probably just put your forum usernames on there.

Thanks again! ONWARDS AND UPWARDS!
---bree