Blink Without Delay Help

Hi, I'm Ash from Malaysia. Anyway about my question could i count the amount of time that a led have turn on with blink without delay? in my set up i want to make an led to turn on for 5 second and off for 5 second, the led will blink for maybe 50 time counting only when it is on. but for every 10 time it has blink, the amount it turn off reduce by one. like count | time on | time off 0-10 5 5 11-20 5 4 21-30 5 3 31-40 5 2 41-50 5 1

should i use if and if...else or is there any other way?

ash901226:
Hi,
I’m Ash from Malaysia.
Anyway about my question could i count the amount of time that a led have turn on with blink without delay?
in my set up i want to make an led to turn on for 5 second and off for 5 second, the led will blink for maybe 50 time counting only when it is on. but for every 10 time it has blink, the amount it turn off reduce by one.
like
count | time on | time off
0-10 5 5
11-20 5 4
21-30 5 3
31-40 5 2
41-50 5 1

should i use if and if…else or is there any other way?

Yes. You can use a if/else if or a switch statement to determine the off time.

i got this code

const int Led=13;
long TimeOn = 5;
long TimeOff1= 5;
long TimeOff2= 4;
long TimeOff3= 3;
long TimeOff4= 2;
long TimeOff5= 1;
long previousMillis = 0;
unsigned long currentMillis;
int state=1;

void setup()
{
  pinMode(Led,OUTPUT);
}
void loop()
{
  for (int i = 0; i<50;i++)
 {
  switch (state){
  case 1:
    digitalWrite(Led,HIGH);
    currentMillis = millis();
    state=2;
    break;
  case 2:
    if(currentMillis - previousMillis > TimeOn)
    {
     state=3;
     previousMillis = currentMillis;
    }
    break;
  case 3:
    digitalWrite(Led,LOW);
    currentMillis = millis();
    state=4;
    break;
  case 4:
    if (i>=0 &&i<=10)
    {
     if(currentMillis - previousMillis > TimeOff1)
    {
     state=1;
    }
    }
     if (i>=11 &&i<=20)
    {
     if(currentMillis - previousMillis > TimeOff2)
    {
     state=1;
    }
    }
     if (i>=21 &&i<=30)
    {
     if(currentMillis - previousMillis > TimeOff3)
    {
     state=1;
    }
    }
    if (i>=31 &&i<=40)
    {
     if(currentMillis - previousMillis > TimeOff4)
    {
     state=1;
    }
    }
     if (i>=41 &&i<=50)
    {
     if(currentMillis - previousMillis > TimeOff5)
    {
     state=1;
    }
    }
    previousMillis = currentMillis;
    break;
    default:
    state=1;
    break;
  }
 }
digitalWrite(Led,LOW);
}

it compile but cant do anything at all

