Help with complicated "Blink Without Delay"

Aruinians,

This might not be complicated, but I think it is.

I'm trying to find an elegant way to "Blink Without Delay" for my First Responder Vehicle project.

The main rub is that I need to be able to select different flash patterns, and have them flash without stalling out the code.

The code for the whole program is four pages long and growing, I'll try to post all the relevant excerpts:

//Relevant variable declaration
boolean lightsOn = false;
 
char lightColorA = 'o';
char lightColorB = 'o';
 
int currentMillis = millis();
int tempMillis = 0;
 
int blinkInterval = 250;
int offInterval = 100;

----

  if(lightsOn)     //lightsOn is a boolean that triggers whether the lights flash or not
 {
    lightBlink();     //This calls the actual flashing function
  }
  else
  {
    colorSelect('o');     //Color 'o' is actually off (colorSelect sets the color to flash)
  }

----

boolean flashPatternTime(int interval)     //Eventually this function will just return true to flash or false for off
//Right now it just adjusts tempMillis
{
  currentMillis = millis();
  
  if(tempMillis - interval > currentMillis)
  {
    tempMillis = millis();
    return false;
  }
  else
  {
    return false;
  }
}
 
void lightBlink()     //This is the function for the first flash pattern, that I'm trying to unbreak
{
  colorSelect(lightColorA);
  flashPatternTime(blinkInterval);     //This is replacing the former (temporary) delay()
  colorSelect('o');
  flashPatternTime(offInterval);
  colorSelect(lightColorA);
  flashPatternTime(blinkInterval);
  colorSelect('o');
  flashPatternTime(offInterval);
}

What I'm thinking of doing is creating several arrays of pre-defined flash patterns. Something like:

flashPattern1 [] = {
{1, 0, 1, 0, 2, 0 , 2}, //Color to flash (0=off, 1 & 2 are colors 1 & 2)
{0, 0, 0, 1, 0, 0, 0}} //Where we are in the sequence

That syntax may be wrong, but I think that illustrates the idea. Basically, the '1' would rotate through the second part of the array, advancing each time the timer reaches the correct point, and flashes whichever color is associated with the array above.

Does this make sense? Is there a better way?

Appreciate any help.

Thanks,

That's the general concept of what I'm going for, and I don't know why reading it triggered the idea to do a if/switch combination to step through the array, but I think it will work and now my head hurts.

Why, oh why, did I go to a school with terrible CompSci teachers?

Why, oh why, did I go to a school with terrible CompSci teachers?

I don't think that you can place all the blame on the teachers. The students need to accept some responsibility for failing to learn to think logically.

I don't know if you've ever tried to learn Assembly Language from a teacher who refused to allow computers to be used in her classroom, but it definitely pushed me to a different field of study.

Now I learn from the internet, to accomplish projects that interest me.

I don't know if you've ever tried to learn Assembly Language from a teacher who refused to allow computers to be used in her classroom

I learned assembly language at a time when it was physically impossible to get any kind of computer into the classroom, because the classroom simply wasn't big enough. :wink:

I'm so glad I'm not old. :slight_smile:

P.S.: I fully acknowledge that learning is the responsibility of the student. That does not change the fact that I hated that professor - I am very much a "learn by doing" personality.

I don't know if you've ever tried to learn Assembly Language from a teacher who refused to allow computers to be used in her classroom, but it definitely pushed me to a different field of study.

I haven't. But, I think that the purpose of the exercise was to teach you to think logically.

Look at the code posted in this forum. Some of it is really good. But, some of it boggles the mind. "It compiles, so it must work; therefore there is a problem in the IDE/library/someone else's code" is far too prevalent an attitude here.

Analyzing code that you have written, playing compiler, drawing pictures that show what is in memory, etc., were things that I suspect that teacher was trying to teach, in addition to teaching assembly language programming.

That does not change the fact that I hated that professor - I am very much a "learn by doing" personality.

I too was unimpressed by my computer studies lecturer, because he was only about three pages ahead of the class in the textbook.
Guess what was the easiest way to shine in class?

I'm definitely trying to think logically, I'm fairly certain I could "brute force" the problem with about 40 variables and if-else statements. I'm trying to avoid that and write code that both A) works and B) I can understand in three days when I look back at it (comments can only delve so far into the convoluted mind).

I appreciate the help I've gotten on these forums so far - I haven't programmed in a long time, and members have been very helpful in showing me different ways to see a problem.

Not sure if this will work (I am at a work computer) but I'm going to try it when I get back.

//Setup the timing variables
long onInterval = 250;
long offInterval = 100;
long interval = onInterval;

//Track the last time the time was updated
long lastMillis = millis();

//Variable to track where in the pattern we are
int flashPatternStepper = 0;
//Variable to track which pattern is being used
int flashPatternSelect = 0;

//Array of possible flash patterns
int [][] flashPatterns = {{1, 0, 2, 0},
			  {1, 2, 1, 2}};

//Variables to track color selection
char color1 = 'r';
char color2 = 'b';

//Pins for the RGB LED
int redPin = 9;
int greenPin = 10;
int bluePin = 11;

//Normal setup just setting pin modes
void setup()
{
	pinMode(redPin, OUTPUT);
	pinMode(greenPin, OUTPUT);
	pinMode(bluePin, OUTPUT);
}

//loop() only calls the handleLEDs function for now
void loop()
{
	handleLEDs();

	//Code to change values of flashPatternSelect, onInterval, offInterval, color1, and color2
}


