Avoiding the void loop()

Hi all. I am new to programming, but I find myself learning at a relatively quick pace. My question is, though, how to avoid the void loop(). I have created a simple LED chase effect using 8 LED's and 1 "status" led which is supposed to blink primarily for cosmetic purposes. However, I am using the delay() function to create the chase, which means that my blink function only repeats after each loop (else I have to program the blink as a "digitalWrite" function in every line and alternate high/low to create the blink. My current code for this simple program is here

int led1 = 13;
int led2 = 12;
int led3 = 11;
int led4 = 9;
int led5 = 8;
int led6 = 7;
int led7 = 6;
int led8 = 5;
int Status = 2;
long interval = 100;
int ledState = LOW;
long previousMillis = 0;

void setup () {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
  pinMode(led7, OUTPUT);
  pinMode(led8, OUTPUT);
  pinMode(Status, OUTPUT);
  Serial.begin(9600);
}

void loop () {
  

  digitalWrite(led1, HIGH);
  digitalWrite(Status, HIGH);
  Serial.println("Step1");
  delay(50);
  digitalWrite(led2, HIGH);
  digitalWrite(Status, LOW);
  Serial.println("Step2");
  delay(50);
  digitalWrite(led3, HIGH);
  digitalWrite(Status, HIGH);
  Serial.println("Step3");
  delay(50);
  digitalWrite(led4, HIGH);
  digitalWrite(Status, LOW);
  Serial.println("Step4");
  delay(50);
  digitalWrite(led5, HIGH);
  digitalWrite(Status, HIGH);
  Serial.println("Step5");
  delay(50);
  digitalWrite(led6, HIGH);
  digitalWrite(Status, LOW);
  Serial.println("Step6");
  delay(50);
  digitalWrite(led7, HIGH);
  digitalWrite(Status, HIGH);
  Serial.println("Step7");
  delay(50);
  digitalWrite(led8, HIGH);
  digitalWrite(Status, LOW);
  Serial.println("Step8");
  delay(50);
  digitalWrite(led1, LOW);
  digitalWrite(Status, HIGH);
  Serial.println("Reset Clear");
  delay(50);
  digitalWrite(led2, LOW);
  digitalWrite(Status, LOW);
  delay(50);
  digitalWrite(led3, LOW);
  digitalWrite(Status, HIGH);
  delay(50);
  digitalWrite(led4, LOW);
  digitalWrite(Status, LOW);
  delay(50);
  digitalWrite(led5, LOW);
  digitalWrite(Status, HIGH);
  delay(50);
  digitalWrite(led6, LOW);
  digitalWrite(Status, LOW);
  delay(50);
  digitalWrite(led7, LOW);
  digitalWrite(Status, HIGH);
  delay(50);
  digitalWrite(led8, LOW);
  digitalWrite(Status, LOW);
  delay(50);
  
}

I would like to create the LED blink independent of the delay functions and more similar to this code:

void loop()
{

  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(green, ledState);  
  }

Is there a way to do this? I know your program can not contain more than one "void loop()" call, so what would a good solution be?
Thanks,
MonorailOrange

MonorailOrange:
I would like to create the LED blink independent of the delay functions and more similar to this code:

Here's just the thing you need: Arduino Playground - HomePage

It's a library that sets up an ISR (interrupt service routine). What you do is initialize it with the time you want (say, for 10 hz you use 1E6/10), then put your code inside the ISR loop.

Every 1/10 second (or whatever you choose) the ISR loop runs, INDEPENDENT of any other part of your code!

Imagine you wanted to run through a bunch of loops 100 times per second - accurately.

You could do this:

void loop(void)
{
run_sub_1();
run_sub_2();
run_sub_3();
delay(1000-constant);
}

...where the constant was an experimentally determined value to "use up" the rest of the time slice. Very tedious and if you change any code, you have to re-calibrate the constant.

OR, do this:

void ISR_Loop()
{
run_sub_1();
run_sub_2();
run_sub_3();
}

Now, the time that it takes to go through the loop is irrelevant... the loop will run at exactly the rate you set it for.

Obviously, the only thing to watch out for is that the execution time of all the subroutines inside the ISR loop cannot be LONGER than the time slice interval, else the stack will fill up with pending, unserviced interrupts and crash the system in milliseconds!

