noob can't exit a loop

Hello all! I’m getting good enough at this to start causing trouble for myself.

My trouble right now is exiting a loo and skipping part of a code after it initially executes… I have searched all afternoon for a solution to this and have tried a bunch of tricks, but I’m missing something.

Part 1:
What is simmers down to is that I want a light to pulse on and off while a button is held down (HIGH). Sounds simple, right? Trouble is that my pulse loops don’t stop when the button goes LOW.

I have modified the starter “Pulsing Light” example to show what I am trying to do rather than insert my whole code.

//Fade an LED in and out like on a sleeping Apple computer

#define LED 11 //the pin for the LED
#define Button 8

int ButtonState = 0;

int i = 0; //We’ll se this to count up and down

void setup() {
pinMode(LED, OUTPUT); //tell Arduino LED is an output
pinMode(Button, INPUT);
}
void loop()
{
ButtonState = digitalRead(Button);

if (ButtonState == HIGH)
{
analogWrite(LED, 225); //starts initial rapid blink
delay(50);
analogWrite(LED, 0);
delay(50);
analogWrite(LED, 225);
delay(50);
analogWrite(LED, 0);
delay(50); //end rapid blink
}

//start pulse
while(ButtonState == HIGH)
{
for (i = 0; i < 255;i++) //loop from 0 to 254(fade in)
{
analogWrite(LED, i); //set the LED brightness
delay(10);
}

delay(1000); //stay full bright for 1 sec
for (i = 255; i > 0; i–) //loop from 255 to 1 (fade out)
{
analogWrite(LED, i); //set the LED brightness
delay(10);
}
delay(1000); //stay full off for 1 sec
}
}
}

Now reading through that linearly, here is what I understand should happen: The code sets up, then checks the button state. If the button is LOW, the light shouldnt turn on. If HIGH, the light should start pulsing. Then the sequence repeats, again checking the button state.

What happens in actuality is that the light stays off until the button is pressed, turns on when the button is pressed, but then stays on even after the button is released. Why?

Part 2:
Ideally, when the button is held down the light will flash rapidly at first and then settle into a slow pulse which stops when the button is released. How do I keep the code checking the button state and maintaining the pulse while the button is HIGH, but skipping the initial rapid flash?

Thanks ya’all!

Not exactly sure, but I’m surprised the compiler didn’t catch the extra curly brace at the end… that might be the problem.

//Fade an LED in and out like on a sleeping Apple computer

#define LED 11 //the pin for the LED
#define Button 8

int ButtonState = 0;
 
int i = 0; //We'll se this to count up and down

void setup() {
  pinMode(LED, OUTPUT); //tell Arduino LED is an output
  pinMode(Button, INPUT);
}
void loop()
  {
    ButtonState = digitalRead(Button);
 
    if (ButtonState == HIGH)
      {
        analogWrite(LED, 225); //starts initial rapid blink
        delay(50);
        analogWrite(LED, 0);
        delay(50);
        analogWrite(LED, 225);
        delay(50);
        analogWrite(LED, 0);
        delay(50); //end rapid blink
      }//neamerjell: end if
   
  //start pulse
    while(ButtonState == HIGH)
    {
      for (i = 0; i < 255;i++) //loop from 0 to 254(fade in)
        {
          analogWrite(LED, i); //set the LED brightness
          delay(10);
        }//neamerjell: end for
 
     delay(1000); //stay full bright for 1 sec
     for (i = 255; i > 0; i--)  //loop from 255 to 1 (fade out)
        {
         analogWrite(LED, i); //set the LED brightness
         delay(10);
        }//neamerjell: end for
      delay(1000); //stay full off for 1 sec
    }//neamerjell: end while
  }//neamerjell: end of void loop()
}//neamerjell: extra, no matching opening curly brace

Ah, it actually did when I compiled it; I copied the code over a bit quick and dirty for the sake of an example :blush: Removed curly, problem persists.

Wouldn’t it stick in the “for (i = 0; i < 255;i++)” loop until it was finished regardless of the button state?

If that’s the issue, a kind of primitive way to do it is to put a digital read along with an if statement inside the loop, but I don’t know if that would work.

Although now that I look at it that doesn’t make much sense, but it’s something to try.

Here is your problem:

//start pulse while(ButtonState == HIGH) { /* code snipped */ }

