Blink Without Delay pain in the a$$

I am willing to control 2 Led's in a project.

I want to make an Led blink for 1 second, and then turns off for another second.
The blink without delay sketch has already explained this one and there is no problem.

But I want the second led to blink for 100ms and turn off for another 100ms 3 times, BUT only upon pressing a button.

I have tried SO many times but kept failing :frowning:
Any ideas?

1 Like

Show us your attempt so we can see where you are going wrong.

1 Like

Post the code that fails.

"The code fails" conveys little useful information. Can you provide details?

Do you mean a button press starts it? How do you stop it?

Or do you mean while a button is pressed? If you impress the button, does the LED go off immediately even if it has been on only a fraction of the time it would stay on to blink?

a7

My real project is actually making an rc car with a turret that is controlled with a motor

But I only need to understand how to make that delay to actually make the turret shoot while the car is moving

int ledState = LOW;
int extraDelay = 0;
char flag;
unsigned long previousMillis = 0;
const long interval = 1000;

void setup(){
	Serial.begin(9600);
}

void loop(){
	

	unsigned long currentMillis = millis();
	unsigned long shootMillis = millis();
	flag = Serial.read();




	if (currentMillis - previousMillis >= interval){
    previousMillis = currentMillis;

    if (ledState == LOW) {
      ledState = HIGH;
      Serial.println("LED_1 ON");
    }
    else {
      ledState = LOW;
      Serial.println("LED_1 OFF");
    }
	}


	if (flag == 'A'){
		for (shootMillis; shootMillis>=interval; shootMillis - interval){
			extraDelay = shootMillis;
		}

	}

}

That is as far as I could write before my brain stopped mathing after the for function
I don't even know if the for function actually does what I think it do.

Now we know that the blink without delay runs every 1 second.
But I may not always press the button at the exact second the script runs.

So lets say I clicked the button after 2600 milliseconds from the arduino start time.
And that's where my brain stopped working.

There is 400 millisecond that I have no idea what to do with.
Should I add it to the next Blink Without Delay script?
Or should I subtract it?

@groundFungus @LarryD

Once the button is pressed I want it to

digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);


digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);


digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);

After blinking 3 times it should automatically stop
The blinking should not start again if I pressed the button again while its blinking.
It should finish blinking 3 times then be ready to blink again when the button is pressed.

Do you want the second LED sequence to start on a serial receive character or a switch press ?

I wrote it like its upon a serial receive in the code above because I don't have the hardware now.

You have two LEDs.

One LED is to toggle every 500ms.

The 2nd LED is to flash 3 times when a physical switch is closed; while flashing this switch is locked out.

Correct ?

Exactly.
The first every 500ms for infinity. (Or 1000ms not so different)
The second every 100ms but only 3 times

const byte ledOnePin = 2;
const byte ledTwoPin = 3;
const byte buttonPin = 4;

void setup() {
  pinMode(ledOnePin, OUTPUT);
  pinMode(ledTwoPin, OUTPUT);
}

void loop() {
  static byte flashCount = 0;
  //BUTTON PRESS STARTS 3 FLASHES @ 100MS
  static bool debounced = false;
  if (buttonPin == HIGH && debounced) {
    flashCount = 6; // 6 equals 3 flashes on and off
    debounced = false;
  }
  else {
    debounced = true;
  }
  // LED ONE, 1 SECOND ON 1 SECOND OFF
  static bool ledOneState = LOW;
  static unsigned long ledOneMillis = 0;
  if (millis() - ledOneMillis >= 1000UL) {
    digitalWrite(ledOnePin, ledOneState);
    Serial.print("LED 1 "); Serial.println(ledOneState ? "ON" : "OFF");
    ledOneState = !ledOneState;
    ledOneMillis = millis();
  }
  // LED TWO, 100Ms ON 1 SECOND OFF
  static bool ledTwoState = HIGH;
  static unsigned long ledTwoMillis = 0;
  if (millis() - ledTwoMillis >= 100UL && flashCount > 0) {
    digitalWrite(ledTwoPin, ledTwoState);
    Serial.print("LED 2 "); Serial.println(ledTwoState ? "ON" : "OFF");
    ledTwoState = !ledTwoState;
    flashCount--;
    ledTwoMillis = millis();
  }
}
1 Like

consider