That library also comes with a demo to show how to set it up. It's so easy..... a caveman can do it! :slight_smile:

Thank you very much! I seriously appreciate it!

You can blink an LED completely separate from whatever your chase effect is doing. Use a timer based on millis().

PSEUDO CODE
int timer = 1000;
long prevMillis;

void loop() {
  if (mills() - prevMillis > timer) {
    // do something with the indicator LED
  }
  // run your chase effect code here, WITHOUT USING DELAY!
}

When I say do it without using delay, I mean it. Look up the BlinkWithoutDelay example in the Playground. But essentially you're doing the same thing as the indicator LED, base the delays off of elapsed millis().

I have code written for an indicator LED that would blink a certain amount of times, indicating whatever effects is being displayed. It was an LED display that I could not see (because I was sitting behind it), so I needed an indicator light to tell me which effect was running. I had 11 different effects, so the indicator LED would blink from one to 11 times with a 1 second pause in between. In between blinks the pause was 250, between repeats it's 1 second. So blink-250-blink-250-blink-1000-blink-250-blink-250-blink-1000, etc., etc. All I had to do was count the amount of blinks and I'd know what effect was being displayed.

Possible interim solution using 'named constants', 'arrays' and 'subroutines'

#define ARRAY_ELEMENT_COUNT(ARRAY)      (sizeof(ARRAY) / sizeof(ARRAY[0]))


const uint8_t   pinSTATUS       =  2;
const uint8_t   pinLED_1        = 13;
const uint8_t   pinLED_2        = 12;
const uint8_t   pinLED_3        = 11;
const uint8_t   pinLED_4        =  9;
const uint8_t   pinLED_5        =  8;
const uint8_t   pinLED_6        =  7;
const uint8_t   pinLED_7        =  6;
const uint8_t   pinLED_8        =  5;

const uint8_t   pinsLEDS[]      =
{
    pinLED_1, pinLED_2, pinLED_3, pinLED_4, pinLED_5, pinLED_6, pinLED_7, pinLED_8
};

const uint8_t   LED_OFF         = LOW;
const uint8_t   LED_ON          = HIGH;


uint8_t         stateStatusLED = LED_OFF;


void chase(uint8_t state )
{
    for ( int i = 0; i < ARRAY_ELEMENT_COUNT(pinsLEDS); i++ )
    {
        if ( LED_OFF == stateStatusLED )
            stateStatusLED = LED_ON;
        else
            stateStatusLED = LED_OFF;

        digitalWrite(pinSTATUS, stateStatusLED);

        digitalWrite(pinsLEDS[i], state);
        delay(50);
    }
}


void loop()
{
    chase(LED_ON);
    chase(LED_OFF);
}


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

    pinMode(pinSTATUS, OUTPUT);

    for ( int i = ARRAY_ELEMENT_COUNT(pinsLEDS); i--; )
    {
        pinMode(pinsLEDS[i], OUTPUT);
    }
}

MonorailOrange:
I am using the delay() function to create the chase, which means that my blink function only repeats after each loop (else I have to program the blink as a "digitalWrite" function in every line and alternate high/low to create the blink.

There are various ways to fix the problem, but by far the best is to adopt the technique used in the 'blink without delay' example sketch to control the chase lights and the blinking. You can extend the technique to control as many other things as you want, and this approach is far, far better than making your sketch stop and wait for specific things to happen using delay(). It's also far more generally useful than using interrupts.

Krupski:
Imagine you wanted to run through a bunch of loops 100 times per second - accurately.

You could do this:

void loop(void)
{
run_sub_1();
run_sub_2();
run_sub_3();
delay(1000-constant);
}

You could do, but it would be a daft solution. The 'blink without delay' example sketch shows you exactly how to do things at regular intervals, there is no need to invent complicated interrupt-based scheduling solutions or use hacky fixed delay scheduling.

What I would do, is have loop() running as fast as it can repeat, without any delays in it.

For each light, I would keep a table of the next time each light should change state.

In each iteration of the loop, for each light, I would compare the current time to the next
time that light is due to change. If a light is due to change, then change it, and update
the next change time.

Maybe you want to have a look at my blog. I blink in all variations :wink: