Stepper

Hello

I have a few states where things happen in a sequence. The states work fine, but the problem I have is that the stepper will not run for 400 steps.

The sequence is:

hold before shot
SHOT FIRED
hold after shot
STEPPER SHOULD RUN
Is interval: 6000
hold before shot
SHOT FIRED
hold after shot
STEPPER SHOULD RUN
Is interval: 6000
etc

I thought I did it correct to have the stepper run for 400 steps when it hits that part, but I'm wrong. I hear the stepper step 1 step, once every second (total duration of hold time is 6 seconds, so it steps 6 steps).

I need the stepper to run for 400 steps when it hits that, regardless of hold time or interval.

What am I doing wrong?

Oh, this is part of a much larger sketch but the problem area is: 'case S_MOVE: // MOVE THE STEPPE n STEPS at n SPEED'

the code:

#include <AccelStepper.h>

long PreviousDelayMillis = 0;

int currentType = 0;
int value = 0;
int numIncr = 0;
int Min = 0;
int Max = 0;


int LinEndleft = 0;  // ENDSTOP LEFT  ---> use as:   if (LinEndleft == HIGH) { blaaah }
int LinEndRight = 0; // ENDSTOP RIGHT

int Confirm = 0; // confirm of init gezet is
int InitMode = 0; // zijn we in initmodes? Zo ja welke dan?
int InitStatus = 0; // init gedaan na opstarten? 0=nee

const int Step1End = 0;                                   // eindpunt is 0, stepper telt af!
long Step1Start = 2666;                              // startpunt is de waarde uit INIT
const int Step2End = 0;                                   // eindpunt is 0, stepper telt af!
long Step2Start = 666;                              // startpunt is de waarde uit INIT
const int Step2Max = 360;                                 // mximaal aantal graden rotatie
int Srev = 200;                                     // number of steps per rev
char Fm = 2;                                        // MicroStepping Factor
char Pitch = 2;                                     // pitch in mm
int Nt = 20;                                        // Number of teeth
float Pstep = (Srev * Fm) / (Pitch * Nt);           // aantal steps per mm
float Pdist = 1 / Pstep;                            // aantal mm per steps

int TimeBetwenShots = 10; // USER INPUT tussen 4 - 1000 secondes between each shot
int TrackLength = 10000; //stappen kan ook maar lengte is nu length of track in mm
int RunTime = 800; //1 hour to complete a 1000mm track komt van userinput vlaues [1] in seconden
int HoldTime = 4; //total holding time /s

float NumShots = RunTime / TimeBetwenShots; // total time devided by # shots
float MMBetweenShots = TrackLength / NumShots; // tracklength devided by shots
int Speed = 500; // StepperSpeed = 400 steps p seconde
AccelStepper stepper1(1, 5, 4);                   // stepper 1 pin setup 14 step - 15 dir

void setup() {
  Serial.begin(9600);

}

void loop() {
  ShootIt();
}







unsigned long previousMillis = 0; // store last time
const long interval = (TimeBetwenShots - HoldTime) * 1000; // seconds to ms minus de holdtijd
const long intervalNorm = TimeBetwenShots * 1000; // seconds to ms for shots fired in NORM

unsigned long previousHold = 0; // store last time a hold ws done

unsigned long previousRelease = 0; // store last time a hold ws done
const long ReleaseTime = 3000; // the holdtime before and after the shot, has to be subtracted from the TimeBetwenShots lateron!


//States
const int S_HOLD = 0;
const int S_SHOOT = 1;
const int S_RELEASE = 2;
const int S_MOVE = 3;

int StepperHasRun = 0;
int ShotCounterStatus = 0;



