Running a section over code continuously

I have spent enough time searching for an answer, without finding a solution, that I finally just need to ask directly. Thanks for the support, and I apologize if this is covered elsewhere.

As part of a much larger robot project, I have three or four pieces of code that I would like to have run continuously and non-stop “in the background”. Essentially, they are various patterns of LED’s being flashed to look like a “busy computer”.

Regardless of the servos that are working, or the range sensor or other robot functions, I want the LED’s to simply flash their patterns over and over again, as long as it is powered up.

To start, I have been trying to simply join two pieces together, to learn the technique, and then I’ll add the other pieces. The first is simply the Knight Rider example from the examples running an 8 LED cluster. The second is lighting a block of 4 LED’s in a random on/random off pattern, to give a very mixed up look.

Both pieces work individually, but I can’t seem to figure out how to marry them in a way that they don’t run sequentially. I don’t want the random lights to affect the Knight Rider, or vice versa.

I thought the thread on using “Blink Without Delay”, would help, but I’ve spent about 6 hours on that path, and can’t seem to figure it out.

I could do it with multiple Arduinos of course, each controlling it’s own set of lights, but that doesn’t seem like the correct solution.

Any help is much appreciated.

Here is the section of Random Flashing code…

int Random1;
int Random2;
int Random3;
int Random4;
int MyPins = {A0, A1, A2, A3, A4, A5};

void setup() {
}

void loop() {
Random1=random(0,5);
analogWrite(MyPins[Random1], 255);
delay(random(250));
analogWrite(MyPins[Random1], 0);
delay(random(250));

Random2=random(0,5);
analogWrite(MyPins[Random2], 255);
delay(random(250));
analogWrite(MyPins[Random2], 0);
delay(random(250));

Random3=random(0,5);
analogWrite(MyPins[Random3], 255);
delay(random(500));
analogWrite(MyPins[Random3], 0);
delay(random(500));

Random4=random(0,5);
analogWrite(MyPins[Random4], 255);
delay(random(250));
analogWrite(MyPins[Random4], 0);
delay(random(250));
}

And the Knight Rider code…

int LeftPinArray = {36, 34, 32, 30, 28, 26, 24, 22, 20};
int Lcount = 0;
int timer = 30;

void setup(){
for (Lcount=0;Lcount<8;Lcount++) {
pinMode(LeftPinArray[Lcount], OUTPUT);
}
}

void loop() {
for (Lcount=0;Lcount<7;Lcount++) {
digitalWrite(LeftPinArray[Lcount], HIGH);
delay(timer);
digitalWrite(LeftPinArray[Lcount + 1], HIGH);
delay(timer);
digitalWrite(LeftPinArray[Lcount], LOW);
delay(timer2);
}
for (Lcount=7;Lcount>0;Lcount–) {
digitalWrite(LeftPinArray[Lcount], HIGH);
delay(timer);
digitalWrite(LeftPinArray[Lcount - 1], HIGH);
delay(timer);
digitalWrite(LeftPinArray[Lcount], LOW);
delay(timer
2);
}

}

Can it be done?

Thanks!

You need to get rid of the delay() function everywhere and use millis() to manage the timing.

As its name implies the demo several things at a time illustrates how to multi-task.

You will also find it easier to manage the problem if you break up your code into short functions.

...R

Thanks Robin2.

I've been looking at that example most of the morning... I can't seem to get my head around it.

I think maybe I just need to stop for the time being, and clear my head and try again in a couple days.

Looking through the code again that Robin2 recommended, (SeveralThingsAtTheSameTimeRev1.ino) is it possible to use random() as the BLINK DURATION, or ON / OFF instead of a constant?

As written, if I watch any individual LED, I can see the pattern, but replacing the constants with random(100,1000) obviously only works the first time the sketch is started, not every time the function is called.

Or am I still missing something significant, that I just don't see?

Jwvanno:
As written, if I watch any individual LED, I can see the pattern, but replacing the constants with random(100,1000) obviously only works the first time the sketch is started, not every time the function is called.

If you post your code I will try to help. I suspect you are using the random stuff in the wrong location.

I can't seem to get my head around it

The idea behind the use of milis() is very simple - just the same as if you were cooking a chicken in the oven. You note the time when you put the chicken in the oven and then while you are doing other things you periodically check the clock to see if 2hrs (or whatever) have elapsed and it is time to take the chicken out. You do NOT sit in front of the cooker for 2hrs doing nothing else - which is what delay() does.

...R

Thanks Robin2.

My code is 99% copied from the example given above, with the appropriate sections copied again, to use 4 LED's.

The overall pattern of the 4 LED's appears random when running, but as I mention, if I only look at a single LED, the repetition of the pattern is obvious. I would love to have random on period and random off period for each LED.

You'll see I have tried to use the random() in the declarations and also in LOOP(), to vary the blink duration as a start, but to no effect.

Thank you for the offer of help!

//========================================
// SeveralThingsAtTheSameTime.ino
//========================================

// ----------LIBRARIES--------------

// --------CONSTANTS (won't change)---------------

const int LED_A_Pin = A0; // the pin numbers for the LEDs
const int LED_B_Pin = A1;
const int LED_C_Pin = A2;
const int LED_D_Pin = A3;

// number of millisecs between blinks
const int LED_A_Interval = 2500;
const int LED_B_Interval = 4700;
const int LED_C_Interval = 600;
const int LED_D_Interval = 1000;

const int blinkDuration = random(1000); // number of millisecs that LED's are on - all LEDs use this

//------------ VARIABLES (will change)---------------------