The ButtonState is initially assigned by the digitalRead() at the top of the function, but within the while- loop it is never updated. If you want to inspect the state of the button again, you need to call digitalRead() again.

As you do not, if ButtonState once was HIGH, it stays that way, and the loop is never exited.

A possible solution could be inserting this just before the end of the loop:

while(ButtonState == HIGH) {

/* your existing code */

// Update ButtonState ButtonState= digitalRead( Button );

}

That should give your expected result.

Hope this helps!

Bingo! Thanks hugo75, that worked perfectly!

Wow! I missed that too, and I have an associate's degree in business computer programming. I getting rusty...

Of course, in my defense, I'm a complete noob when it comes to C.

Or instead of:

while(ButtonState == HIGH)
{

// yadda yadda

    // Update ButtonState
    ButtonState= digitalRead( Button );

}

do this:

while (digitalRead( Button ) == HIGH)
{

// yadda yadda

}

And by the way, to exit a loop you can use "break", eg.

while (something)
{

  if (something_else)
     break;  // exit loop

}

Hi,

I am just at the beginning of understanding coding too, and had to work through a similar problem just a short time ago today. My question sort of fits here at the end of this current thread, because now that I found a way out of the loop with the ‘break’ command, I want to start a second loop and do another segment of code. But I can’t figure out the correct way to do it. Each method I try ends up with errors during the verification. Since this is new to me, the errors don’t always make any sense as they are displayed. I am now following my second book for the Arduino - Arduino A Quick Start Guide. I got through the first project, and the author suggested playing with the rather simple code for the blinking LED to see if the reader could flash his initials in Morse Code. I opted for SOS instead. So what I hope to achieve is 3 loops of code, in which I can program 3 short, 3 long, and 3 short flashes.

Here is what I have so far, but I can’t figure out how to properly move into the second loop: (The first 3 lines use a variable definition protocol the book has yet to explain, so I just copied them not fully understanding their detail yet). How do I properly start the next loop? I tried using a second “void loop ()” and it caused an “error - redefinition of void loop - void loop previously defined here”. Yet in other posts on the forum I found multiple “void loop()” statements in code.

const unsigned int LED_PIN = 13;
const unsigned int PAUSE500 = 500;  //PAUSE 500 ms
const unsigned int PAUSE100 = 100;  //PAUSE 100 ms
int i = 0;	//counter for first loop
int j = 0;		//counter for second loop

void setup()  {
  pinMode(LED_PIN, OUTPUT);		//define pin 13 as output
}

void loop() 
//Start loop 1
					