void ShootIt() {
  static int state = S_HOLD ;
  switch (state)
  {
    case S_HOLD:    // hold the camera steady BEFORE taking a shot for n seconds
      if (previousHold == 0) {
        previousHold = millis();
      }
      if (millis() - previousHold >= (HoldTime * 1000) / 2)
      {
        Serial.println(F("hold before shot"));
        previousHold = 0;
        state = S_SHOOT;
      }
      break;


    case S_SHOOT:
      // fire the remote focus and shutter on PIN 11 + 12
      shoot();
      state = S_RELEASE;
      break;

    case S_RELEASE: // hold the camera steady BEFORE taking a shot for 2 seconds
      if (previousRelease == 0) {
        previousRelease = millis();
      }
      if (millis() - previousRelease >= (HoldTime * 1000) / 2)
      {
        Serial.println(F("hold after shot"));
        previousRelease = 0;
        state = S_MOVE;
      }
      break;

    // ## PROBLEM AREA #############################################
    case S_MOVE: // MOVE THE STEPPE n STEPS at n SPEED

      stepper1.setSpeed(800);
      stepper1.moveTo(400);
      if (StepperHasRun == 0 && stepper1.distanceToGo() != 0) // StepperHasRun is 0
      {
        stepper1.run();
        //    Serial.print(stepper1.distanceToGo());
      }



      if (previousMillis == 0) {
        previousMillis = millis();
      }
      if (millis() - previousMillis >= interval)
      {

        Serial.print(F("Is interval: ")); Serial.println(interval);
        previousMillis = 0;
        state = S_HOLD;
        StepperHasRun = 0;
      }
      break;



  } // end switch

} // end ShootIt()



void shoot()
{
  digitalWrite(11, HIGH); // focus up
  digitalWrite(12, HIGH); // shutter up
  digitalWrite(12, LOW); // shutter down
  digitalWrite(11, LOW); // focus diwn
  Serial.println(F("SHOT FIRED"));
  ShotCounterStatus = ShotCounterStatus + 1;
}

I suspect you are not using stepper1.run(); properly. It really should be called from loop() and loop() should repeat hundreds or thousands of times per second. stepper.run() just moves the motor 1 step if it is time for the next move. Otherwise it does nothing.

The alternative is to use the blocking call stepper.runToPosition().

Study the Accelstepper documentation.

...R

Thanks again Robin

I did try that but the stepper still runs for 6 seconds, regardless of the # of steps I enter.

Calling it from loop() breaks the states; the motor keeps running. I also tried runToPosition but the same 6 seconds apply there, motor keeps running until the next state starts.

I've tried numerous options but if it's really not possible to do it like I thought it would work than I have to figure something out, again.

Thanks!

I could not find a way to get it to run within the states and without using the loop90. Loop() made the moto run continuously, regardless of the state it was in, so that didn't really help.

I did mention before that within the state, the motor would run for the duration of the state. So I recalculated the number of steps per ms, regarding speed etc, and used that as the duration of the state.
The remaining intervaltime is now a delay minus the stepper runtime.

All in all the timing is the same...

In other words, the motor is now running based on time and not based on steps. Hope this works out but I can't find a solution to get it running in any other way.

If anyone knows how to get it running in any other way within the state I would be very grateful!

snewpers:
Thanks again Robin

I did try that but the stepper still runs for 6 seconds, regardless of the # of steps I enter.

Calling it from loop() breaks the states; the motor keeps running. I also tried runToPosition but the same 6 seconds apply there, motor keeps running until the next state starts.

I've tried numerous options but if it's really not possible to do it like I thought it would work than I have to figure something out, again.

It is certainly possible to get the functionality you want.

If calling from loop() breaks states then the state "system" is wrong. Maybe have a look at Planning and Implementing a Program

When you try something different you need to post the updated code.

...R

Thanks Robin

This whole project has been one of revisions and reading more and more examples and texts and to be honest, reading more somehow made it more confusing... I still have a lot learn.

The new code that does work (but not as I wanted it to) is :

#include <AccelStepper.h>

long PreviousDelayMillis = 0;

int currentType = 0;
int value = 0;
int numIncr = 0;
int Min = 0;
int Max = 0;


int LinEndleft = 0;  // ENDSTOP LEFT  ---> use as:   if (LinEndleft == HIGH) { blaaah }
int LinEndRight = 0; // ENDSTOP RIGHT

int Confirm = 0; // confirm of init gezet is
int InitMode = 0; // zijn we in initmodes? Zo ja welke dan?
int InitStatus = 0; // init gedaan na opstarten? 0=nee

const int Step1End = 0;                                   // eindpunt is 0, stepper telt af!
long Step1Start = 5000;                              // startpunt is de waarde uit INIT
const int Step2End = 0;                                   // eindpunt is 0, stepper telt af!
long Step2Start = 666;                              // startpunt is de waarde uit INIT
const int Step2Max = 360;                                 // mximaal aantal graden rotatie

int Srev = 200;                                     // number of steps per rev
char Fm = 1;                                        // MicroStepping Factor
char Pitch = 2;                                     // pitch in mm
int Nt = 20;                                        // Number of teeth
float Pstep = (Srev * Fm) / (Pitch * Nt);           // aantal steps per mm
float Pdist = 1 / Pstep;                            // aantal mm per steps

