Help with a problem using while and if statements together

Hi all, I am just writing some code for a simple time lapse controller that I've built.

I am trying to integrate a button, and once it is pressed (to gnd) I want to go into a while loop with a counter built in.

The code compiles and is running, but its running through the if and for loops constantly, irrespective of the button state?

What am I doing wrong guys?

Thanks

#include <LiquidCrystal.h>


//Pin naming
int focusPin = 2;
//int focusLED = 13;
int shutterPin = 4;
int shutterLED = 13;
int enterButton = A2;
int pauseButton = A1;
int LDRPin = A5;      // Analog input pin that the lDR is attached to
int LCDBackLight = 3;      // Analog (PWM) output pin that the BACKLIGHT is attached to
int amountPot = A4;
int intervalPot = A3;


//Parameters
int focusDelay = 800;
int shutterDelay = 800;
//int interval = 20000;
int maxInterval = 600000; //Max interval between shots in millis allowed
int maxAmount = 1000; //Maxium amount of shots allowed

const int minLight = 40;        // at or below this light level, use minimum backlight intensity
const int maxLight = 900;        // at or above this light level, use maximum backlight intensity
const int minBacklight = 20;      // lowest backlight intensity to use
const int maxBacklight = 255;    // highest backlight intensity to use

int LDRRead = 0;         // value read from the LDR
int outputValue = 0;     // value output to the PWM (analog out)

int intervalRead = 0;         // value read from the interval pot
int amountRead = 0;         // value read from amount of photos pot

int interval = 0;
int amount = 0;





// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {

  //Set up LCD
  lcd.begin(16, 2);
  delay(100);

  //Set up pins
  pinMode(focusPin, OUTPUT);
  pinMode(shutterPin, OUTPUT);
  pinMode(shutterLED, OUTPUT);
  pinMode(LCDBackLight, OUTPUT); 
  pinMode(enterButton, INPUT);
  pinMode(pauseButton, INPUT);


  //enable pull ups on buttons
  digitalWrite(enterButton, HIGH);
  digitalWrite(pauseButton, HIGH);


}


void loop(){


  int shots = 0;

  // LDR controlled LCD backlight via PWM part
  int sum = 0;
  for (int i=0; i<16; i++) // take 16 samples from the analog input
  {
    sum += analogRead(LDRPin);
  }
  LDRRead = sum/16; // divide by the amount of samples for the average value

  // map it to the range[0..255] of the analog output that the LCD backlight it connected to
  outputValue = LDRRead/4;   // alternative to map function for scaling down from analog input
  outputValue = map(constrain(LDRRead, minLight, maxLight), minLight, maxLight, minBacklight, maxBacklight );

  // change the analog out value to adjust LCD backlight intensity
  analogWrite(LCDBackLight, outputValue);   



  // read interval from pot
  intervalRead = analogRead(intervalPot);
  interval = map (interval, 0, 1023, 0, maxInterval);

  // read amount from pot
  // amountRead = analogRead(amountPot);
  //amount = map (amount, 0, 1023, 0, maxAmount);

  amount = 10;


  lcd.setCursor(0,0);
  lcd.print("Shots:");
  lcd.print(amount  );

  lcd.setCursor(0,1);
  lcd.print("Delay:");
  lcd.print(interval  );



  digitalRead(enterButton);



  if (enterButton == LOW);
  {

    while (shots < amount)
    {


      lcd.setCursor(0,0);
      lcd.print("Shots:");
      lcd.print(amount);
      lcd.print("/");
      lcd.print(shots + 1  );

      //Trigger focus
      digitalWrite(focusPin, HIGH);
      delay(focusDelay);

      //Trigger shutter
      digitalWrite(shutterPin, HIGH);
      digitalWrite(shutterLED, HIGH);
      delay(shutterDelay);
      digitalWrite(shutterPin, LOW);
      digitalWrite(shutterLED, LOW);
      digitalWrite(focusPin, LOW);

      delay(interval);


      shots++;
    }



  }

  if (enterButton == HIGH);
  {
    //do nothing
  }
}
digitalRead(enterButton);

This reads the value but throws it away. You need to declare a variable and test that.

  int bval;

  bval = digitalRead(enterButton);


  if (bval == LOW);

Pete

Do not put a ; after an if statement if you want it to do anything.

Thanks guys, I hoped it was only something simple.

Is it possible to run something only once when the for loop becomes untrue - ie, clear the display or update it with some text after the duration has run?

Thanks again

Is it possible to run something only once when the for loop becomes untrue

Not sure what this means.
Generally you can do anything you like using if statements and Boolean flags.

sorry Mike I meant the while loop.

Id like to display a message on the lcd after the final shot has taken and leave it there until the enter button is pressed, then it will exit the while loop.

so basically just as the while loop is exiting id like to perform a task, but only once?

Thanks

You would normally perform it just after the while loop.

The only way of doing it inside the while loop would be to duplicate the test the while loop does inside the while loop - wasteful.

Just do it after the while loop has finished.

Hi, thanks. That's true pretty illogical of me not to think of just putting it after :stuck_out_tongue:

