Receiving serial and colour fading.

Hi, I am trying to incorporate some colour fading into my code, however I have hit a roadblock. If I was to put it into my loop, the Arduino would miss all the serial data until it had finished fading LED's, then it'd wait maybe 1/16 of a second for serial data, then go back to fading LED's, which means it'd pretty much miss all of the serial data, Ideally I need 2 loops, but since the ATMega isn't a multitasking uC I can't really do that.

Here is my code:

void setup(){
  Serial.begin(115200);
  pinMode(12, OUTPUT);
}

void loop()
{
  char c, t;
   int nnn;

   if(Serial.available() > 0) // If there is data to read
   {
       c = Serial.read(); // Get a character

       delay(50);

       if(c >= 'a' && c <= 'z') // If it's a command
       {
          nnn = 0;
          while(Serial.available() > 0) // While there is still data
          {
             t = Serial.read(); // Read next character

             if(t == ',' || t == ' ')
               continue; // Skip commas and spaces
             if(t >= '0' && t <= '9') // If it's a number
             {
                nnn *= 10; // Multiply previous value by 10
                nnn += t - '0'; // Add the new digit
             }
             else
                break;

             delay(50);
          }
       }
   }

   // Now, do something with c and nnn
   switch(c)
   {
      case 's':
        analogWrite(5,nnn);
        break;
      case 'f':
        analogWrite(3,nnn);
        break;
        case 'u':
          if (nnn > 100){
            digitalWrite(12, HIGH);
          }
          if (nnn < 100){
            digitalWrite(12, LOW);
          }
          break;
        case 'r':
          analogWrite(10,nnn);
          break;
        case 'g':
          analogWrite(6,nnn);
          break;
        case 'b':
          analogWrite(9,nnn);
          break;
        case 'a':
          analogWrite(3, nnn);
          analogWrite(6, nnn);
          analogWrite(9, nnn);
          analogWrite(10, nnn);
          analogWrite(11, nnn);
          digitalWrite(12, LOW);
          break;
      // Add other letters here, with break after each one
   }
}

Basically I just send z, 255 over serial and it'll start colour fading, so lets just say that "z" is the switch for the fading. SO somehow when z = 1, I have to have the LED's fade between random colours, but continue running everything in loop() so it doesn't miss serial data.

Is this possible?

-Dan :slight_smile:

Is this possible?

Yes, it is. Look at the blink without delay example. Basically, you want to get rid of all the delay statements. Create functions to perform individual actions, such as ReadSerialData() and FadeNextStep().

Call these functions in loop.

void loop()
{
   ReadSerialData();
   FadeNextStep();
}

ReadSerailData's purpose ought to be obvious. If there is serial data, read and parse it. Set some global variables that the FadeNextStep function will read.

FadeNextStep will use millis() to determine what time it is (relative to some fixed event) and compare that to the time that it should next do something. If it's time, do it, and set the next time to do something.

The "do it" part is to use analogWrite to set the appropriate pin's PWM value.

Thanks for the reply, I came up with this just before and it works fairly well :slight_smile:

int z = 0;
float h;
int h_int;
int val = 0;
void setup(){
  Serial.begin(115200);
  pinMode(12, OUTPUT);
}

void h2rgb(float H, int& R, int& G, int& B) {

  int var_i;
  float S=1, V=1, var_1, var_2, var_3, var_h, var_r, var_g, var_b;

  if ( S == 0 )                       //HSV values = 0 ÷ 1
  {
    R = V * 255;
    G = V * 255;
    B = V * 255;
  }
  else
  {
    var_h = H * 6;
    if ( var_h == 6 ) var_h = 0;      //H must be < 1
    var_i = int( var_h ) ;            //Or ... var_i = floor( var_h )
    var_1 = V * ( 1 - S );
    var_2 = V * ( 1 - S * ( var_h - var_i ) );
    var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) );

    if      ( var_i == 0 ) {
      var_r = V     ;
      var_g = var_3 ;
      var_b = var_1 ;
    }
    else if ( var_i == 1 ) {
      var_r = var_2 ;
      var_g = V     ;
      var_b = var_1 ;
    }
    else if ( var_i == 2 ) {
      var_r = var_1 ;
      var_g = V     ;
      var_b = var_3 ;
    }
    else if ( var_i == 3 ) {
      var_r = var_1 ;
      var_g = var_2 ;
      var_b = V     ;
    }
    else if ( var_i == 4 ) {
      var_r = var_3 ;
      var_g = var_1 ;
      var_b = V     ;
    }
    else                   {
      var_r = V     ;
      var_g = var_1 ;
      var_b = var_2 ;
    }

    R = (1-var_r) * 255;                  //RGB results = 0 ÷ 255
    G = (1-var_g) * 255;
    B = (1-var_b) * 255;
  }
}

void loop()
{
   if(z == 1){
     if(val < 1023){
     val = val++;
     delay(20);
    h = ((float)val)/1024;
    h_int = (int) 360*h;
    int redvar;
    int bluevar;
    int greenvar;
    h2rgb(h, redvar, greenvar, bluevar);
    analogWrite(10, redvar);
    analogWrite(6, greenvar);
    analogWrite(9, bluevar);
    }
    else{ val = 0; }
   }
  char c, t;
   int nnn;

   if(Serial.available() > 0) // If there is data to read
   {
       c = Serial.read(); // Get a character

       delay(50);

       if(c >= 'a' && c <= 'z') // If it's a command
       {
          nnn = 0;
          while(Serial.available() > 0) // While there is still data
          {
             t = Serial.read(); // Read next character

             if(t == ',' || t == ' ')
               continue; // Skip commas and spaces
             if(t >= '0' && t <= '9') // If it's a number
             {
                nnn *= 10; // Multiply previous value by 10
                nnn += t - '0'; // Add the new digit
             }
             else
                break;

             delay(50);
          }
       }
   }

   // Now, do something with c and nnn
   switch(c)
   {
      case 's':
        analogWrite(5,nnn);
        break;
      case 'f':
        analogWrite(3,nnn);
        break;
        case 'u':
          if (nnn > 100){
            digitalWrite(12, HIGH);
          }
          if (nnn < 100){
            digitalWrite(12, LOW);
          }
          break;
        case 'r':
          analogWrite(10,nnn);
          break;
        case 'g':
          analogWrite(6,nnn);
          break;
        case 'b':
          analogWrite(9,nnn);
          break;
        case 'z':
          if(nnn > 100){
            z = 1;
          }
          if(nnn < 100){
            z = 0;
          }
          break;
        case 'a':
          analogWrite(3, nnn);
          analogWrite(6, nnn);
          analogWrite(9, nnn);
          analogWrite(10, nnn);
          analogWrite(11, nnn);
          digitalWrite(12, LOW);
          break;
      // Add other letters here, with break after each one
   }
}