{
   for (;i < 3; i = i + 1){			//check loop count <3, if so add one to count
      if (i > 2) break;			//if count > 2 bail out of this loop
      
    					

  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(PAUSE100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(PAUSE100);
    
   }

}

//Start loop 2

   for (;j < 3; j = j + 1){			//check loop count <3, if so add one to count
      if (j > 2) break;			//if count > 2 bail out of this loop
      
    

  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(PAUSE100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(PAUSE100);
  
   }

Zoandar:

for (;i < 3; i = i + 1){			//check loop count <3, if so add one to count

if (i > 2) break; //if count > 2 bail out of this loop

Errr …

So what I hope to achieve is 3 loops of code, in which I can program 3 short, 3 long, and 3 short flashes.

What you want to achieve is to do 3 short, 3 long and 3 short flashes. The term “loops of code” is perhaps misleading.

Keep it simple, your code has a number of issues, not the least of which is that you never re-initialize the variable “i”.

So for the 3 short flashes:

for (int i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop

That’s all. It’s overthinking it to try to have a “for” loop that counts to 3, and then inside that loop check if you have reached 3 yet. Similarly for the long flashes.

Now if you want to do the 3 short/long/short flashes many times then the appropriate place for that is in the loop function. Because it loops indefinitely. Otherwise put it in setup.

Personally I wouldn’t put “counters for loops” into the global variables. It’s confusing. Just declare them where you need to.

Thanks for the reply! I'll give your suggestions a try.

In order to keep the post from growing huge, I did not account for several changes I made to the code in the troubleshooting efforts I tried before I posted. The first thing I wanted to make happen was to get the continuously flashing LED to stop after flashing only 3 times. I was unsuccessful no matter what I tried changing until I finally moved the "int i = 0" OUTSIDE of the FOR loop and put it up at the top. I see you have me moving it back where it started, so I will expect this not to work again but I will try what you posted before passing judgment. :)

Once I got it to blink 3 times and stop, I did not yet 'clean up' the code I had been switching around, so perhaps that is why you see all the unneeded steps. That and I am completely new to this language, so not yet able to recognize clean code from messy code. :)

I wanted to develop this in steps. Make the first loop work and stop. Then make the second loop work and stop, etc. Once I was sure each loop worked on its own only then would I go back and make it so the loops progressed 1,2,3 and variables would then need to be re-initialized as the loops started over. But that was far from where I was having this problem.

Re-reading what you have posted I now see that you did not answer my original question. When I want to have

loop 1

loop2

how do I move correctly from loop1 to loop2? My loops may not be very good code at the moment, but I am trying to figure out how to do one loop after another, so at the moment not really concerned about the loops themselves as long as they start and end like they are supposed to so I can see what is happening on the LED.

One way is this:

int i;

// loop 1

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop

// loop 2

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(500);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(500);
  }  // end of loop

// loop 3

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop

And if you want to stop it doing anything else:

while (true) {}

That’s a loop it won’t get out of in a hurry!

The other thing is you don’t have to use their pre-designed “loop” idea. For one thing, you never need to leave “setup”.

So you could do this:

void setup ()
{
 // set stuff up here ...


loop1 ();

loop2 ();

loop3 ();

while (true) {}  // now just loop doing nothing

}

void loop ()
{}  // we never get here

void loop1 ()
 {

// do loop 1 stuff

 }

void loop2 ()
 {

// do loop 2 stuff

 }

void loop3 ()
 {

// do loop 3 stuff

 }

But the names are a bit misleading. I think you might be calling a loop what I would call a function. If you want to “make a loop work and stop” well it isn’t really a loop is it? For me, a loop is something that, well, loops. Repeats. Does things multiple times.

The first thing I wanted to make happen was to get the continuously flashing LED to stop after flashing only 3 times.

Well you didn’t say originally “to stop after flashing 3 times” so my original code wouldn’t stop. All this talk about loops implies something that doesn’t stop.

My original code would work if you simply moved it from “loop” to “setup” because setup is done once, and loop is done many times.

Thanks. I am trying to work this out one step at a time. Once I can adapt to this very steep learning curve of trying to learn the Arduino’s variant of C++ and the Arduino project building, both at the same time, I will hopefully be better able to see how things need to be. But for now I am at a “cold start” on this, and the engine “isn’t starting”. :slight_smile:

I have whittled the many errors I was getting when I tried just your your example (because it was not a ‘complete code segment’) down to one single error, which is

“Basic_Loop_Structure:8: error: expected unqualified-id before ‘{’ token”. It highlights the pair of braces beginning just above “void setup()” and the very last brace. Without those there, I get about 8 errors, so I thought they needed to be there. I am guessing here and have no idea what this cryptic error really means. When I tried earlier today to look for some C++ beginner tutorials, I did not find anything that seems to fit the parameters I have seen so far through the first book “Getting Started With Arduino”. It seems there a many variants of C++, and the Arduino IDE doesn’t use some of the things being taught on those tutorials, so they start right out telling me I need things like "# include " which I do not think is even pertinent here. So I am left to try to work this out by only seeing what is in these books I have on Arduino, and I am finding it very hard to crack the shell on getting into this.

Can you tell me what that error means, and what I need to add (or remove) to fix it?

//Basic loop structure compliments of forum

int LED_PIN = 13;
int i = 0;

{
void setup () {
  pinMode(LED_PIN, OUTPUT);
}



// loop 1

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop

// loop 2

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(500);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(500);
  }  // end of loop

// loop 3

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop
  
}

Don’t just throw in brackets to get rid of errors, as you saw that just creates more. This works, and it makes the LEDs blink nicely. Compare to yours to see the difference:

//Basic loop structure compliments of forum

int LED_PIN = 13;
int i = 0;

void setup () {
  pinMode(LED_PIN, OUTPUT);



// loop 1

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop

// loop 2

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(500);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(500);
  }  // end of loop

// loop 3

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop
  
}

 void loop ()
 {
 // nothing to do in loop
 
 }

Just to explain, there is nothing in the “loop” function. Since you only want to do it once, we put the loops (which are not loop functions, just loops) into “setup”.