void handleLEDs()
{
	//Check to see if lights should be on or off
	if(flashPatterns[flashPatternSelect][flashPatternStepper] == 0)
	{
		interval = offInterval
	}
	else
	{
		interval = onInterval;
	}

	//Check if we need to advance flashPatternStepper to the next place in the sequence
	if(millis() - lastMillis > interval)
	{
		lastMillis = millis();
		flashPatternStepper++;
	
		if(flashPatternStepper > flashPatterns.length-1)
		{
			flashPatternStepper = 0;
		}
	}

	//colorSelect decides which LED Pins should be active, if any
	colorSelect();
}

//Control the colors
void colorSelect()
{
	char colorChoice;

	///Set colorChoice based on where we are in the sequence
	switch (flashPattern[flashPatternSelect][flashPatternStepper])
	{
		case 1:
			colorChoice = color1;
			break;

		case 2:
			colorChoice = color2;
			break;

		case 0:
			colorChoice = 'o';
			break;
	}

	//Actually turn on/off the LED pin(s)
	switch(colorChoice)
	{
	    	case 'y':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, LOW);
	      		digitalWrite(bluePin, HIGH);
      			break;

    		case 'w':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, LOW);
      			arduino.digitalWrite(bluePin, LOW);
      			break;

    		case 'r':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, HIGH);
      			break;

    		case 'g':     
     			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, LOW);
      			digitalWrite(bluePin, HIGH);
      			break;

    		case 'b':     
      			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, LOW);
      			break;
	
    		case 'p':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, LOW);
      			break;

    		case 'c':     
      			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, LOW);
      			digitalWrite(bluePin, LOW);
      			break;

    		case 'o':
      			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, HIGH);
      			break;
  	}
}

Hopefully I can build from this to what I need.

//Array of possible flash patterns
int [][] flashPatterns = {{1, 0, 2, 0},
			  {1, 2, 1, 2}};

That's not how to define an array in C/C++. The [] are in the wrong place. The size needs to be defined for all but the last dimension.

		interval = offInterval

is missing something. I can't quite put by finger on it...

		if(flashPatternStepper > flashPatterns.length-1)

flashPatterns is an array, not a class instance. It doesn't have methods or fields.

	switch (flashPattern[flashPatternSelect][flashPatternStepper])

Did you mean flashPatterns?

     			arduino.digitalWrite(bluePin, LOW);

What? As opposed to a PIC that is supposed to execute this instruction?

That's what I get for writing code in Notepad, and writing the same program for Arduino and Processing (which is where arduino.digitalWrite(bluePin, LOW) came from - a botched copy-paste from an e-mail to myself).

I'll fix the points you mentioned and throw it back up once I've gotten it to work - I know for a fact I'm not the only person working on this at this time.

It seems like all the problems you identified are all syntax problems rather than logic, so I have hope that the concept itself is solid.

EDIT:

This worked. Thanks everyone for the help.

//Setup the timing variables
long onInterval = 250;
long offInterval = 250;
long interval = onInterval;

//Track the last time the time was updated 
long lastMillis = millis();

//Variable to track where in the pattern we are 
int flashPatternStepper = 0; 
//Variable to track which pattern is being used 
int flashPatternSelect = 0;

//Array of possible flash patterns
int flashPatterns [2][4] = {{1, 0, 2, 0},
			  {1, 2, 1, 2}};
int arrayLength = 4;

//Variables to track color selection
char color1 = 'r';
char color2 = 'b';

//Pins for the RGB LED
int redPin = 9;
int greenPin = 10;
int bluePin = 11;

//Normal setup just setting pin modes
void setup()
{
	pinMode(redPin, OUTPUT);
	pinMode(greenPin, OUTPUT);
	pinMode(bluePin, OUTPUT);
}

//loop() only calls the handleLEDs function for now 
void loop() 
{
	handleLEDs();

	//Code to change values of flashPatternSelect, onInterval, offInterval, color1, and color2 
}


void handleLEDs()
{
	//Check to see if lights should be on or off
	if(flashPatterns[flashPatternSelect][flashPatternStepper] == 0)
	{
		interval = offInterval;
	}
	else
	{
		interval = onInterval;
	}

	//Check if we need to advance flashPatternStepper to the next place in the sequence
	if(millis() - lastMillis > interval)
	{
		lastMillis = millis();
		flashPatternStepper++;
	
		if(flashPatternStepper > arrayLength-1)
		{
			flashPatternStepper = 0;
		}
	}

	//colorSelect decides which LED Pins should be active, if any
	colorSelect();
}

//Control the colors
void colorSelect()
{
	char colorChoice;

	///Set colorChoice based on where we are in the sequence
	switch (flashPatterns[flashPatternSelect][flashPatternStepper])
	{
		case 1:
			colorChoice = color1;
			break;

		case 2:
			colorChoice = color2;
			break;

		case 0:
			colorChoice = 'o';
			break;
	}

	//Actually turn on/off the LED pin(s)
	switch(colorChoice)
	{
	    	case 'y':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, LOW);
	      		digitalWrite(bluePin, HIGH);
      			break;

    		case 'w':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, LOW);
      			digitalWrite(bluePin, LOW);
      			break;

    		case 'r':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, HIGH);
      			break;

    		case 'g':     
     			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, LOW);
      			digitalWrite(bluePin, HIGH);
      			break;

    		case 'b':     
      			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, LOW);
      			break;
	
    		case 'p':     
      			digitalWrite(redPin, LOW);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, LOW);
      			break;

    		case 'c':     
      			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, LOW);
      			digitalWrite(bluePin, LOW);
      			break;

    		case 'o':
      			digitalWrite(redPin, HIGH);
      			digitalWrite(greenPin, HIGH);
      			digitalWrite(bluePin, HIGH);
      			break;
  	}
}