const byte LedPins [] = { 13, 12 };
#define  Nled   sizeof(LedPins)

enum { Off = HIGH, On = LOW };

unsigned long msecLst [Nled];
unsigned long Period  [Nled] = { 1000, 100 };
bool fire;

// -----------------------------------------------------------------------------
void loop()
{
    unsigned long msec = millis ();

    // -------------------------------------
    // 1st led
    if ( (msec - msecLst [0]) > Period [0])  {
        msecLst [0] = msec;

        digitalWrite (LedPins [0], ! digitalRead (LedPins [0]));
    }

    // -------------------------------------
    // 2nd led
    if (fire && (msec - msecLst [1]) > Period [1])  {
        msecLst [1] = msec;

        digitalWrite (LedPins [1], ! digitalRead (LedPins [1]));
    }

    // -------------------------------------
    if (Serial.available ())  {
        switch (Serial.read ())  {
        case 'A':
            fire = true;
            break;

        case 's':
            fire = false;
            digitalWrite (LedPins [1], Off);
            break;
        }
    }
}

// -----------------------------------------------------------------------------
void setup()
{
	Serial.begin(9600);

    for (unsigned n = 0; n < Nled; n++)  {
        digitalWrite (LedPins [n], Off);
        pinMode      (LedPins [n], OUTPUT);
    }
}
1 Like

One way to do it.

#define LEDoff                     LOW
#define LEDon                      HIGH

const byte LED1                  = 2;
const byte LED2                  = 3;
const byte mySwitch              = 4;

bool blinkFlag                   = false;

byte lastMySwitchState;
byte count;

unsigned long previousMillis;
unsigned long switchMillis;
unsigned long blinkMillis;

const unsigned long interval     = 500ul;
const unsigned long LED2interval = 100ul;

//********************************************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);

  pinMode(mySwitch, INPUT_PULLUP);

} //END of   setup()


//********************************************************************************
void loop()
{
  //***************************************
  //time to toggle the heartbeat LED ?
  if (millis() - previousMillis >= interval)
  {
    //restart the TIMER
    previousMillis = millis();

    //toggle LED
    digitalWrite(LED1, !digitalRead(LED1));

  }

  //***************************************
  //time to check the switches ?
  if (millis() - switchMillis >= 100)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();

  }

  //***************************************
  //when enabled, has the LED2 blink TIMER expired ?
  if (blinkFlag == true && millis() - blinkMillis >= LED2interval)
  {
    //restart this TIMER
    blinkMillis = millis();

    //toggle the LED2
    digitalWrite(LED2, !digitalRead(LED2));

    //are we finished with the flashing sequence ?
    if (count > 3)
    {
      //disable this TIMER
      blinkFlag = false;
      digitalWrite(LED2, LEDoff);
    }

    count++;
  }

  //***************************************
  //other none blocking code goes here
  //***************************************

} //END of   loop()


//********************************************************************************
void  checkSwitches()
{
  byte currentState;

  //***********************************************
  //mySwitch
  currentState = digitalRead(mySwitch);

  if (lastMySwitchState != currentState)
  {
    lastMySwitchState = currentState;

    //when we are not flashing LED2, is the switch pressed
    if (blinkFlag == false && currentState == LOW)
    {
      //reset the blink counter
      count = 0;

      //enable the LED2 TIMER
      blinkFlag = true;

      //restart the TIMER
      blinkMillis = millis();

      //LED2 on
      digitalWrite(LED2, LEDon);
    }

  } //END of  mySwitch

} //END of checkSwitches()


1 Like

non-blocking timing has a different concept than blocking timing.
blocking timing follows a linear sequence
like you have written above

digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);


digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);

this could be called linear execution with real pausing (the delay()s )

non-blocking timing could be called circular-repeated execution with time-comparing

run down the commands inside a loop very very often = the circular-repeating
on each run check how much time has passed by.

if 100 milliseconds of time have passed by do an action
then set new start-point of time and do the same again

This tutorial explains it in small steps with an all day situation of baking pizza
until pizza is ready to eat.

best regards Stefan

1 Like

Thanks a lot @LarryD @gcjr @KawasakiZx10r for helping me with this.
I connected the hardware using a breadboard and the code @LarryD made work.
I couldn't check the other codes but I am sure that they will be more than helpful.
There is a lot of things I have to learn, thanks for helping <3

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.