exiting a loop - terminating process.

Hi. Completely noob question - confused. In the code below I want to count the number of void loop() iterations then terminate by setting all pins LOW. I need to make sure that all is 'dead' before switching off the power to the board.

I have adapted this sketch from a previous project in which switches were sensed. This program will run for hours in the middle of the night unattended - imaging the stars on an equatorial mount. Yet to write the code for wake - for the time being an external timer.

I don't think I understand the while and for expressions - try as I may - either the process terminates after 1 iteration or keeps going or terminates after 5 iterations where I have a constant of 3 (I have not been able to replicate this last behaviour).

// only the relevant stuff

const int iterations = 3;
int var = 0;

void loop(){
// Locks up camera mirror, waits then opens camera shutter, takes shot, then a stepper repositions the camera for next shot - this all works fine.

// Now I want to terminate camera and stepper activation by setting all pins low.
}
for (var=0; var < iterations; var++);{

// this where I get stuck - something in here to set all pins LOW and stop all processes
// based on number of iterations declared...
}
// set all pins LOW here.
}
}

Thanks for looking :slight_smile:

Posting code that will not compile wastes everyone's time.

All executable code needs to be placed inside a function - setup(), loop(), or a user-defined function. Most of your code is not.

while and for loops behave similarly but their syntax is different.

From the Arduino reference:
"while loops will loop continuously, and infinitely, until the expression inside the parenthesis, () becomes false. "
"The for statement is used to repeat a block of statements enclosed in curly braces. An increment counter is usually used to increment and terminate the loop. " What do you get confused about?

corrections:

const int iterations = 3;
int var = 0;

void loop(){
// Locks up camera mirror...

// Now I want to terminate ...
} /* You're closing the void loop here, remove it. did the compiler thrown an error? */
/*/// remove the semicolon after the closing parenthesis in the for declaration //////// */
for (var=0; var < iterations; var++);{ 

// this where I get stuck - something in here to set all pins LOW and stop all processes
// based on number of iterations declared...
}
// set all pins LOW here.
}
} /*////// not needed, remove //////*/

since you cannot exit the 'void loop()' you can use an infinite loop at the end of your code, after turning off everything. like so, while(true){ };.

The problem here is the Arduino is not running standard C - there's no main() visible in a sketch. Instead, you get one call of setup(), followed by a repeated call to loop() - so everything outside of these functions is ignored, unless you call it from inside (like a function).

If I misunderstood, and the line with var is meant to be inside loop(), then the problem is how to trigger it - do you want to use a switch, a timer, etc.? You could easily add a switch, and when it is detected, set all the pins to low and loop endlessly - the closest thing the Arduino has to exit().

My apologies. Here is the full sketch comments and all. I'm self taught and this is my second production sketch. I'm sure that it can do with polish.

Thanks for the feedback. I have tried the examples provided without success. Use of while statements exits the loop on the first iteration.

Given that this sketch is fairly simple and only needs to shutdown after a prescribed period of time, I have adapted the blink without delay script. The only criteria needed to define the number of exposures is how long the board has been running.

Number of frames could also be used. I've tried both methods without success, and for, while, switch, goto, break..

Thanks again.

#include <Stepper.h> 
/*Ditherbot/Sparehand. Adapted from DoubleArmDrive sketch 2007 - 
 http://www.synergous.com
 
 This sketch automates multiple long exposure imaging using a 
 Canon DSLR Camera and stepper driven Ditherbot/Sparehand, pressing
 4 pushbutton switches on the hand controller of an equatorial mount.
 I want to keep it in its original condition.

 The image sequencing and dithering is independent of any equatorial 
 mount electronics/software and hardware, which is negatively earthed -
 an antique.
 
 Dithering - moving the camera between shots so that subsequent images 
 does not fall on the same sensor pixels -  improves image quality. 
 The Ditherbot/Sparehand repositioning in RA and DEC, between exposures.
 
 The stepper motor is bipolar - some rewriting will be needed for
 3 wire reluctance motors out of CDROM drives. Unipolars
 require different electronics.
 
 A pdf of the very basic motor shield (PCB) can be downloaded from 
 http://www.synergous.com - see the Double Arm Drive page - its near 
 the bottom of the page under the Electronics sub-heading.
 
 Change the next 5 lines as required for motor resolution, session time, exposure, 
mirror delay and dither speed. It should only be necessary to change session time 
thereafter. 
Rule of thumb, timing not critical - e.g 8 x 7 minute exposures provides 30 seconds 
between exposures per hour; that is, 32 frames in 4 hours - set for 4 hours 15 minutes 
for full 4 hours of exposure.
 */