int TimeBetwenShots = 5; // USER INPUT tussen 4 - 1000 secondes between each shot
int RunTime = 1800; //1 hour to complete a 1000mm track komt van userinput vlaues [1] in seconden
int HoldTime = 1; //total holding time /s

float NumShots = RunTime / TimeBetwenShots; // total time devided by # shots
int Speed = 500; // StepperSpeed = 400 steps p seconde

float stepper1Run = (Step1Start / NumShots * 1000) / Speed;


AccelStepper stepper1(1, 5, 4);                   // stepper 1 pin setup 14 step - 15 dir

void setup() {
  Serial.begin(9600);

}

void loop() {
  ShootIt();
}







unsigned long previousMillis = 0; // store last time
unsigned long previousHold = 0; // store last time a hold ws done
unsigned long previousRelease = 0; // store last time a hold ws done
const long interval = (TimeBetwenShots * 1000) - (2 * HoldTime * 1000); //new interval - holdtime


//States
const int S_HOLD = 0;
const int S_SHOOT = 1;
const int S_RELEASE = 2;
const int S_MOVE = 3;

int ShotCounterStatus = 0;



void ShootIt() {
  static int state = S_HOLD ;
  switch (state)
  {
    case S_HOLD:    // hold the camera steady BEFORE taking a shot for n seconds

      if (previousHold == 0) {
        previousHold = millis();
      }
      if (millis() - previousHold >= (TimeBetwenShots * 500) )
      {
        Serial.println(F("hold before shot"));
        Serial.println(Pstep);
        Serial.println(interval);
        previousHold = 0;
        state = S_SHOOT;
      }
      break;


    case S_SHOOT:
      shoot();
      state = S_RELEASE;
      break;

    case S_RELEASE: // hold the camera steady BEFORE taking a shot for 2 seconds
      if (previousRelease == 0) {
        previousRelease = millis();
      }
      if (millis() - previousRelease >= (TimeBetwenShots * 500) - stepper1Run)
      {
        Serial.println(F("hold after shot"));
        previousRelease = 0;
        state = S_MOVE;
      }
      break;




    case S_MOVE: // MOVE THE STEPPE n MS at n SPEED
      if (previousMillis == 0) {
        previousMillis = millis();
      }
      if (millis() - previousMillis >= stepper1Run) //stepper1Run is calculated time in ms
      {

        Serial.print(F("Is interval: ")); Serial.println(stepper1Run);

        previousMillis = 0;
        state = S_HOLD;

      }

      stepper1.setMaxSpeed(Speed);
      stepper1.setSpeed(Speed);
      stepper1.moveTo(2);
      stepper1.runSpeed();

      break;



  } // end switch

} // end ShootIt()



void shoot()
{
  digitalWrite(11, HIGH); // focus up
  digitalWrite(12, HIGH); // shutter up
  digitalWrite(12, LOW); // shutter down
  digitalWrite(11, LOW); // focus diwn
  Serial.println(F("SHOT FIRED"));
  ShotCounterStatus = ShotCounterStatus + 1;
}

I've modified the holding time before and after the shot and the actual stepper time is now calculated bases on distance vs speed vs # of shots. The # steps between te shots I converted into ms so the 'move' state now has the duration of #steps/ms. A bit of an odd way but the values I see in the serial monitor and by timing them manually with a stopwatch seem to work fine.

This line, and other like it almost certainly does not do what you expect

const long interval = (TimeBetwenShots * 1000) - (2 * HoldTime * 1000); //new interval - holdtime

Your variables TimeBetweenShots and HoldTime are defined as INTs and will almost certainly overflow with those multiplications.

I suggest you define them as unsigned long to give yourself lots of room for large numbers.

Also I much prefer to do that sort of calculation in pieces because then I can check the intermediate values with Serial.print() statements.

This comment

case S_RELEASE: // hold the camera steady BEFORE taking a shot for 2 seconds

does not make any sense when the state S_RELEASE is set AFTER the shot is taken.

Why is stepper1Run in this line?

if (millis() - previousRelease >= (TimeBetwenShots * 500) - stepper1Run)

What is stepper1Run?
Has it got the correct value?

