When to process received serial data?

So I have a sketch that basically sweeps through the color spectrum illuminating a RGB LED strip.

The function goes through several loops changing the red color, then green, then blue etc etc.

As the function can take 30 seconds or so to complete, before returning to the main loop function, it takes forever before I receive any serial data.

Void loop()  {
 DoRgbSequence();
 ReceiveData();
} 

Void DoRgbSequence()  {
  // loop through red

  // loop through green

  // loop through blue...... 

 Etc etc etc......

}

What I did to solve this is do a receive between each loop, but this is still slow...

Void DoRgbSequence()  {
  // loop through red

 ReceiveData() ;

 //loop through green

 ReceiveData() ;

 // loop...... 

ReceiveData() ;

 Etc etc etc

}

Any suggestions on how or when I should receive or process the serial buffer, without having to wait for a function to complete?

Basically I'm sending a serial command (proprietary string formatted message) to tell the arduino to change color sequence or do another task. But as the color sequences are time consuming, it takes a while to complete before actioning the received command.

Help.....

You can include the RecieveData routine in each iteration of DoRgbSequence() instead of after.

In void DoRgbSequence() , you can place the function parts of ReceiveData() anywhere inside you wish. at various intervals through DoRgbSequence(). You say it takes about 30 seconds to run through DoRgbSequence() , how often do you want to receive data? Try placing the function after certain sections/timestamps of the rbg sequence where a slight lag may not be too noticeable as the serial can “block”.

Bill

But as the color sequences are time consuming,

Maybe you should fix that. Do you have any delays in you code?

zoomkat:
Maybe you should fix that. Do you have any delays in you code?

So I actually have multiple color sequence functions (DoRgbSequence1, DoRgbSequence2, etc etc) that are called depending on the serial command (via Xbee) that was sent to the Arduino

I also send serial commands to vary the fade delay and the brightness.
So the function can be as short or as long as I define. I used 30 seconds as an example because DoRgbSequence1 actually cycles through many different colors.

void DoRgbSequence1() {
  int r, g, b;

  XbeeRx();  
   
  // fade from blue to violet
  for (r = 0; r < 256; r++) { 
    analogWrite(REDPIN, r / Brightness);
    delay(fadeDelay);
  } 

  XbeeRx();  

  // fade from violet to red
  for (b = 255; b > 0; b--) { 
    analogWrite(BLUEPIN, b / Brightness);
    delay(fadeDelay);
  } 
  
  XbeeRx();  

  //ORANGE (note delays)
  // fade from red to orange
  for (g = 0; g < 127; g++) { 
    analogWrite(GREENPIN, g / Brightness);
    delay(fadeDelay * 2);
  } 

  XbeeRx();  

  ETC ETC.......

So by putting the receive function inside any of the “for loops” would still have a somewhat unpredictable receive time.
And for a fast light sequence it could be calling the receive function pretty often… is that a problem?
Are interrupts of some kind the solution??

On a side note the XbeeRx() function uses Serial.available() to see if there is data, or just jumps out of the function.

void XbeeRx() {
  String content = "";
  char character;

  if (Serial.available() > 0) {

    while(Serial.available()) {
        character = Serial.read();
        content.concat(character);
    }
  
    if (content == "x\n") {
      ResetPinValues();
      SequenceNo = -1; // set to -1 to stop ALL
      Serial.println("Stopping ALL sequences\n");
    }    
    else if (content == "1\n") {
      ResetPinValues();
      SequenceNo = 1;
      Serial.println("Changing sequence to 1\n");
    }
    else if (content == "2\n") {
      ResetPinValues();
      SequenceNo = 2;
      Serial.println("Changing sequence to 2\n");
    }

ETC ETC...

So, you do have delay()s in your code and this is what is preventing timely response to serial (and any other) input. To solve this you need to change the structure of your program

(1) Change it to a "state Machine" such that at any one time the program is in one of many states doing something. Usually the program will stay in that state until a period of time has elapsed then change to another state. For instance your program could output particular RGB values for a period.

(2) Use millis() for timing instead of delay(). When the program enters a particular state save the time from millis() and go round loop() again reading input(s) etc. When millis() minus the start time equals or is greater than the timing period for the state take any actions required and move to a new state and save the start time again.

Unlike using delay() this timing method does not block the free running of loop() which allows inputs to be checked frequently. See Several things at the same time for woring examples of the method.

Read, and understand the concept behind, the sketch "Blink without delay"

You didn't answer the question about delays in your code.

TheRaven762: As the function can take 30 seconds or so to complete, before returning to the main loop function, it takes forever before I receive any serial data.

Why is that a problem ?

What do you want to do with the received data while the function is executing ?

It is a complete waste of time posting an outline of your code when the problem is likely to be in the details. You should NOT be using the delay() function if you want your program to be responsive. Have a look at several things at a time which illustrates the use of millis() for timing and planning and implementing a program which also includes user data input..

...R