arduinoserial-portinterruptledfastled

How to use Serial as an interrupt for other functions


I'm making an LED control program (using FastLED, of course) and using Serial (with the Serial monitor) to control it. I just connected it via USB and for the most part it works just fine. However, I noticed with the long, flashing routines that I couldn't stop them and make the LEDs do something else. The flash routine in my code is very simple:

void flash(CRGB color, int count, int del){
  for(int i = 0; i < count; i++){
    if(pause){
      break;
    }
    fillLeds(color.r, color.g, color.b);
    milliDelay(del);
    fillLeds(0,0,0);
    milliDelay(del);
  }
}

With fillLeds(r,g,b) being a for loop, looping through and setting all LEDs to a certain color, and milliDelay is just delay() using millis and not the delay() function.

I need to be able to pause not just this, but other functions as well (probably using break;) and then execute other code. It seems easy, right? Well, I've noticed that when I send a byte over Serial, it goes into this "queue," if you will, and then is sequentially read.

I can’t have this happen. I need the next byte entering Serial to activate some kind of event that pauses the other flash() function running, and then be used. I have implemented this like:

void loop()
{
  if (Serial.available() > 0)
  {
    int x = Serial.read();
    Serial.print(x);
    handleRequest(x);
  }

  FastLED.show();
  FastLED.delay(1000 / UPDATES_PER_SECOND);
}

Where handleRequest(x); is just a long switch statement with calls to the flash method, with different colors being used, etc.

How can I make the Arduino pause other loops whenever a new byte is received, instead of adding it to this "queue" to be acted upon later? If this is not possible thanks for reading anyway. I've tried using serialEvent() which doesn't appear to work.


Solution

  • I think you need two loops. You have one, which is your main loop, and you can add another (like a multi threading) with the TimerOne library. Like this:

    Timer1.initialize(your desired delay in this loop);
    Timer1.attachInterrupt(your desired function in this loop);
    

    So maybe you can add an if statement with a variable in your second loop to prevent some function and update the variable in your first loop or something like that.