In your S_MOVE section I suspect you are getting time and steps mixed up. You can check using distanceToGo() whether the stepper has reached its destination. I don't see the need for timing. Alternatively use runSpeedToPosition() - also without any timing.

...R

Thanks again Robin

I have changed the const long into unsigned long but the results are the same.

The comment is indeed incorrect, was a leftover from a copy/paste, sorry.

'Stepper1Run' holds the time that the motor should run at the set speed. It's value is a calculation of total track length, interval between shots and total running time. The value represents milliseconds, so when the state is 'move' it will run for 'Stepper1Run' time.

The interval is split in two, 50% of the interval before the shot, 50% after the shot. I subtracted the ms for the motor so in total the interval stays the same and not interval+ms from motor.

I've used runSpeedToPosition too, but it only works once, and if the state repeats it only moves one step. More functions of accelstepper did that: run fine the first time and then only 1 step for each following state cycle, or run for the total time of that state, which is half the interval time...

Really odd, I though this part would be a breeze compared to the menu and other code :slight_smile:

Thanks!

OK, fixed it... kinda.

The reason it would only run once is because it was at the target position after one state has passed.
Resetting is with 'stepper1.setCurrentPosition(0);' prior to the 'move' state does the trick. Only problem is that 'stepper1.runSpeedToPosition();' blocks everything else and does not support acceleration.

I'll find a solution for that to, but for now it's OK.

The modified code is:

#include <AccelStepper.h>

long PreviousDelayMillis = 0;

int currentType = 0;
int value = 0;
int numIncr = 0;
int Min = 0;
int Max = 0;


int LinEndleft = 0;  // ENDSTOP LEFT  ---> use as:   if (LinEndleft == HIGH) { blaaah }
int LinEndRight = 0; // ENDSTOP RIGHT

int Confirm = 0; // confirm of init gezet is
int InitMode = 0; // zijn we in initmodes? Zo ja welke dan?
int InitStatus = 0; // init gedaan na opstarten? 0=nee

const int Step1End = 0;                                   // eindpunt is 0, stepper telt af!
long Step1Start = 20000;                              // startpunt is de waarde uit INIT
const int Step2End = 0;                                   // eindpunt is 0, stepper telt af!
long Step2Start = 666;                              // startpunt is de waarde uit INIT
const int Step2Max = 360;                                 // mximaal aantal graden rotatie
int Srev = 200;                                     // number of steps per rev
char Fm = 1;                                        // MicroStepping Factor
char Pitch = 2;                                     // pitch in mm
int Nt = 20;                                        // Number of teeth
float Pstep = (Srev * Fm) / (Pitch * Nt);           // aantal steps per mm
float Pdist = 1 / Pstep;                            // aantal mm per steps

unsigned long TimeBetwenShots = 40; // USER INPUT tussen 4 - 1000 secondes between each shot
int TrackLength = 10000; //stappen kan ook maar lengte is nu length of track in mm
int RunTime = 1800; //1 hour to complete a 1000mm track komt van userinput vlaues [1] in seconden
int HoldTime = 2; //total holding time /s
unsigned long interval = (TimeBetwenShots - HoldTime) * 1000; // seconds to ms minus de holdtijd


long motor1Run = round(Step1Start / (RunTime / TimeBetwenShots));

float NumShots = RunTime / TimeBetwenShots; // total time devided by # shots
float MMBetweenShots = TrackLength / NumShots; // tracklength devided by shots
int Speed = 500; // StepperSpeed = 400 steps p seconde
AccelStepper stepper1(1, 5, 4);                   // stepper 1 pin setup 14 step - 15 dir

void setup() {
  Serial.begin(9600);

}

void loop() {
  ShootIt();
}


unsigned long previousMillis = 0; // store last time
//const long intervalNorm = TimeBetwenShots * 1000; // seconds to ms for shots fired in NORM

unsigned long previousHold = 0; // store last time a hold ws done

unsigned long previousRelease = 0; // store last time a hold ws done
//const long ReleaseTime = 3000; // the holdtime before and after the shot, has to be subtracted from the TimeBetwenShots lateron!


//States
const int S_HOLD = 0;
const int S_SHOOT = 1;
const int S_RELEASE = 2;
const int S_MOVE = 3;

int StepperHasRun = 0;
int ShotCounterStatus = 0;



