rec/play 3 axis with accelstepper.h question

Robin2:
Using one button to cause different actions can get very confusing for the user - as well as for the code.

i miss understood, for me it's 1 action, recording a position. The count is only for more positions, and while you can't go back, and it doesn't matter if you press and record 1 position to much because it will be empty so it will skip it in the replay. It doesn't really matter if your forgot if you pressed 19 or 20 times. i'm not going to make a button for every position i want to record.

and about the sensor. If I make it this way, I need it to do this only in setup then? i can't run the arm with medium or high speed trough the sensor and always calibrating the position? or at least it's not a good idea? (like an encoder but only on one step)

Yes you can re-check your position every time the arm swings through that zero position. But it does not give you much useful information. There are only two possible outcomes:

  1. The sensed position matches the calculated position. Do nothing.

  2. The sensed position does not match the calculated position. Emergency stop.

HighSolutions:
i miss understood, for me it's 1 action, recording a position. The count is only for more positions, and while you can't go back, and it doesn't matter if you press and record 1 position to much because it will be empty so it will skip it in the replay. It doesn't really matter if your forgot if you pressed 19 or 20 times. i'm not going to make a button for every position i want to record.

I think you are completely missing the bigger picture.

This is the first time you have explained that you want to record another data point every time the button is pressed.

And why would a position be empty if you press the button an extra time?

Also, during playback there must be some pre-determined time interval between the movements for successive data points. A stepper motor cannot physically move instantaneously from one position to the next. Consequently an unwanted button press (data item) will show up as a pause.

IMHO either you have not told us everything or you need to do a major re-think.

...R

Robin2:
I think you are completely missing the bigger picture.

This is the first time you have explained that you want to record another data point every time the button is pressed.

And why would a position be empty if you press the button an extra time?

Also, during playback there must be some pre-determined time interval between the movements for successive data points. A stepper motor cannot physically move instantaneously from one position to the next. Consequently an unwanted button press (data item) will show up as a pause.

IMHO either you have not told us everything or you need to do a major re-think.

...R

I really don't get the issue? in post 12 you explain yourself exactly what i want, so i don't get how you don't know that i wan't to save multiple positions/xyz locations/data points or whatever you may call them... What would be the point of an stepper arm with only 1 position??? You even conclude that the recording is working as is..... what's the problem there?

And why it would be empty? why would it need to be empty? if you look at the code... you can see there is an array, PosSave1 till 3, for every stepper 1, with 5 places to store a value of steps, i placed numbers there already so i could try the replay function w/o the need of recording the positions every time i uploaded code or reset the arduino.
but if i want to store it just write's over the pre determined positions.

and no, i don't want a pre-determined time interval between the movements...... thats why i was trying to figure out the if statement : if (stepper1.isRunning() == false && stepper2.isRunning() == false && stepper3.isRunning() == false) // IF stepper is running: DO nothing
IF stepper is done running, then you must proceed to next saved position. what my main question was.....
so in this case it doesn't matter what the timing is, if stepper 1, does one step and the other do nothing, they can proceed to the next position as soon the 1 step in that steppers speed and acceleration is done.
but if they all three need to go 800.000 steps then they will do that, in there own speed and acceleration. and as soon as all 3 steppers hit their 800.000s step. the if statement will read a is.running equal false, so they can go on to the next thing in the if statement, let it be a next position or something completely different like turning on a coffee machine.

i will post my working code. I put 2 extra steppers in it, added extra arrays to keep te code a little shorter and to make it easier to change how many positions i can store, for now there are 20 positions possible and working, i think i can even store 50 but to be gentle on my arduino i ordered an sd shield to store data on in the future.

Read the code, i don't want to be mean but i really think you could have understood my questions if you've read the code and my questions.

MorganS:
Yes you can re-check your position every time the arm swings through that zero position. But it does not give you much useful information. There are only two possible outcomes:

  1. The sensed position matches the calculated position. Do nothing.

  2. The sensed position does not match the calculated position. Emergency stop.