byte LED_A_State = LOW; // used to record whether the LEDs are on or off
byte LED_B_State = LOW; // LOW = off
byte LED_C_State = LOW;
byte LED_D_State = LOW;

unsigned long currentMillis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previousLED_A_Millis = 0; // will store last time the LED was updated
unsigned long previousLED_B_Millis = 0;
unsigned long previousLED_C_Millis = 0;
unsigned long previousLED_D_Millis = 0;

unsigned long previousServoMillis = 0; // the time when the servo was last moved

//========================================

void setup() {

// set the LED pins as output:

pinMode(LED_A_Pin, OUTPUT);
pinMode(LED_B_Pin, OUTPUT);
pinMode(LED_C_Pin, OUTPUT);
pinMode(LED_D_Pin, OUTPUT);

}

//========================================

void loop() {

currentMillis = millis(); // capture the latest value of millis()
// this is equivalent to noting the time from a clock
// use the same time for all LED flashes to keep them synchronized

int blinkDuration = random(1000); // number of millisecs that LED's are on - all LEDs use this

// readButton(); // call the functions that do the work

updateLED_A_State();
updateLED_B_State();
updateLED_C_State();
updateLED_D_State();
switchLEDs();
// servoSweep();

}

void updateLED_A_State() {

if (LED_A_State == LOW) {
if (currentMillis - previousLED_A_Millis >= LED_A_Interval) {
LED_A_State = HIGH;
previousLED_A_Millis += LED_A_Interval;
}
}
else {
if (currentMillis - previousLED_A_Millis >= blinkDuration) {
LED_A_State = LOW;
previousLED_A_Millis += blinkDuration;
}
}
}

//========================================

void updateLED_B_State() {

if (LED_B_State == LOW) {
if (currentMillis - previousLED_B_Millis >= LED_B_Interval) {
LED_B_State = HIGH;
previousLED_B_Millis += LED_B_Interval;
}
}
else {
if (currentMillis - previousLED_B_Millis >= blinkDuration) {
LED_B_State = LOW;
previousLED_B_Millis += blinkDuration;
}
}
}

//========================================

//========================================

void updateLED_C_State() {

if (LED_C_State == LOW) {
// if the LED is off, we must wait for the interval to expire before turning it on
if (currentMillis - previousLED_C_Millis >= LED_C_Interval) {
// time is up, so change the state to HIGH
LED_C_State = HIGH;
// and save the time when we made the change
previousLED_C_Millis += LED_C_Interval;
// NOTE: The previous line could alternatively be
// previousLED_C_Millis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical

}
}
else { // i.e. if LED_C_State is HIGH

// if the LED is on, we must wait for the duration to expire before turning it off
if (currentMillis - previousLED_C_Millis >= blinkDuration) {
// time is up, so change the state to LOW
LED_C_State = LOW;
// and save the time when we made the change
previousLED_C_Millis += blinkDuration;
}
}
}

//========================================

void updateLED_D_State() {

if (LED_D_State == LOW) {
// if the LED is off, we must wait for the interval to expire before turning it on
if (currentMillis - previousLED_D_Millis >= LED_D_Interval) {
// time is up, so change the state to HIGH
LED_D_State = HIGH;
// and save the time when we made the change
previousLED_D_Millis += LED_D_Interval;
// NOTE: The previous line could alternatively be
// previousLED_C_Millis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical

}
}
else { // i.e. if LED_D_State is HIGH

// if the LED is on, we must wait for the duration to expire before turning it off
if (currentMillis - previousLED_D_Millis >= blinkDuration) {
// time is up, so change the state to LOW
LED_D_State = LOW;
// and save the time when we made the change
previousLED_D_Millis += blinkDuration;
}
}
}

//========================================

void switchLEDs() {
// this is the code that actually switches the LEDs on and off

digitalWrite(LED_A_Pin, LED_A_State);
digitalWrite(LED_B_Pin, LED_B_State);
digitalWrite(LED_C_Pin, LED_C_State);
digitalWrite(LED_D_Pin, LED_D_State);

}

I recognize that the code above mistakenly used Analog pins A0-A3. That was an error that I corrected by moving to appropriate digital pins.

Thanks.

2 possibilities:

1 - attach an interrupt to a timer, and update your LEDs off that

2 - find a serversweep function that doesn't "block".

There's nothing wrong with using the analog pins as digital. Doing a digitalWrite to A0 is perfectly legit; see "note" near the bottom of this page.

For a different explanation of the blink without delay thing you might find this YouTube episode useful.

This line

const int blinkDuration = random(1000);

should be
int blinkDuration; [code][/code]
because you definitely DO NOT want it to be constant and, at this stage you don't know what the value will be

AND
This line

int blinkDuration = random(1000);

should be

blinkDuration = random(1000);

because you have already defined the variable at the top of the program

After that line add

Serial.println(blinkDuration);

so you can see what values are being produced
I think you will find that it is changing the value much too often.

I think you need to reconsider what you are trying to achieve.
How often do you want the blinkDuration to change?
If you want it to change every (say) 20 seconds you could add another section specially to do that

void updateBlinkDuration() {

   if (currentMillis - previousBlinkUpdateMillis >= blinkUpdateInterval) {
       blinkDuration = random(1000);
       previousBlinkUpdateMillis += blinkUpdateInterval;
    }

}

...R

Thank you Robin2.

I had actually done exactly what you recommended last night but thought it was still failing.

However, your other comment about simply updating too rapidly proved the point. I slowed things down a bit and now I see that it is working properly. My thanks to you and the others who commented.

And I learned more than I bargained for. (Thanks JimboZA!)