void ShootIt() {
  static int state = S_HOLD ;
  switch (state)
  {
    case S_HOLD:    // hold the camera steady BEFORE taking a shot for n seconds
      if (previousHold == 0) {
        previousHold = millis();
      }
      if (millis() - previousHold >= (HoldTime * 500) )
      {
        Serial.println(F("hold before shot"));
        previousHold = 0;
        state = S_SHOOT;
        stepper1.setCurrentPosition(0);
      }
      break;


    case S_SHOOT:
      // fire the remote focus and shutter on PIN 11 + 12
      shoot();
      state = S_RELEASE;
      break;

    case S_RELEASE: // hold the camera steady BEFORE taking a shot for 2 seconds

      if (previousRelease == 0) {
        previousRelease = millis();
      }
      if (millis() - previousRelease >= (HoldTime * 500) )
      {
        Serial.println(F("hold after shot"));
        previousRelease = 0;
        state = S_MOVE;
      }
      break;

    // ## PROBLEM AREA #############################################
    case S_MOVE: // MOVE THE STEPPE n STEPS at n SPEED



      if (previousMillis == 0) {
        previousMillis = millis();
      }
      if (millis() - previousMillis >= interval)
      {

        Serial.print(F("Is interval: ")); Serial.println(interval);
        Serial.println(round(Step1Start / NumShots));
        Serial.println(stepper1.currentPosition());
        previousMillis = 0;
        state = S_HOLD;

      }



      stepper1.setMaxSpeed(Speed);
      stepper1.setSpeed(Speed);
      stepper1.moveTo(motor1Run);
      // stepper1.runSpeed();

      stepper1.runSpeedToPosition();





      break;



  } // end switch

} // end ShootIt()



void shoot()
{
  digitalWrite(11, HIGH); // focus up
  digitalWrite(12, HIGH); // shutter up
  digitalWrite(12, LOW); // shutter down
  digitalWrite(11, LOW); // focus diwn
  Serial.println(F("SHOT FIRED"));
  ShotCounterStatus = ShotCounterStatus + 1;
}

snewpers:
Only problem is that 'stepper1.runSpeedToPosition();' blocks everything else and does not support acceleration.

I believe runToPosition() blocks but uses acceleration.

And stepper.run() is the standard function for acceleration without blocking.

...R

I believe runToPosition() blocks but uses acceleration.

That's indeed correct but I still somehow I cannot get the stepper to run n steps. When I use runtoposition(), move(), moveTo() and about every other function, it'll run for the amount I have the mills set (the interval in my sketch). So if the interval is 6 seconds, it'll run for 6 seconds, regardless of # of steps I set.

And stepper.run() is the standard function for acceleration without blocking.

Also correct but the problem is the same.And if I put the 'stepper1.setCurrentPosition(0);' inside the state it obviously only runs for 1 step, resets, runs 1 step etc until the interval has passed.

I have tried a lot of options to get it running like I would like it to run, but it's either running for 'interval' time, only 1 step or only one (correct) cycle before it does nothing anymore. The Serial monitor indicates that the sketch is still running and intervals are correct but the motor is not moving anymore...

I'm a bit lost here :slight_smile:

      if (millis() - previousHold >= (HoldTime * 500) )
      {
        Serial.println(F("hold before shot"));
        previousHold = 0;
        state = S_SHOOT;
        stepper1.setCurrentPosition(0);
      }

