My Aim:
When no switch is pressed, I want my LED to keep turning on and off 6 times, stop for a couple of seconds, and repeat. If the switch is pressed, I want the LED to stop turning on. Once the switch is released, I want it to turn on and off as before. My Problem:
My problem is that the system only reviews the switch's state once the 'for loop' has finished, i.e. the LED has completed turning on/ off 6 times. What do I have to do if I want the sequence (aka stream) to stop exactly when I press the switch, when when it is still in the for loop? The code I wrote so far:
int LED_RED_GPIO=15; //led pin
int SW1_GPIO=22; //switch pin
void setup()
{
Serial.begin(9600); //Sets the data rate in bits per second (baud) for serial data transmission
pinMode(LED_RED_GPIO, OUTPUT); //Configures pin 15 to behave as an output
pinMode(SW1_GPIO, INPUT); //Configures pin 22 to behave as an output
}
//The stream occurs unless switch is pressed
void loop()
{
int switchstate = digitalRead(SW1_GPIO); //local variable, holding state of switch
if (switchstate==HIGH)
{
digitalWrite(LED_RED_GPIO, LOW);
Serial.println("switch pressed, stream inactive");
}
else{sw
Serial.println("switch not pressed, stream active");
for (int i = 0; i <=5; i++) //repeats loop 6 times
{
Serial.println(i);
digitalWrite(LED_RED_GPIO, HIGH); //LED is on for 1 second
delay(1000);
digitalWrite(LED_RED_GPIO, LOW); //LED is off for 1 second
delay(1000);
}
delay(2000);
}
}
That is, indeed, the problem, so what is the solution ?
Part of the solution is not to use a for loop in the first place because the well named loop() function will do the looping for you. However, if you use delay()s for the timing that will not help
You need to implement non blocking using millis() for the timing.
I tried putting an 'if' statement in the for loop that said: if the switch is pressed then break out of the 'for' loop. but I assume that is not what you mean?
To do "exactly" you need to convert your for+delay loop into a non-blocking https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay form. This would be best. The core part of the Blink without delay for the 6 flashes would need to count the flashes and change the interval depending on the number of flashes:
int flash = 0;
...
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
flash++;
interval = 1000;
} else {
ledState = LOW;
if (flash == 6) {
flash = 0;
interval = 2000;
} else {
interval = 1000;
}
}
...then add some code into loop() to reset things when your inhibiting switch is pressed.
if (digitalRead(SW1_GPIO) == HIGH){ // reset led state
ledState = LOW;
flash = 0;
interval = 1000;
previousMillis=millis()-interval;
}
If "exactly" means you can wait until your loop iterates again, you can put it in the for loop's iteration condition like Paul said:
for (int i = 0; (i <=5 && digitalRead(SW1_GPIO) ==LOW) ; i++)
If you want to do something hacky in the middle you can add a conditional break at points in your for loop:
Hello banana2000
Try this sketch. I´ve used event driven timers each for flashing and for interupting. You have to change the pin address and make some fine tuning to your project. Emergency flash lights?
/* BLOCK COMMENT
When no switch is pressed, I want my LED to keep turning on and off 6 times, stop for a couple of seconds,
and repeat. If the switch is pressed, I want the LED to stop turning on. Once the switch is released,
I want it to turn on and off as before.
https://forum.arduino.cc/t/how-to-get-out-of-a-for-loop-once-a-switch-is-pressed/953756
*/
#define ProjectName "How to get out of a for loop once a switch is pressed?"
// HARDWARE AND TIMER SETTINGS
// YOU MAY NEED TO CHANGE THESE CONSTANTS TO YOUR HARDWARE AND NEEDS
constexpr byte ButtonPin {A0}; // portPin o---|button|---GND
constexpr byte LedPin {9}; // portPin o---|220|---|LED|---GND
#define OutPutTest
constexpr unsigned long OutPutTestTime {1000};
// VARIABLE DECLARATION AND DEFINITION
unsigned long currentTime;
struct TIMER { // has the following members
unsigned long duration; // memory for interval time
unsigned long stamp; // memory for actual time
bool control_; // control for start/stop
};
TIMER flash {50, 0, true};
TIMER startStopp {1000, 0, true};
// -------------------------------------------------------------------
void setup() {
Serial.begin(9600);
Serial.println(F("."));
Serial.print(F("File : ")), Serial.println(__FILE__);
Serial.print(F("Date : ")), Serial.println(__DATE__);
Serial.print(F("Project: ")), Serial.println(ProjectName);
pinMode (LED_BUILTIN, OUTPUT); // used as heartbeat indicator
pinMode(ButtonPin, INPUT_PULLUP);
pinMode(LedPin, OUTPUT);
#ifdef OutPutTest
// check outputs
digitalWrite(LedPin, HIGH), delay(OutPutTestTime);
digitalWrite(LedPin, LOW), delay(OutPutTestTime);
#endif
}
void loop () {
currentTime = millis();
static int blinkCount = 6 * 2;
digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
if (currentTime - flash.stamp >= flash.duration && blinkCount ) {
flash.stamp = currentTime;
blinkCount--;
if (digitalRead(ButtonPin)) digitalWrite(LedPin, !digitalRead(LedPin));
}
if (currentTime - startStopp.stamp >= startStopp.duration && !blinkCount ) {
startStopp.stamp = currentTime;
blinkCount = 6 * 2;
}
}