Stepper bouncing with variable amplitude

Hi, I am happily moving a stepper from two end points (moveTo). I would like those end point values to change at every cycle (cycle= 1 back and forth movement) as per a discrete value, for example 10 steps.

So, first move back and forth 500 steps, then back and forth 490 steps, then 480 … until 0 and from there, move up with increments of 10 until the 500 and back to 0 and so on …

Sorry if this is too basic but I cannot figure out how to.

Thanks for the suggestions.

#include <AccelStepper.h>

void setup()
{ 

stepper.setMaxSpeed(100);
stepper.setAcceleration(20);
stepper.moveTo(500);
}

void loop()
{
// If at the end of travel go to the other end
if (stepper.distanceToGo() == 0)
stepper.moveTo(-stepper.currentPosition());

stepper.run();
}

Instead of getting the motor to move to currentPosition() get it to move to the position you want it to go to

stepper.moveTo(-stepper.currentPosition());

...R

Thanks Robin2. Finally I managed to have a code that seems to be working OK. Lots of reading and understanding was necessary (and much more is needed …).

Next step is to adapt the code for non blocking calls since I need to have 2 other steppers moving at constant speed. I am afraid the WHILE is not ok and I have to change the logic to IF … to be continued.

Suggestions are welcome.

Here the code:

#include <AccelStepper.h>

AccelStepper M1(1, 2, 3);

int MinWidth = 100;
int Increment = 50;
int MaxWidth = 500;

void setup() {
  
   M1.setMaxSpeed(1000);
   M1.setAcceleration(500);
   M1.setCurrentPosition(0);
            }
            
void loop()
   {
  
     M1.setCurrentPosition(0);
    
     while (M1.currentPosition() != (-MaxWidth))
             {       
        
             M1.moveTo(MinWidth);
             M1.runToPosition();
              
             M1.moveTo(-M1.currentPosition());
             M1.runToPosition();
          
             MinWidth=MinWidth+Increment; 
             }
            
             MinWidth = 100;
              
     while (M1.currentPosition() != (MinWidth))
             {       
             M1.moveTo(-M1.currentPosition() - Increment);
             M1.runToPosition();

             M1.moveTo(-M1.currentPosition());
             M1.runToPosition();
             }
    }

VictorElectro:
I have to change the logic to IF ... to be continued.

Let's see that version and your description of what happens when you try it.

Note that runToPosition() is a blocking function so that will probably have to go also, to be replaced with run() or runSpeed()

...R

I have been trying to solve this with the IF and non blocking calls but I am not there …
As a summary, here what I am trying to achieve:

  • Move Stepper 1 (M1) to the MinWidth+Offset position
  • Move it back to the MinWidth position
  • Increment the Offset value by the Offset
  • Do the above oscillation until the MaxWidth position is reached
  • Then do the reverse (decreasing phase) which is exactly:
  • Move to the MaxWidth-Offset position
  • Go back to the MaxWidth position
  • Do this oscillations until the MinWidth position is reached
  • And do this forever …

Stepper2 and 3 (M2 & M3)

  • Move at constant speed as defined by the setSpeed().

In my sketch all seems to be fine until M1 reached the first MinWidth+Offset value. Then the second IF toggle the bool PosSwing and enter the third IF. There … well just moves back and Forth from 100 to 99 …
Finally I disabled the Offset increment because the way it is now, will invalidate all the IF’s and M1 will simply keep on moving.

My head is spinning… , suggestion are welcome. Thanks.

#include <AccelStepper.h>
AccelStepper M1(1, 2, 3); // pin 2 = step, pin 3 = direction
AccelStepper M2(1, 4, 5); // pin 4 = step, pin 5 = direction
AccelStepper M3(1, 6, 7); // pin 6 = step, pin 7 = direction

int MinWidth = 0;
int MaxWidth = 1000;
int Offset = 100;    
bool Increasing = true;
bool PosSwing = true;

void setup() {
    Serial.begin(38400);
    
    M1.setMaxSpeed(1000);
    M2.setMaxSpeed(1000);
    M3.setMaxSpeed(1000);
    
    M1.setCurrentPosition(0);    
    M2.setCurrentPosition(0);
    M3.setCurrentPosition(0);

    M1.setSpeed(200);
    M2.setSpeed(200);
    M3.setSpeed(20);  

    M1.setAcceleration(100);
    M2.setAcceleration(0);
    M3.setAcceleration(0);
             }            
void loop() {

  // To add later for the deceasing phase ?
      //if (M1.currentPosition() >= (MaxWidth)){
      //Increasing = ! Increasing

      // the positive swing up to the current destination
      if (PosSwing == true && M1.currentPosition() < (MinWidth+Offset)){
          Serial.println("in the first IF");
          M1.moveTo(MinWidth+Offset);
          M1.runSpeedToPosition();  
          M2.runSpeed();
          M3.runSpeed();
      }
        // revert the PosSwing value for the negative swing
        if (M1.currentPosition() == (MinWidth+Offset)){
          Serial.println("In the second IF");
          Serial.println(PosSwing);
          PosSwing = !PosSwing;
          Serial.println(PosSwing);
        }
      // the negative swing to the minwidth destination
      if (PosSwing == false && M1.currentPosition() >= (MinWidth+Offset)){
          Serial.println("In the third IF");
          M1.moveTo(MinWidth);
          M1.runSpeedToPosition();  
          M2.runSpeed();
          M3.runSpeed();
        }
        Serial.print ("M1 Current Position is ");
        Serial.println (M1.currentPosition()); 
        //Serial.print ("M2 Current Position is ");
        //Serial.println (M2.currentPosition());
        //Serial.print ("M3 Current Position is ");
        //Serial.println (M3.currentPosition()); 
        Serial.print ("The Offset value is ");
        Serial.println (Offset); 

        // Increase the Offset of its value
        //Offset = Offset+Offset;
   }

When you try to put all the code into loop() it makes it very hard to see the different parts and their interactions.

If you want two motors always to run at a constant speed then their code should just be at the bottom of loop() out of the way of code for the other motor. And if you want all the motors to move at the same time you can’t use runSpeedToPosition() - so make all the motors move at the end of loop(). Something like

void loop() {

   // other code

   M1.runSpeed();
   M2.runSpeed();
   M3.runSpeed();
}

Then there needs to be code to decide what the oscillating motor should do - by changing the destination of the motor. That code can be in a function on its own. Something like

void updateMotor1() {
   if (M1.distanceToGo == 0) {
      if (motorPos <= 0) { // stepper has reached the return position
          if (motorPos >= maxPos or motorPos <= minPos) {
             offset = -offset;
          }
          motorPos += offset;
          M1.moveTo(motorPos);
       }
       else {
         motorPos = -motorPos;
         M1.moveTo(motorPos);
       }
    }
}

and put a call to that function in loop() like this

void loop() {

  updateMotor1();

  M1.runSpeed();
  M2.runSpeed();
  M3.runSpeed();
}

NOTE - I have neither compiled nor tested the above

…R

Thanks Robin2, much appreciated. Let me understand and digest all that info.

I need to re-read you excellent post at Planning and Implementing an Arduino Program - Programming Questions - Arduino Forum

As per the stepper commands, I thought that only the .runToPosition() and .runToNewPosition were blocking, not the .runSpeedToPosition().

I will then use the .run() when implementing acceleration and .runSpeed() for constant speed.

VictorElectro:
As per the stepper commands, I thought that only the .runToPosition() and .runToNewPosition were blocking, not the .runSpeedToPosition().

Check the documentation for the library. I have been wrong before.

...R