It seems to me that if now minus previousHold(Start) is greater than HoldTime (times some scale factor who's meaning is not at all obvious), then the hold is over. The action, then, is correct, but the serial output is misleading.

Shouldn't you make sure that the stepper has completed any movement before you reset the current position?

The Serial monitor indicates that the sketch is still running and intervals are correct but the motor is not moving anymore...

Given the above, and not seeing the serial output, I have trouble believing this statement.

    case S_RELEASE: // hold the camera steady BEFORE taking a shot for 2 seconds

      if (previousRelease == 0) {
        previousRelease = millis();
      }
      if (millis() - previousRelease >= (HoldTime * 500) )
      {
        Serial.println(F("hold after shot"));

The comment is the same as for the previous case. At least one of them is wrong.

The serial output is the same as the previous case. At least one of them is wrong. And, now I have even more trouble believing your statement above.

snewpers:
it'll run for the amount I have the mills set (the interval in my sketch). So if the interval is 6 seconds, it'll run for 6 seconds, regardless of # of steps I set.

I said earlier (in Reply #6) don't mix up millis() and the step count. Just let it continue for as long as it requires to get all the steps done. You don't need to use millis() at all in that context.

...R

Hi Paul

I have the holdtime set to 2 seconds (for instance). That's one second before the shot is taken and one second after the shot is taken (shuttertime may be slower).
So the holdtime in seconds * 500 results in half the holdtime in mseconds: 1000ms (when total holdtime is 2 seconds).

In the 'S_HOLD' case I reset the current motorposition to 0, so that the stepper can/will move n amount of steps (motor1Run).
When the states are all done, it resets again and the stepper will move (motor1Run) again. Without that resetting to 0 it will only run once, since the stepper is at the correct position.
The sketch continues to hold, shoot, hold, interval correctly but there is no moto movement after the first cycle of cases.

The serialmonitor show steps and time, I'll post an image when I get home.
The comment was a copy/paste mistake. Previous hold and previous release are two different milli-counts.

#include <AccelStepper.h>

long PreviousDelayMillis = 0;

int currentType = 0;
int value = 0;
int numIncr = 0;
int Min = 0;
int Max = 0;


int LinEndleft = 0;  // ENDSTOP LEFT  ---> use as:   if (LinEndleft == HIGH) { blaaah }
int LinEndRight = 0; // ENDSTOP RIGHT

int Confirm = 0; // confirm of init gezet is
int InitMode = 0; // zijn we in initmodes? Zo ja welke dan?
int InitStatus = 0; // init gedaan na opstarten? 0=nee

const int Step1End = 0;                             // eindpunt is 0, stepper telt af!
long Step1Start = 20000;                            // startpunt is de waarde uit INIT
const int Step2End = 0;                                   // eindpunt is 0, stepper telt af!
long Step2Start = 666;                              // startpunt is de waarde uit INIT
const int Step2Max = 360;                                 // mximaal aantal graden rotatie
int Srev = 200;                                     // number of steps per rev
char Fm = 1;                                        // MicroStepping Factor
char Pitch = 2;                                     // pitch in mm
int Nt = 20;                                        // Number of teeth
float Pstep = (Srev * Fm) / (Pitch * Nt);           // aantal steps per mm
float Pdist = 1 / Pstep;                            // aantal mm per steps

unsigned long TimeBetwenShots = 40; // USER INPUT tussen 4 - 1000 secondes between each shot
int TrackLength = 10000; //stappen kan ook maar lengte is nu length of track in mm
int RunTime = 1800; //1 hour to complete a 1000mm track komt van userinput vlaues [1] in seconden
int HoldTime = 2; //total holding time /s
unsigned long interval = (TimeBetwenShots - HoldTime) * 1000; // seconds to ms minus de holdtijd


long motor1Run = round(Step1Start / (RunTime / TimeBetwenShots));

float NumShots = RunTime / TimeBetwenShots; // total time devided by # shots
float MMBetweenShots = TrackLength / NumShots; // tracklength devided by shots
int Speed = 500; // StepperSpeed
AccelStepper stepper1(1, 5, 4);                   // stepper 1 pin setup step -  dir

void setup() {
  Serial.begin(9600);

}

void loop() {
  ShootIt();
}


unsigned long previousMillis = 0; // store last time
unsigned long previousHold = 0; // store last time a hold [before] was done
unsigned long previousRelease = 0; // store last time a hold [after] was done


//States
const int S_HOLD = 0;
const int S_SHOOT = 1;
const int S_RELEASE = 2;
const int S_MOVE = 3;

int StepperHasRun = 0;
int ShotCounterStatus = 0;



void ShootIt() {
  static int state = S_HOLD ;
  switch (state)
  {
    case S_HOLD:    // hold the camera steady BEFORE taking a shot for half the HOLDTIME
      if (previousHold == 0) {
        previousHold = millis();
      }
      if (millis() - previousHold >= (HoldTime * 500) )
      {
        Serial.println(F("hold before shot"));
        previousHold = 0;
        state = S_SHOOT;
        stepper1.setCurrentPosition(0);
      }
      break;


    case S_SHOOT:
      // fire the remote focus and shutter on PIN 11 + 12
      shoot();
      state = S_RELEASE;
      break;



    case S_RELEASE: // hold the camera steady AFTER taking a shot for half the HOLDTIME

      if (previousRelease == 0) {
        previousRelease = millis();
      }
      if (millis() - previousRelease >= (HoldTime * 500) )
      {
        Serial.println(F("hold after shot"));
        previousRelease = 0;
        state = S_MOVE;
      }
      break;



    case S_MOVE: // MOVE THE STEPPE n STEPS at n SPEED
      if (previousMillis == 0) {
        previousMillis = millis();
      }
      if (millis() - previousMillis >= interval)
      {

        Serial.print(F("Is interval: ")); Serial.println(interval);
        Serial.println(round(Step1Start / NumShots));
        Serial.println(stepper1.currentPosition());
        previousMillis = 0;
        state = S_HOLD;

      }

      stepper1.setMaxSpeed(Speed);
      stepper1.setSpeed(Speed);
      stepper1.moveTo(motor1Run);
      stepper1.runSpeedToPosition();

      break;

  } // end switch

} // end ShootIt()





void shoot()
{
  digitalWrite(11, HIGH); // focus up
  digitalWrite(12, HIGH); // shutter up
  digitalWrite(12, LOW); // shutter down
  digitalWrite(11, LOW); // focus diwn
  Serial.println(F("SHOT FIRED"));
  ShotCounterStatus = ShotCounterStatus + 1;
}

Hi Robin,

Agreed, but the sketch has changed since post #6, the new sketch is in post #8.
What I did in #6 was have the motor run for n amunt of ms, where I converted the steps (I wanted) into ms.
That's a terrible solution!

It works now, but it's blocking. It's not a major deal and it won't really do much harm, but the calculations are not accurate anymore.

My main goal is that I want the motor to be still just before and after a shot is taken and move to the next position 'in a hurry' and wait for the next shot to complete.
That's why I have millis in the S_MOVE case; that's the (adjusted) interval between shots and also the time period where the motor should run in.

I hope this made sense...

In the 'S_HOLD' case I reset the current motorposition to 0, so that the stepper can/will move n amount of steps (motor1Run).

But, you do that without caring that the stepper may still be moving. It seems to me that you need to make sure that the stepper has stopped before saying "Here's zero from now on".

snewpers:
It works now, but it's blocking.

So why not un-block it?

What about this

    case S_MOVE: // MOVE THE STEPPE n STEPS at n SPEED

        static bool init = true;
        if (init == true) {
            stepper1.setMaxSpeed(Speed);
            stepper1.setSpeed(Speed);
            stepper1.moveTo(motor1Run);
            init = false;
        }
        stepper1.run();
        if (stepper1.distanceToGo() == 0) {
            state = S_HOLD;
            init = true;
        }
        break;

...R

PaulS:
But, you do that without caring that the stepper may still be moving. It seems to me that you need to make sure that the stepper has stopped before saying "Here's zero from now on".

The holdingtime is longer than the time it takes to do the desired number of steps. If it it as problem after all, I could speed it up to 1000 steps/sec and that would surely be enough. No?

That being said, if the function is blocking, does that also block the mills count?

Robin2:
So why not un-block it?

What about this

    case S_MOVE: // MOVE THE STEPPE n STEPS at n SPEED

static bool init = true;
        if (init == true) {
            stepper1.setMaxSpeed(Speed);
            stepper1.setSpeed(Speed);
            stepper1.moveTo(motor1Run);
            init = false;
        }
        stepper1.run();
        if (stepper1.distanceToGo() == 0) {
            state = S_HOLD;
            init = true;
        }
        break;




...R

Hmm odd, I wrote a reply but somehow that wasn't posted before.

Anyway... I'll try that code but I miss the interval. The interval is basically the time between shots, minus the hold time. Without the interval, the only time between shots would be the holding time, which is something like 2 seconds.

I'll try the code anyway!

snewpers:
The interval is basically the time between shots, minus the hold time. Without the interval, the only time between shots would be the holding time, which is something like 2 seconds.

I don't think I understand.

If you need to take account of the time required for the motor to move in order to figure the time for the next photo then millis() will be doing that in the background without any effort by you. Just the same way your kitchen clock does.

...R

Yes correct,

The interval tim I use in S_MOVE is the time between shots. So I really need that interval. With the code you posted, that interval is missing and the motor did run (with acceleration) and kept running until the # of steps are reached. But there was no further interval time, so the next shot came too early.

Maybe this helps?

HOLD -----> SHOT -----> RELEASE [stepper]-------------interval------------> = time between shots

Everything after 'RELEASE' is simultaneous; the stepper moving and the interval count.

Reading your last post I assume that millis is not blocked by anything? If that's correct hen there is no further problem, other than that I should test if theres enough interval in each situation for the motor to run in.