There are a few problems here.

  for (int i = 0; i<50;i++)
  {

The variable “i” is going to rapidly go from 0 to 49, probably before any of your times elapse.


    switch (state){
    case 1:
      digitalWrite(Led,HIGH);
      currentMillis = millis();
      state=2;
      break;
    case 2:
      if(currentMillis - previousMillis > TimeOn)
      {
        state=3;
        previousMillis = currentMillis;
      }
      break;

In case 2 you care checking currentMillis but that won’t change because you are not updating it.

i thought for loop is use for counting. am i wrong to assume this?

A for loop is usually used for doing something a fixed number of times and its counter variable is often used within the loop to do something based on its value. Unless there is something inside the loop to slow it down then it will run very fast as Nick says.

i thought for loop is use for counting. am i wrong to assume this?

Yes, and no. Yes, a for loop counts the number of times it has iterated. Counting things that happen in the body, like time passage, no.

Some people use a while or for-next loop or series of NOP's to delay less than 4 micros. Every instruction has a certain number of cycles, at 16 million cycles per second, to perform.

OP, something else you should know is arrays of variables. You don't need 5 different-name time-off's with a code section for each but a 5-element array of time-off's to choose which to use by index.

Also, time variables should be unsigned long unless you have a huge number of those. Reason is that Arduino time is given in milliseconds since start as an unsigned long and using variables of the same type saves type conversion. If memory space is an issue then yes, let it convert but otherwise it is cleaner and quicker not to.

For type unsigned long add UL to the end of the constant number to tell the compiler "unsigned long". 1 second is 1000UL milliseconds, 5 seconds == 5000UL.

Unsigned math is especially useful for time, even across the rollover differences will be correct.

ash901226: i thought for loop is use for counting. am i wrong to assume this?

You can use it for counting. But try to work out what is happening here:

switch (state){
    case 1:
      digitalWrite(Led,HIGH);
      currentMillis = millis();
      state=2;
      break;
    case 2:
      if(currentMillis - previousMillis > TimeOn)

The state will quickly transition from 1 to 2. Then, staying on 2 for a long time, "i" will increase from 0 to 49.

And as I said before, your test for currentMillis is flawed, because in this part of the switch statement you are not updating currentMillis.

OP, have you loaded and run the Blink Without Delay that comes with your IDE?

And you only want to control how long on and off times are?

This is how I would have done it:

const int Led=13;

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

void loop()
{
  static unsigned long startTime;
  static int count = 0;
  static int state = 0;

  switch (state){
  case 0: // Turn ON
    digitalWrite(Led,HIGH);
    startTime = millis();
    state = 1;  // Stay ON till OFF time
    break;

  case 1: // Wait until OFF time
    if(millis() - startTime > 5000)  // After 5 seconds
    {
      digitalWrite(Led,LOW);
      count++;
      state=2;  // Stay OFF till ON time
      startTime = millis();
    }
    break;

  case 2: // Wait until next ON time
    if(millis() - startTime > (5000 - (count/10)*1000))  // After 5/4/3/2/1 seconds
    {
      state=0;  // Turn ON
      if (count >= 50)
        state = 3;  // After 50 cycles, stop
    }
    break;

  case 3:  // Stopped
    break;
  }
}

My first thought (without much time given to it) as to a possible solution compiles but is otherwise untested.

const uint8_t           pinLED          = 13;

const unsigned long     dtONE_SECOND    = 1000UL;
const unsigned long     dtFIVE_SECONDS  = 5000UL;


unsigned long           dtEvent         = millis();
unsigned long           dtOff           = dtFIVE_SECONDS;
int                     count           = 0;


// See: <http://arduino.cc/playground/Code/TimingRollover>

bool isEventTime(unsigned long const tmsRef, unsigned long const tmsEvent)
{
    return ((long)(tmsRef - tmsEvent) >= 0);
}

void loop()
{
    if ( isEventTime(millis(), dtEvent) )
    {   
        switch ( count )
        {
            case 10:
            case 20:
            case 30:
            case 40:
            case 50:
                dtOff -= dtONE_SECOND;
                break;
    
            case 51:
                count   = 0;
                dtOff   = dtFIVE_SECONDS;
                dtEvent = millis();

                return;
        }

        dtEvent += (digitalRead(pinLED) ? dtOff : dtFIVE_SECONDS);

        digitalWrite(pinLED, ! digitalRead(pinLED));
    
        count++;
    }
}

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

That article is confused. Once you work in unsigned's, you forget about negative.

This time check works no matter what start, end and wait times you feed it, but you need all three.

unsigned long start, end, wait;

start = 0xFFFFFFF0; end = 0x100; wait = 0x100;

if ( end - start >= wait ) { println( "end - start >= wait" ); } else { Serial.println( "wait is not over yet" ); }

Put all that in setup(), nothing in loop(), change start and end and wait all you want, there is no need to flag on millis() rollover nor any correction to make upon such flag.

GoForSmoke: That article is confused. Once you work in unsigned's, you forget about negative. ...

Which article?

hello guys, actually could someone explain to me what does this line mean in lloyddean code

dtEvent += (digitalRead(pinLED) ? dtOff : dtFIVE_SECONDS);

ash901226:
hello guys, actually could someone explain to me what does this line mean in lloyddean code

dtEvent += (digitalRead(pinLED) ? dtOff : dtFIVE_SECONDS);

+= is shorthand for take this variable and add something to it.

The right side of the equation is the ternary operator that is shorthand for if this is true, set the value to this, otherwise that.

The entire thing is functionally equivalent to this:

If (digitalRead(pinLED)
   dtEvent = dtEvent + dtOff 
else
   dtEvent = dtEvent + dtFIVE_SECONDS

It's shorthand for

if (digitalRead (pinLED) == HIGH)
{
  dtEvent = dtEvent + dtFIVE_SECONDS;
}
else
{
  dtEvent = dtEvent + dtOff;
}

ash901226:
i got this code

...

void loop()
{
  for (int i = 0; i<50;i++)
{
  switch (state){
  case 1:
    digitalWrite(Led,HIGH);
    currentMillis = millis();
    state=2;



it compile but cant do anything at all

Hi Ash,

You don’t need a for loop because the whole loop() function gets called over and over already by the Arduino framework. You only need to keep track of when things need to happen, and if it’s time for something to happen. See if you can understand this version. Good luck!

const int LED=11;
void setup(){
    pinMode(LED, OUTPUT);
}

long nextTime=0;
bool nextState=HIGH;
long count;

void loop(){
    long currentTime=millis();
    if (currentTime < nextTime) return;  // if not time for something to happen, just return

    // it's now time to make nextState happen
    if (nextState==HIGH){
        // turn it on and schedule OFF in 5 seconds
        digitalWrite(LED, HIGH);
        nextState=LOW;
        nextTime = currentTime + 5000;
    }
    else {
        // turn it off and schedule ON in the right number of seconds according to "count"
        digitalWrite(LED, LOW);
        nextState=HIGH;
        if (count < 11){ nextTime=currentTime + 5000; }
        else if (count < 21){ nextTime=currentTime + 4000; }
        else if (count < 31){ nextTime=currentTime + 3000; }
        else if (count < 41){ nextTime=currentTime + 2000; }
        else if (count < 51){ nextTime=currentTime + 1000; }
        else {
            // what should happen after it has blinked 50 times?
        }
        count = count + 1;    // or just "count++'"
    }
}