3

Building upon my previously solved question Ultrasonic Sensor range finder help (Solved).

Is there a better way to make the LED blink than using a delay and stopping all the rest of the code? For example, the LED is set to turn on, then shortly after turn off. Is there a better way to do this?

For example, if the LED is turned on, it then delays the code, which means it has to wait for the delay to be over, turn off, then change its pattern. For example, allow the Arduino to interrupt the blink with a new interval blink, mid blink? I'm sorry if this is confusing, it's tough to explain.

Simply put, is there a better function than delay() that can allow the Arduino to suddenly change the state of the LED while it is waiting on a delay() to finish?

The code I'm working on is this:

#include <NewPing.h>
#define TRIGGER_PIN  15
#define ECHO_PIN     2
#define MAX_DISTANCE 500
int LED1 = 3;
int LED2 = 16;
int LED3 = 9;
int LED4 = 6;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
}

void loop() {
  delay(50);
  unsigned int uS = sonar.ping_median(10);
  int IN = sonar.convert_in(uS);
  if (IN <= 5) {
    analogWrite(LED4, 255);
    delay(100);
    analogWrite(LED4, 0);
  } else if (IN >= 5 && IN <= 12) {
    analogWrite(LED4, 1);
    delay(200);
    analogWrite(LED4, 0);
  } else if (IN >= 13) {
    analogWrite(LED4, 100);
    delay(300);
    analogWrite(LED4, 0);
  }
}
2
  • Look into Timer/Counter interrupts.
    – RubberDuck
    Commented Dec 12, 2017 at 10:41
  • There is a standard Ardiono tutorial on this: Blink Without Delay. Commented Dec 12, 2017 at 11:06

3 Answers 3

2

You can use millis() to get a timer:
millis() Returns the number of milliseconds since the Arduino board began running the current program.

void loop(){
    if(millis() % 100 == 0){//%(modullo) is the rest of a division. 19%10=9 because10/10 = 1 and the rest is 9
        //you have wait 100 millisecond. When millis()%100 == 0 millis() is a multiple of 100.
    }
}

For your code you can do this:

int LED1 = 3;
int LED1 = 3;
int LED2 = 16;
int LED3 = 9;
int LED4 = 6;

//Ligth on -> 1 light off -> 0
int LED1Stat = 0;
int LED2Stat = 0;
int LED3Stat = 0;
int LED4Stat = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(LED1, OUTPUT);    //every 100 ms
  pinMode(LED2, OUTPUT);    //every 250 ms
  pinMode(LED3, OUTPUT);    //every 500 ms
  pinMode(LED4, OUTPUT);    //every 1000 ms

}

void loop() {
    //for no Delay
    if(millis()%100 = 0){
        LED1Stat = !LED1Stat;
        digitalWrite(LED1, LED1Stat);
    }
    if(millis()%250 = 0){
        LED2Stat = !LLED2Stat;
        digitalWrite(LED2, LED2Stat);
    }
    if(millis()%500 = 0){
        LED3Stat = !LED3Stat;
        digitalWrite(LED3, LED3Stat);
    }
    if(millis()%1000 = 0){
        LED4Stat = !LED4Stat;
        digitalWrite(LED4, LED4Stat);
    }
}

[EDIT]

long prevMillis = 0;
void loop(){
    if(millis()-prevMillis >= 100){
        LED1Stat = !LED1Stat;
        digitalWrite(LED1, LED1Stat);
        prevMillis = millis();
    }
    //...

}
1
  • 2
    This does not work well if 1) you can't ensure 1 millisecond between calls to loop or 2) you can't for any reason call the loop function once a millisecond or 3) the millis skips one of the milestones (remember that about every 42 milliseconds the millis jumps). Much better to track the time in the usual way (if ((millis() - prevMillis) >= PERIOD) { prevMillis += PERIOD; do_stuff() })
    – frarugi87
    Commented Dec 12, 2017 at 10:23
0

In general, if you want two separate tasks (like controlling the LED and do something else) 'simultaneously', you should not use delay.

Instead use a long int variable to keep the time since something happened (like switching the LED color in your case). Than check in the loop how much time has passed and act on it.

E.g.

When you call analog writes with non zero values, set the variable to the current time. Than instead of the delay check if the current time minus the variable < 100 or 200 or 300 depending on the value you need and than set the analog write back to 0 (switching off the LED). In the rest of the loop you can do other tasks.

0

I think the delay function will wait until enough clock cycles are done. The function counts the cycles and you must wait for enough.

The timer/counters are a part of a microcontroller and are used for example to measure the time between two events or generating interrupt after a defined time. The advantage is you can start the timer and the code after it must not wait. When the time is over you can simply generate an interrupt and execute small code in the interrupt handler.

1
  • Using millis() (effectively a software timer) is way easier than configuring a hardware timer. Commented Dec 15, 2017 at 8:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.