I must be doing something else wrong, because now it sits in the final while loop and the message stays on screen when the enter button is pressed?

#include <LiquidCrystal.h>


//Pin naming
int focusPin = 2;
//int focusLED = 13;
int shutterPin = 4;
int shutterLED = 13;
int enterButton = A2;
int pauseButton = A1;
int LDRPin = A5;      // Analog input pin that the lDR is attached to
int LCDBackLight = 3;      // Analog (PWM) output pin that the BACKLIGHT is attached to
int amountPot = A4;
int intervalPot = A3;


//Parameters
int focusDelay = 800;
int shutterDelay = 800;
//int interval = 20000;
int maxInterval = 600000; //Max interval between shots in millis allowed
int maxAmount = 1000; //Maxium amount of shots allowed

const int minLight = 40;        // at or below this light level, use minimum backlight intensity
const int maxLight = 900;        // at or above this light level, use maximum backlight intensity
const int minBacklight = 20;      // lowest backlight intensity to use
const int maxBacklight = 255;    // highest backlight intensity to use

int LDRRead = 0;         // value read from the LDR
int outputValue = 0;     // value output to the PWM (analog out)

int intervalRead = 0;         // value read from the interval pot
int amountRead = 0;         // value read from amount of photos pot

int interval = 0;
int amount = 0;





// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {

  //Set up LCD
  lcd.begin(16, 2);
  delay(100);

  //Set up pins
  pinMode(focusPin, OUTPUT);
  pinMode(shutterPin, OUTPUT);
  pinMode(shutterLED, OUTPUT);
  pinMode(LCDBackLight, OUTPUT); 
  pinMode(enterButton, INPUT);
  pinMode(pauseButton, INPUT);


  //enable pull ups on buttons
  digitalWrite(enterButton, HIGH);
  digitalWrite(pauseButton, HIGH);


}


void loop(){


  int shots = 0;

  // LDR controlled LCD backlight via PWM part
  int sum = 0;
  for (int i=0; i<16; i++) // take 16 samples from the analog input
  {
    sum += analogRead(LDRPin);
  }
  LDRRead = sum/16; // divide by the amount of samples for the average value

  // map it to the range[0..255] of the analog output that the LCD backlight it connected to
  outputValue = LDRRead/4;   // alternative to map function for scaling down from analog input
  outputValue = map(constrain(LDRRead, minLight, maxLight), minLight, maxLight, minBacklight, maxBacklight );

  // change the analog out value to adjust LCD backlight intensity
  analogWrite(LCDBackLight, outputValue);   



  // read interval from pot
  intervalRead = analogRead(intervalPot);
  interval = map (interval, 0, 1023, 0, maxInterval);

  // read amount from pot
  // amountRead = analogRead(amountPot);
  //amount = map (amount, 0, 1023, 0, maxAmount);

  amount = 10;


  lcd.setCursor(0,0);
  lcd.print("Shots:");
  lcd.print(amount  );

  lcd.setCursor(0,1);
  lcd.print("Delay:");
  lcd.print(interval  );


  int bval;

  bval = digitalRead(enterButton);


  //if the enter button is pressed, execute the following loop
  if (bval == LOW)
  {
    //run though the shutter loop until the number of shots has been reached
    while (shots < amount)
    {

      // LDR controlled LCD backlight via PWM part
      int sum = 0;
      for (int i=0; i<16; i++)
      {
        sum += analogRead(LDRPin);
      }
      LDRRead = sum/16;
      outputValue = LDRRead/4;  
      outputValue = map(constrain(LDRRead, minLight, maxLight), minLight, maxLight, minBacklight, maxBacklight );
      analogWrite(LCDBackLight, outputValue); 


      lcd.setCursor(0,0);
      lcd.print("Shots:");
      lcd.print(amount);
      lcd.print("/");
      lcd.print(shots + 1  );

      //Trigger focus
      digitalWrite(focusPin, HIGH);
      delay(focusDelay);

      //Trigger shutter
      digitalWrite(shutterPin, HIGH);
      digitalWrite(shutterLED, HIGH);
      delay(shutterDelay);
      digitalWrite(shutterPin, LOW);
      digitalWrite(shutterLED, LOW);
      digitalWrite(focusPin, LOW);

      delay(interval + focusDelay + shutterDelay);

      lcd.clear();
      shots++;
    }
    //display message on the lcd and wait for enter button press
    bval = digitalRead(enterButton);
    while (bval == HIGH)
    {
      lcd.setCursor(0,0);
      lcd.print(shots);
      lcd.print(" Shots taken");

    }

  }


  //if enter button has not been pressed, do nothing and keep waiting
  if (bval == HIGH)
  {
    //do nothing
  }


}

The final while loop doesn't call digitalRead so it can never see any change - stop using bval and just put the calls to digitalRead() directly in the while and if conditions.

Thanks Mark, I still can't get it work - currently the final while while loop gets ignored and the program goes back to the start. Not sure what I'm doing wrong?

#include <LiquidCrystal.h>


