Run loop while pressed button

Hello, community (edited, sorry!)
I have been trying to run a loop while a button is pressed and stop the loop when depressed, but I can’t find the right code for that.
I have fade-in and out leads that I want to run while the button is pressed.
I have deleted the button lines so I can have a fresh start.
I deeply appreciate some help. Thanks!
Here is the code so far (no button code added).




void setup () 
{ 
  pinMode(2,OUTPUT);// declare pin 2 to be an output
  pinMode(3,OUTPUT);// declare pin 3 to be an output
  pinMode(4,OUTPUT);// declare pin 4 to be an output
  pinMode(5,OUTPUT);// declare pin 5 to be an output
}

void loop(){
  
  for (int a=0; a<=10;a++)     //loop from 0 to 255,it controls the increase in PWM brightness
  {
    analogWrite(4,a);           //set the brightness of pin 3:          
    delay(8);                   //wait for 8 ms        
  }
    for (int a=100; a>=0;a--)   //loop from 255 down to 0,it control PWM brightness reduction
  {
    analogWrite(3,a);           // set the brightness of pin 3:
    delay(8);                   //wait for 8 ms
  }
  delay(800);                  //wait for 800 ms

  for (int a=0; a<=50;a++)     //loop from 0 to 255,it controls the increase in PWM brightness
  {
    analogWrite(2,a);           //set the brightness of pin 3:          
    delay(8);                   //wait for 8 ms        
  }
  
  for (int a=255; a>=0;a--)   //loop from 255 down to 0,it control PWM brightness reduction
  {
    analogWrite(5,a);           // set the brightness of pin 3:
    delay(8);                   //wait for 8 ms
  }
  delay(800);  
    for (int a=50; a>=0;a--)   //loop from 255 down to 0,it control PWM brightness reduction
  {
    analogWrite(2,a);           // set the brightness of pin 3:
    delay(8);                   //wait for 8 ms
  }
  delay(800);                  //wait for 800 ms
  
    for (int a=0; a<=50;a++)     //loop from 0 to 255,it controls the increase in PWM brightness
  {
    analogWrite(4,a);           //set the brightness of pin 3:          
    delay(8);                   //wait for 8 ms        
  }
    for (int a=100; a>=0;a--)   //loop from 255 down to 0,it control PWM brightness reduction
  {
    analogWrite(3,a);           // set the brightness of pin 3:
    delay(8);                   //wait for 8 ms
  }
  delay(800);                  //wait for 800 ms
 
    for (int a=0; a<=50;a++)     //loop from 0 to 255,it controls the increase in PWM brightness
  {
    analogWrite(2,a);           //set the brightness of pin 3:          
    delay(8);                   //wait for 8 ms        
  }
    for (int a=200; a>=0;a--)   //loop from 255 down to 0,it control PWM brightness reduction
  {
    analogWrite(4,a);           // set the brightness of pin 3:
    delay(8);                   //wait for 8 ms
  }
  delay(800);                  //wait for 800 ms
  
    for (int a=0; a<=50;a++)     //loop from 0 to 255,it controls the increase in PWM brightness
  {
    analogWrite(2,a);           //set the brightness of pin 3:          
    delay(8);                   //wait for 8 ms        
  }
    for (int a=255; a>=0;a--)   //loop from 255 down to 0,it control PWM brightness reduction
  {
    analogWrite(3,a);           // set the brightness of pin 3:
    delay(8);                   //wait for 8 ms
  }
  delay(800);                  //wait for 800 ms
  for (int a=255; a>=0;a--)   //loop from 255 down to 0,it control PWM brightness reduction
  {
    analogWrite(5,a);           // set the brightness of pin 3:
    delay(8);                   //wait for 8 ms
  }
  delay(800);  
}

hello,

code is unreadable, please Edit and add the </> code tags

the way your code is written, it’s going to be hard to stop the animation in the middle (unless you use interrupts and block in the interrupt but then the watchdog might bite you)

Done. Thanks Mr. Jackson

Thanks looks much better isn’t it ? :slight_smile:

comments are a still bit off too…

for (int a=0; a<=10;a++) //loop from 0 to 255

for (int a=100; a>=0;a--) //loop from 255 down to 0,

analogWrite(4,a); //set the brightness of pin 3:

So you need to think in terms of a non blocking state machine for each PWM value and for each step of the animation. as this is very repetitive you can probably describe that in a structure

something like this might actually even work (totally untested, typed here)