Aha! I now see what you mean by putting it "inside setup". :) One of my hurdles is that I have only the code in the book projects upon which to build. The author of Arduino A Quick Start Guide had put a suggestion at the end of the first LED blinking project to see if the reader could modify the code learned so far to make it blink his initials. But I know that not everyone writes code the same way. I have some background in coding in MS Basic, but that was a very long time ago (TRS-80 Model 1!). As such I also remember that a single misplaced character can disable a subroutine or even the whole program. So I know to be very careful. I just need more experience. In retrospect, asking the reader to do something that much different from the example code right at the start of the book might not be the best idea. :)

I had added those brackets to try and fix the errors because I was thinking "code needs to be enclosed in brackets". So in a way I was trying to put the code inside Setup, I just didn't do it right.

Now, as far as my wanting to use "loops" goes, once I get past the part we are at here, I was intending to set up the program so that it does the SOS thing and then repeats and does it again, over and over. So for that I need to loop the whole segment we have in Setup, I guess. With what we have now, I think "subroutine" would have been a better description instead of loop, but as I understand it the true meaning of subroutine would mean I would have the code to do "S" and the code to do "O", and then tell the main program to 'call S' , call O, call S again. Maybe I should use the term "block" for an embedded segment of code?

Anyway, I'm gettin' there, many thanks to YOU!! :)

Yes, subroutine, function, procedure are all more-or-less synonyms.

My suggestion now is to make a function called "dot" and another called "dash" which do the obvious things of blinking the LED once of the correct length.

You could get fancy and make a function that does each letter of Morse (if you are going for the general approach), of which S and O are two examples.

This function would call dot and dash the required number of times (based on a table of the values, or a big "switch" statement).

Then you could do SOS by calling this new one with the appropriate letters. All good learning stuff.

I agree! That sounds like a good way to reinforce what I am learning here. :slight_smile:

I have it working, but for some reason the number of LED flashes isn’t correlating as it should?? Here is what I had to do to get it to flash 3 times for each letter. I also added in an 800ms pause after the code is loaded into the UNO, because all the Tx/Rx flashing gets confusing if the code starts right away when trying to count the flashes. Note that I have the variable “i” set to 2, 4, 3 but I am seeing 3 flashes in each block. Why might it be doing that?

//Basic loop structure compliments of forum

int LED_PIN = 13;
int i = 0;

void setup () {
  pinMode(LED_PIN, OUTPUT);

  delay(800);

// loop 1

for (i = 0; i < 2; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop

// loop 2

for (i = 0; i < 4; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(500);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(500);
  }  // end of loop

// loop 3

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(100);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(100);
  }  // end of loop
  
}

 void loop ()
 {
 // nothing to do in loop
 
 }

If you unravel the first two loops you see why:

digitalWrite(LED_PIN, LOW);		//LED Off
delay(100);

// loop 2

digitalWrite(LED_PIN, HIGH);		//LED On
delay(500);

The first loop ends with a short delay, so the first flash in the second loop looks like the last flash in the first loop.

So you have:

short flash
short gap
long flash ← this looks like part of the short flash group
long gap

Think about that, and what minor re-arranging you could make to have it look better. I noticed it myself, but thought I would leave that for you. :wink: Well at least that’s my story.

But I wouldn’t change the number of flashes, that is only hiding the true problem.

I will put a longer delay between each block and try it again. Thanks!

I now have the repeating SOS that I set out to do from the start. :grin: Thanks VERY much for your help with this!! I think I’ll now try the subroutine method you mentioned earlier, before I continue on with the book. Here is the repeating SOS code:

//Repeating SOS

int LED_PIN = 13;
int i = 0;

void setup () {
  pinMode(LED_PIN, OUTPUT);
  delay(800);
}
  
  
 void loop ()
 {
 

// Send S 3 times

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(120);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(120);
  }  // end of Send S 3 times

delay(500);

// Send O 3 times

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(500);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(500);
  }  // end of loop Send O 3 times
  
delay(500);

// Send S 3 times

for (i = 0; i < 3; i++)
  {
  digitalWrite(LED_PIN, HIGH);		//LED On
  delay(120);
  digitalWrite(LED_PIN, LOW);		//LED Off
  delay(120);
  }  // end of Send S 3 times
delay(800);
}