//Pin naming
int focusPin = 2;
//int focusLED = 13;
int shutterPin = 4;
int shutterLED = 13;
int enterButton = A2;
int pauseButton = A1;
int LDRPin = A5;      // Analog input pin that the lDR is attached to
int LCDBackLight = 3;      // Analog (PWM) output pin that the BACKLIGHT is attached to
int amountPot = A4;
int intervalPot = A3;


//Parameters
int focusDelay = 800;
int shutterDelay = 800;
//int interval = 20000;
int maxInterval = 600000; //Max interval between shots in millis allowed
int maxAmount = 1000; //Maxium amount of shots allowed

const int minLight = 40;        // at or below this light level, use minimum backlight intensity
const int maxLight = 900;        // at or above this light level, use maximum backlight intensity
const int minBacklight = 20;      // lowest backlight intensity to use
const int maxBacklight = 255;    // highest backlight intensity to use

int LDRRead = 0;         // value read from the LDR
int outputValue = 0;     // value output to the PWM (analog out)

int intervalRead = 0;         // value read from the interval pot
int amountRead = 0;         // value read from amount of photos pot

int interval = 0;
int amount = 0;





// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {

  //Set up LCD
  lcd.begin(16, 2);
  delay(100);

  //Set up pins
  pinMode(focusPin, OUTPUT);
  pinMode(shutterPin, OUTPUT);
  pinMode(shutterLED, OUTPUT);
  pinMode(LCDBackLight, OUTPUT); 
  pinMode(enterButton, INPUT);
  pinMode(pauseButton, INPUT);


  //enable pull ups on buttons
  digitalWrite(enterButton, HIGH);
  digitalWrite(pauseButton, HIGH);


}


void loop(){


  int shots = 0;

  // LDR controlled LCD backlight via PWM part
  int sum = 0;
  for (int i=0; i<16; i++) // take 16 samples from the analog input
  {
    sum += analogRead(LDRPin);
  }
  LDRRead = sum/16; // divide by the amount of samples for the average value

  // map it to the range[0..255] of the analog output that the LCD backlight it connected to
  outputValue = LDRRead/4;   // alternative to map function for scaling down from analog input
  outputValue = map(constrain(LDRRead, minLight, maxLight), minLight, maxLight, minBacklight, maxBacklight );

  // change the analog out value to adjust LCD backlight intensity
  analogWrite(LCDBackLight, outputValue);   



  // read interval from pot
  intervalRead = analogRead(intervalPot);
  interval = map (interval, 0, 1023, 0, maxInterval);

  // read amount from pot
  // amountRead = analogRead(amountPot);
  //amount = map (amount, 0, 1023, 0, maxAmount);

  amount = 10;


  lcd.setCursor(0,0);
  lcd.print("Shots:");
  lcd.print(amount  );

  lcd.setCursor(0,1);
  lcd.print("Delay:");
  lcd.print(interval  );


  int bval;

  bval = digitalRead(enterButton);


  //if the enter button is pressed, execute the following loop
  if (bval == LOW)
  {
    //run though the shutter loop until the number of shots has been reached
    while (shots < amount)
    {

      // LDR controlled LCD backlight via PWM part
      int sum = 0;
      for (int i=0; i<16; i++)
      {
        sum += analogRead(LDRPin);
      }
      LDRRead = sum/16;
      outputValue = LDRRead/4;  
      outputValue = map(constrain(LDRRead, minLight, maxLight), minLight, maxLight, minBacklight, maxBacklight );
      analogWrite(LCDBackLight, outputValue); 


      lcd.setCursor(0,0);
      lcd.print("Shots:");
      lcd.print(amount);
      lcd.print("/");
      lcd.print(shots + 1  );

      //Trigger focus
      digitalWrite(focusPin, HIGH);
      delay(focusDelay);

      //Trigger shutter
      digitalWrite(shutterPin, HIGH);
      digitalWrite(shutterLED, HIGH);
      delay(shutterDelay);
      digitalWrite(shutterPin, LOW);
      digitalWrite(shutterLED, LOW);
      digitalWrite(focusPin, LOW);

      delay(interval + focusDelay + shutterDelay);

      lcd.clear();
      shots++;
    }
    //display message on the lcd and wait for enter button press
    digitalRead(enterButton);
    while (enterButton == HIGH)
    {
      lcd.setCursor(0,0);
      lcd.print(shots);
      lcd.print(" Shots taken");
      digitalRead(enterButton);
    }

  }


  //if enter button has not been pressed, do nothing and keep waiting
  if (bval == HIGH)
  {
    //do nothing
  }


}

Again you are not reading the value from the button in the while loop.
There is no need to keep putting the value on the screen with a while loop, once is enough.

I have written a rather good (if I do say so myself :slight_smile: ) tutorial on using the while loop:

http://hacking.majenko.co.uk/the-while-loop

It explains to you how to do it properly. I suggest you read it through - it's not too long.

Thanks guys, got it going now. Great tutorial, it really helped. I'm just reading the pin only in the while loop now as you suggest :slight_smile:

next step is to get rid of the delays and use a counter so I can do other tasks such as update the display, should be fun trying to get that working!