const byte led2Pin = 2; // use better names
const byte led3Pin = 3; // use better names
const byte led4Pin = 4; // use better names
const byte led5Pin = 5; // use better names
const byte buttonPin = 6; // wire D6 -- button -- GND

// the animation sequence involves a pin's PWM moving from a start to an end value every ∆t
struct t_animation {
  byte      ledPin;      // 0 means no pin involved and it's just a delay of ∆t
  int       startPwm;
  int       endPwm;
  uint32_t  deltaT;
} animation[] = {
  {led4Pin,   0,  10,   8},
  {led3Pin, 100,   0,   8},
  {      0,   0,   0, 800}, // delay(800)
  {led2Pin,   0,   50,  8},
  {led5Pin, 255,   0,   8},
  {      0,   0,   0, 800}, // delay(800)
  {led2Pin,  50,   0,   8},
  {      0,   0,   0, 800}, // delay(800)
  {led4Pin,   0,  50,   8},
  {led3Pin, 100,   0,   8},
  {      0,   0,   0, 800}, // delay(800)
  {led2Pin,   0,   50,  8},
  {led4Pin, 200,   0,   8},
  {      0,   0,   0, 800}, // delay(800)
  {led2Pin,   0,   50,  8},
  {led3Pin, 255,   0,   8},
  {      0,   0,   0, 800}, // delay(800)
  {led5Pin, 255,   0,   8},
  {      0,   0,   0, 800}, // delay(800)
};

const byte stepCount = sizeof animation / sizeof animation[0];


void takeAnimationStep()
{
  unsigned long lastUpdate = 0;
  bool currentStepComplete = false;

  // default values for 1st animation
  static byte currentStep = 0;
  static int pwmValue = animation[0].startPwm;

  if (millis() - lastUpdate >= animation[currentStep].deltaT) {
    if (animation[currentStep].ledPin != 0) {
      analogWrite(animation[currentStep].ledPin, pwmValue);
      lastUpdate = millis();

      // go to next PWM value (increase or decrease)
      if (animation[currentStep].startPwm > animation[currentStep].endPwm) {  // go down
        pwmValue--;
        currentStepComplete = (pwmValue < animation[currentStep].endPwm);
      } else {  // go up
        pwmValue++;
        currentStepComplete = (pwmValue > animation[currentStep].endPwm);
      }

      if (currentStepComplete)  {
        currentStep = (currentStep + 1) % stepCount;  // go to next step or circle back to 0
        pwmValue = animation[currentStep].startPwm;   // preload initial PWM value
      }
    } else { // pin was 0, it was a delay
      currentStep = (currentStep + 1) % stepCount;    // go to next step or circle back to 0
      pwmValue = animation[currentStep].startPwm;     // preload initial PWM value
    }
  }
}

void setup ()
{
  pinMode(led2Pin, OUTPUT); // declare pin 2 to be an output
  pinMode(led3Pin, OUTPUT); // declare pin 3 to be an output
  pinMode(led4Pin, OUTPUT); // declare pin 4 to be an output
  pinMode(led5Pin, OUTPUT); // declare pin 5 to be an output
  pinMode(buttonPin, INPUT_PULLUP); 
}


void loop() {
  if (digitalRead(buttonPin) == LOW) takeAnimationStep(); // button pressed
}


the magic happens (or at least is supposed to) in the animation array where you describe the steps. for example the first entry {led4Pin, 0, 10, 8} means go from PWM 0 to 10 on led4Pin with delays of 8ms in between each change. And { 0, 0, 0, 800} is just equivalent to a delay(800) but non blocking (no pins involved)

that’s probably a base to work from - totally untested :slight_smile:

Thanks, man! I’ll test it and play around with the values. I’m expecting a brain meltdown by the end of the day though.

Here is a detailed explanation of my project.
A book where when you open a certain page some tiny leds embedded on the page will fade in and out (or just turn on and off in some order, depending on the page) and some sound will play.
My idea is to include 2 tiny Seeeduino xiao, an Arduino compatible board, one only for the LEDs and the other only for the sounds in order to save battery. Both Seeeduino xiao will run the loop when the page is turned, one will play the leds and the other will play the audio. A button on that page may run a group of led (some will be 3 leds, some 4 leds). Each of the buttons will run a specific part of the loop. The same goes for the sounds, 6 buttons to play six different audio files, depending on the page. I have run 4 leds fading in and out using two cell button batteries and lasted for over three hours nonstop, so that will power the book (well, two batteries for each board).
This is a year-long project (and a very long code), so I assume this will be a long ride.
By the way, I am willing to hire somebody to help me out, this could be too much for me, a newbie, so get in touch!