my if statement works now so isn't it possible (if i find the right sensor/switch) to do something like:
if (stepper1.isRunning() == false && stepper2.isRunning() == false && stepper3.isRunning() == false){
check if it passed sensor, yes || no
no? proceed to next position
yes? how many x steps of was the stepper: add x steps to current position
set new 0 position minus/plus this position,
and go to next position.

i would need to make a piece of code recording the steppers step when passed the sensor with the .currentPosition() function.
But i don't know if you can set .setCurrentPosition() on another value except 0?

ps. if it's not possible to .setCurrentPosition() not on zero. it may be possible to add and extra value intercepting /adding extra steps like this:
int calibration = 0
int newval1 = 100
sensor makes calibration -12
newval1 = possave1 + calibration
stepper1.moveTo(newval1)

newval1 should be 88
but if you change to another position the calibration stays as long as you add it to every saved position right?

Sounds good but if you get a discrepancy, what do you do? The code has no way of knowing what caused it. If it did know then it could calculate for it.

If there is a discrepancy for an unknown reason then you have to stop. There is no point continuing once you know that you are lost.

do you have an example of when and how this discrepancy could happen where i can’t recover from?
the situation i have in mind where the correction could be nice if the whole base of the arm turns and a person(me for example) is blocking the turning and it misses a few steps, i think it would be nice that if it turned around and hit the sensor it wil correct it’s self assuming i have learned my mistake and moved away. (although i’m not sure it misses a step easily, also this more of a learning my self things then that i think it’s really necessary)

maybe i could add an extra sensor or switch to make the opportunity of calibrating bigger.

Here is the full code as is now btw:
oh and ps. i stepped up from an uno to a mega.

#include <AccelStepper.h>
#include <MultiStepper.h>
// EG X-Y-Z position arm driven by 3 steppers
// Alas its not possible to build an array of these with different pins for each :-(
AccelStepper stepper1(AccelStepper::DRIVER, 22, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 24, 25);
AccelStepper stepper3(AccelStepper::DRIVER, 26, 27);
AccelStepper stepper4(AccelStepper::DRIVER, 28, 29);
AccelStepper stepper5(AccelStepper::DRIVER, 30, 31);

//define the buttons
const int button1 = 2; //reccord button
const int button2 = 3; //replay button

//define variable for values of the button
int button1Count = 0;   //for switch case recording
bool button1Pressed = false;
bool button2Pressed = false;

//timing
unsigned long milli;
unsigned long milliOld;
const long interval = 2000;

//define potentiometers
const int pot1 = A0;
const int pot2 = A1;
const int pot3 = A2;
const int pot4 = A3;
const int pot5 = A4;

// stepper positions setup
int rotation1;
int val1 = 0;
int previous1 = 0;
int long newval1 = 0; 

int rotation2;
int val2 = 0;
int previous2 = 0;
int long newval2 = 0; 

int rotation3;
int val3 = 0;
int previous3 = 0;
int long newval3 = 0; 

int rotation4;
int val4 = 0;
int previous4 = 0;
int long newval4 = 0; 

int rotation5;
int val5 = 0;
int previous5 = 0;
int long newval5 = 0; 

//define variable for saved position 
int PosSave1[21]={1023,0,512,1023,350,1023,0,512,1023,350};
int PosSave2[21]={1023,0,1023,0,1023,1023,0,512,1023,350};
int PosSave3[21]={1023,0,512,1023,350,1023,0,512,1023,350};
int PosSave4[21]={1023,0,1023,0,1023,1023,0,512,1023,350};
int PosSave5[21]={1023,0,512,1023,350,1023,0,512,1023,350};
int playback = 1; // for switch case replay
int i = 0;
int max = 20;  //max is maximum count of PosSave's 

void setup() {
   // Configure each stepper
  stepper1.setMaxSpeed(600);
  stepper1.setAcceleration(600);
  rotation1 = 100;                         //stepper shaft rotation (200 = 1 full rotation)
  stepper2.setMaxSpeed(600);
  stepper2.setAcceleration(600);
  rotation2 = 200;                         //stepper shaft rotation (200 = 1 full rotation)
  stepper3.setMaxSpeed(600);
  stepper3.setAcceleration(600);
  rotation3 = 400;                         //stepper shaft rotation (200 = 1 full rotation)
  stepper4.setMaxSpeed(600);
  stepper4.setAcceleration(600);
  rotation4 = 600;                         //stepper shaft rotation (200 = 1 full rotation)
  stepper5.setMaxSpeed(600);
  stepper5.setAcceleration(600);
  rotation5 = 800;                         //stepper shaft rotation (200 = 1 full rotation)

  //define buttons as input units
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);

  //initialize serial communication for saved position
  Serial.begin(9600);
}
void loop() {
// This part is for manual moving the steppers:
  
        //read the potentiometer values and define the potentiometer value with the map function
  if(button2Pressed == false){   // made this so if button 2 is pressed for replay the potmeters won't interfere
  val1 = analogRead(A0);
  val2 = analogRead(A1);
  val3 = analogRead(A2);
  val4 = analogRead(A3);
  val5 = analogRead(A4);
 
//  {if ((val1 > previous1+2) || (val1 < previous1-2)) // Check that a move of the pot is at least > or < than 6 in case of jitter
    { 
    newval1 = map(val1, 0, 1023, -rotation1, rotation1);  // Map value (rotation[] = stepper shaft rotation)
    stepper1.moveTo(newval1);   // Move stepper to new position
    stepper1.run();
    previous1 = val1;  // save current value into variable previous
    } 
//  }
//  {if ((val2 > previous2+2) || (val2 < previous2-2))  // Check that a move of the pot is at least > or < than 6 in case of jitter
    {
    newval2 = map(val2, 0, 1023, -rotation2, rotation2);   // Map value (rotation[] = stepper shaft rotation)
    stepper2.moveTo(newval2);
    stepper2.run();  // Move stepper to new position
    previous2 = val2;  // save current value into variable previous
    }  
//    }
//    {if ((val3 > previous3+6) || (val3 < previous3-6))  // Check that a move of the pot is at least > or < than 6 in case of jitter
    {
    newval3 = map(val3, 0, 1023, -rotation3, rotation3);   // Map value (rotation[] = stepper shaft rotation)
    stepper3.moveTo(newval3);
    stepper3.run();  // Move stepper to new position
    previous3 = val3;  // save current value into variable previous
    }
//    }
//  {if ((val4 > previous4+6) || (val4 < previous4-6))  // Check that a move of the pot is at least > or < than 6 in case of jitter
    {
    newval4 = map(val4, 0, 1023, -rotation4, rotation4);   // Map value (rotation[] = stepper shaft rotation)
    stepper4.moveTo(newval4);
    stepper4.run();  // Move stepper to new position
    previous4 = val4;  // save current value into variable previous
    }
//  }
//  {if ((val5 > previous5+6) || (val5 < previous5-6))  // Check that a move of the pot is at least > or < than 6 in case of jitter
    {
    newval5 = map(val5, 0, 1023, -rotation5, rotation5);   // Map value (rotation[] = stepper shaft rotation)
    stepper5.moveTo(newval5);
    stepper5.run();  // Move stepper to new position
    previous5 = val5;  // save current value into variable previous
    }
//  }
  }
  
//This part is for recording the positions:

  //if button1 is pressed (HIGH), save the potentiometers position  
  if(digitalRead(button1) == HIGH)
  { button1Pressed = true;}
  else { button1Pressed = false; }
  
  if(button1Pressed)
  {
    milli = millis();
    
    if(milli - milliOld >= interval)     //the millis-delay makes sure you don't write 20 positions in 1 button push
    {
      i++;
      milliOld = milli;
      
      PosSave1[i] = newval1;
      PosSave2[i] = newval2;
      PosSave3[i] = newval3;
      PosSave4[i] = newval4;
      PosSave5[i] = newval5;
      Serial.println("Position");
      Serial.println(i);
      Serial.println("Saved");
      Serial.println(PosSave1[i]);
      Serial.println(PosSave2[i]);
      Serial.println(PosSave3[i]);
      Serial.println(PosSave4[i]);
      Serial.println(PosSave5[i]);
    }
  }

    if(i > max || i < 0)              //resets the count to re-record positions if needed
    {
      i = 0;
    }
  
//This part is for replaying said recorded positions:

  //if button2 pressed (HIGH), the steppers (should) move to saved position
  if(digitalRead(button2) == HIGH){
    Serial.println("Button2 Go");
    delay(2000);
    button2Pressed = true;
  }
  
  if(button2Pressed)
  {
    newval1 = PosSave1[i] ;
    stepper1.moveTo(newval1); 
    newval2 = PosSave2[i] ;
    stepper2.moveTo(newval2);
    newval3 = PosSave3[i] ;
    stepper3.moveTo(newval3);
    newval4 = PosSave4[i] ;
    stepper4.moveTo(newval4);
    newval5 = PosSave5[i] ;
    stepper5.moveTo(newval5);
    
    stepper1.run();  // Move stepper to new position
    stepper2.run();  
    stepper3.run();  
    stepper4.run();  
    stepper5.run();  
    
  if (stepper1.isRunning() == false && stepper2.isRunning() == false && stepper3.isRunning() == false && stepper4.isRunning() == false && stepper5.isRunning() == false)
    {
      Serial.println("Position");
      Serial.println(i);
      Serial.println("Finished");
      i++; 
    }
    
    if (i > max)
    { 
      i = 0;
      button2Pressed = false;
    }
  }  
}

In that example, you could have lost 2 complete turns while blocked. It can't count how many were lost. So it is still lost.

Turn the problem around. You expect to see the sensor any time the arm is between counts 5 and 50. (Spinning slow, you expect exactly 0 to 58 maybe.) If your calculated position is in that range and the sensor is not active, Emergency stop.

HighSolutions:
I really don't get the issue? in post 12 you explain yourself exactly what i want, so i don't get how you don't know that i wan't to save multiple positions/xyz locations/data points or whatever you may call them..

If you re-read Reply #12 you will see that I never mentioned multiple positions. The problem is that you are applying your wider knowledge to my words and assuming that is what I meant. And all along that is why I have been struggling with this Thread.

And why it would be empty?

I have no idea. It was you that mentioned "empty" in Reply #20

And, to be constructive it would certainly be possible to make a motor start on the next move once the present move is finished. Just check for when distanceToGo() gets to zero.

Do you want to wait until all the motors have finished a move before any of them starts on the next move?

...R