//change number of motor steps to suit motor
#define motorSteps 200

//change the session time
long sessiontime = 10000;

//change this line to set exposure time.
int exposuretime = 2000; //milliseconds

//change this line to set mirror delay
int mirrordelay = 1000;

//change this line to set dither speed
int ditherspeed = 10;

long previousMillis = 0;

int shutterPin = 8;

int mirrorPin = 11; 

bool exposing = false;

//Stepper
#define motorPin1 4
#define motorPin2 5
#define motorPin3 6
#define motorPin4 7

//initialize stepper library
Stepper stepper(motorSteps, motorPin1,motorPin2,motorPin3,motorPin4);

//LED
int ledPin = 13; //on indicates dithering in progress

void setup() {
  pinMode(shutterPin, OUTPUT);
  pinMode(mirrorPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
}
void loop() {
  { 
    digitalWrite(mirrorPin, HIGH);
    delay(mirrordelay);
    digitalWrite(shutterPin, HIGH);
    exposing = true; //shutter open - probably superfluous  
    if (exposing == true) //safe guard - probably superfluous
    { //no dither
      stepper.setSpeed(0); // just don't want the stepper moving
      stepper.step(0);        // it's stationary anyway - think about removing these lines
      digitalWrite(ledPin, LOW);
      delay(exposuretime);
    }
    digitalWrite(shutterPin, LOW);
    digitalWrite(mirrorPin, LOW);
    exposing = false;
    if (exposing == false) //shutter closed - same superfluous?
    { //dither
      digitalWrite(ledPin, HIGH);
      stepper.setSpeed(5);
      stepper.step(50);
    }
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > sessiontime)
    {
      digitalWrite(shutterPin, LOW);
      digitalWrite(mirrorPin, LOW);
      stepper.setSpeed(0); 
      stepper.step(0);
    }
  }
}

If I understand it, this is the code to quit:

    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > sessiontime)
    {
      digitalWrite(shutterPin, LOW);
      digitalWrite(mirrorPin, LOW);
      stepper.setSpeed(0); 
      stepper.step(0);
    }
  }
}

At the end, it will fall out of loop(), then come back in at the top (since loop() is itself inside a loop), and continue.

What you want to do is wait forever inside this test once you've shut everything down:

    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > sessiontime)
    {
      digitalWrite(shutterPin, LOW);
      digitalWrite(mirrorPin, LOW);
      stepper.setSpeed(0); 
      stepper.step(0);
      while (1) { } // <-- wait here forever
    }
  }
}

The while(1) { } here will just loop forever, until you shut down/reset your Arduino.

what the purpose of previousMillis? I dont see it being used anywhere in the code. Maybe (currentMillis > sessiontime) will do fine.

The while(1) { } here will just loop forever, until you shut down/reset your Arduino.

I have tried this several ways.

the offending line appears to be

unsigned long currentMillis = millis();
//placed here the loop terminates after 2 iterations.
unsigned long currentMillis = millis();

// pin setting prior to while is redundant

      if (currentMillis - previousMillis > sessiontime)
      
        while (1) {
        }
      }
    }
  }
}
// written this way the loop continues
 if (currentMillis - previousMillis > sessiontime)

        while (1) {
        }
      }
    }
  }
}

All I want to do is check the time the board has been running and terminate the process once the session time is up.

@David

The problem here is the Arduino is not running standard C - there's no main() visible in a sketch. Instead, you get one call of setup(), followed by a repeated call to loop() - so everything outside of these functions is ignored, unless you call it from inside (like a function).

But of course we can call our own main() from setup()

void setup()
{
  myMain();
}

void loop() {}

or change main.cpp - C:\Program Files (x86)\arduino-0022\hardware\arduino\cores\arduino - into something completely different ... e.g.

#include <WProgram.h>

int main(void)
{
  bool stopLoop = false;

  while (true)
  {
    init();
    setup();
    for ( ;stopLoop == false ; )  loop();
    stopLoop = false;
    postMortem();
  }
  return 0;
}

and you have the ability to exit loop by setting stopLoop to true ... the application will call postMortem once and if postMortem() exits it start again.

I notice your code never changes previousMillis=0 and sessiontime=10000, so this

if(currentMillis - previousMillis > sessiontime)

is really this:

if(currentMillis - 0 > 10000)

or