sounds like a cool project

how do you know which page is “open” ?
where are the leds? embedded in the page?
to save battery you should go for only 1 processor
also the Seeeduino xiao has very few pins, how many LEDs do you plan to drive?

You can’t “stop” loop(). It runs forever. You have almost 6-seconds of delays in your code, during which nothing else can happen, except interrupts. You either need to use an interrupt routine for a button or learn to use millis() instead of delay(). (Better yet, do both).

Once you have detected the button press, all you need then is a test at the top of the loop to determine if the button is pressed.

I will design a device (aka, button) to open and close a circuit depending if the page is turned or not. I will assign a pin number to the button to run a specific code. There will be a total of 5 of these buttons for 5 pages. I have a 3d printer to work on the design of the different pieces, very useful tool indeed. As for the leds, each page will have an inner “skeleton” (a very thin plastic layer) where the tiny leds will be placed. That will help to settle the different components (wires, leds,…) and will make everything more tidy. Overall, each page should be 2 or 3 mm thick.
Batteries, I thought to using two arduinos in order to last longer and have more pins available.

As for the pins, I am planning to have as many leds as pins on the board has, 10.

Thanks Steve. I’ll dig into it.

You don’t say which Arduino board. Two Arduinos use twice the battery. If you need more I/O, add a MCP23017 Port Extender.
I would use the Wemos D1 Mini (my go-to board). It’s only a bit over 1 sq inch and has WiFi. (You can reprogram it over WiFi).

I am currently using seeeduino xiao, which is a tiny microcontroller Arduino compatible. I like the idea of the wemos D1, wifi is less messy, and the size matches what I’m looking for. I guess I will first work on the code, which is the hardest part, especially being a newbie, and from there I can work on the best hardware solution.
The concept is to place all the electronics in the spine of the book, microcontroller, batteries, and port extender (if I finally go with only one device).
The reason to go with two arduinos is also to simplify the code. I’m just starting and I feel it could be overwhelmingly complicated to run leds and sound with one controller, but it makes sense to use only one. Still, a lot to be considered. Step by step.

Sound? That could compilate things. What sound module are you envisioning?

I want to play sound through a micro sd card module. I have already made some tests although I haven’t mixed it with leds. I know there are some tutorials.
I bought some extra 3W Mini Digital power amplifier board but I haven’t try them yet. Without the amplifier the sound is too low.
Maybe having to controllers, one for leds and one for sound, is the best solution after all. What do you think?

No. That is inviting more issues that will be difficult to analyze. (I speak from experience). Any Arduino or Wemos or NodeMCU is sufficient for your project. Adding a second processor won’t do anything about the low volume- that’s what the amplifier is for.

I am a big believer in KISS. (Keep it simple, stupid).

Alright, I’ll follow the KISS method. I’ll get some extensor port to make it feasible.
It will be a challenge but I won’t do it all alone, that’s why this community is about.
I’m going to start with a simple fade in LED program activated by a button. I want to understand the process entirely, so I can add more layers of complexity.

This is the best way to proceed. Write your code with the process that you are experimenting with in a function. This way when you are ready to add complexity you just need to add the functions you have already gotten to work.

Start also very simple
Study the examples and tutorials explaining how to not use delay() in the code (or my previous code if it works) as you’ll need to keep things as asynchronous as possible.

Okay. I have a simple motor to run while a button is pressed.
I have two questions regarding this:
1-How can I make the motor to run, let’s say, for thirty seconds? and when it stops, it will be slowing its speed, I mean fading out.
Thanks!
And here is the code for the loop, on and off while pressed the button.

const int buttonPin = 2;    
const int VibratePin =  3;    
int buttonState = 0;        

void setup() {
  pinMode(VibratePin, OUTPUT);
  pinMode(buttonPin, INPUT);

}

void loop() {
  
  buttonState = digitalRead(buttonPin);
  if (buttonState == LOW) {
    digitalWrite(VibratePin, HIGH);
    analogWrite(5, HIGH);  //increase the value of 'brightness' by 1
  }
  else {
    digitalWrite(VibratePin, LOW);
    analogWrite(5, HIGH);  
    }
}

Let’s start with “slowing its speed”. What kind of motor is it? Since you are using digital.write(), your only choice is on or off. If you want speed control, then you need to be using a PWM motor.

Do you want the motor to run for thirty seconds while the button is pressed, or after?

I’m using a tiny vibrating motor. I can connect it in an analog pin though. PWM is decreasing speed by turning on and off the pin, right? Is it better or easier to connect it in analog instead?