if(currentMillis > 10000)

That means that 10 seconds into the program it falls in here and continues to do so - is that what you want?

Perhaps you want a separate time check for stopping, with a long delay:

if(currentMillis > 10000000) // 10,000 sec about 3 hrs
  while (1) { } // wait forever

Actually, stepping away from the problem, I can see that I've made things difficult for myself. It's very simple - thanks David.

The board will not stop while the stepper is active - a session time of 30 seconds means a board time of ~34 seconds with delays. This is accounted for in the imaging run, with significant delays between exposures.

Thanks again

 #include <Stepper.h>
 Change the next five lines as required
 
 */

//change number of motor steps to suit motor
#define motorSteps 200

//change number of frames to shoot
long sessiontime = 30000;


//change this line to set exposure time.
int exposuretime = 2000; //milliseconds

//change this line to set mirror delay
int mirrordelay = 1000;

//change this line to set dither speed
int ditherspeed = 10;

long unsigned time;

int settle = 1000;

int shutterPin = 8;

int mirrorPin = 11; 

bool exposing = false;

//Stepper
#define motorPin1 4
#define motorPin2 5
#define motorPin3 6
#define motorPin4 7

//initialize stepper library
Stepper stepper(motorSteps, motorPin1,motorPin2,motorPin3,motorPin4);

//LED
int ledPin = 13; //if its on dithering is in progress

void setup() {
  pinMode(shutterPin, OUTPUT);
  pinMode(mirrorPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
}
void loop() {
  { 
    digitalWrite(mirrorPin, HIGH);
    delay(mirrordelay);
    digitalWrite(shutterPin, HIGH);
    delay(exposuretime);
  }
  digitalWrite(shutterPin, LOW);
  digitalWrite(mirrorPin, LOW);
  exposing = false;
  if (exposing == false) //shutter closed
  { //dither
    digitalWrite(ledPin, HIGH);
    stepper.setSpeed(5);
    stepper.step(50);
    delay(settle);
    {
      time = millis();               // time board has been running
      if (time >= sessiontime) // this only works with >= for this application
        while(1){
        }
    }
  }
}

David. I think we crossed paths.

You are correct. In the meantime, I've solved it another way - board time vs sessiontime. Thanks again for your help.

Rowland.

I found that it is possible for the session to end with the camera locked into an exposure. Also, I've used long unsigned time for the delays, because int doesn't handle the long times required of this program. long works too - does it really matter - there are no negative numbers to consider as far as timing is concerned.

The sketch finished up looking like this.

#include <Stepper.h>

 Change the next five lines as required
 
 */

//change number of motor steps to suit motor
#define motorSteps 200
int steps = 50;
int rpm = 5;

//change sessiontime = 
// (exposuretime+mirrordelay+motortime+printdelay)*exposures
// dithering time = 3000; time print delay = 1000;
long unsigned sessiontime = 15408000;

//change this line to set exposure time.
long unsigned exposuretime = 420000; //milliseconds

//change this line to set mirror delay
long unsigned mirrordelay = 4000;

//change this line to set dither speed

long unsigned time;

int shutterPin = 8;

int mirrorPin = 11; 

bool exposing = false;

//Stepper
#define motorPin1 4
#define motorPin2 5
#define motorPin3 6
#define motorPin4 7

//initialize stepper library
Stepper stepper(motorSteps, motorPin1,motorPin2,motorPin3,motorPin4);

//LED
int ledPin = 13; //if its on dithering is in progress

void setup() {
  pinMode(shutterPin, OUTPUT);
  pinMode(mirrorPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);
}
void loop() {
  { 
    digitalWrite(mirrorPin, HIGH);
    delay(mirrordelay);
    digitalWrite(shutterPin, HIGH);
    delay(exposuretime);
  }
  digitalWrite(shutterPin, LOW);
  digitalWrite(mirrorPin, LOW);
  exposing = false;
  if (exposing == false) //shutter closed
  { //dither
    digitalWrite(ledPin, HIGH);
    stepper.setSpeed(rpm);
    stepper.step(steps);
    { 
      Serial.print("Time: ");
      time = millis();
      Serial.println(time);
      delay(1000);
      time = millis();
      if (time >= sessiontime)
      {
        digitalWrite(shutterPin, LOW);
        digitalWrite(mirrorPin, LOW);
        {
          while(1){
          }
        }
      }
    }
  }
}

geoland:
David. I think we crossed paths.

No problem - I'm just glad it was something solvable!