Break from function move to new function on serial data receipt

Morning Arduino boffins

I have just recently aquired an Arduino Uno and decided I would learn something new. I've got myself a NeoPixel header board which Im controlling via serial from a raspberry pi. As per the code below, I am entering a function on receipt of a charecter - in this case 'd'. What I want to do is be able to interupt the 'light show' by sending the arduino the letter 'a' to make it imediatly quit and flash a bright white light.

On the PI, the code (Truncated) is:

import serial
ser = serial.Serial('/dev/ttyACM0', 9600)
ser.write('d')
sleep(50)
ser.write('a')

On the Arduino

#include "SPI.h" // Comment out this line if using Trinket or Gemma
#include <Adafruit_NeoPixel.h>

#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN            6
#define NUMPIXELS      40
#define BRIGHTNESS 30

#define NUM_LEDS 40
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);


void setup()
{
  pixels.begin(); // This initializes the NeoPixel library.
  Serial.begin(9600);
}

void loop()
{
  lightOn(10);
    if (Serial.available() > 0) {
   
        { 
            int Byte = Serial.read();
            readserial(Byte);
        }
    }          
}

void readserial(int inByte)
{

    
    int i;

         switch (inByte) {
            case 'a':
                 for(int i=0;i<NUMPIXELS;i++){
                    pixels.setPixelColor(i, pixels.Color(255,255,255));
                    pixels.show(); 
                  }
                  delay(5000);
              break;
            case 'b':
                 for(int i=0;i<NUMPIXELS;i++){
                    pixels.setPixelColor(i, pixels.Color(255,255,255));      
                    pixels.show();
                  }
                break;
             case 'c':
               strip.setBrightness(BRIGHTNESS);
                strip.begin();
                strip.show(); // Initialize all pixels to 'off'
                for(int i=0;i<NUMPIXELS;i++){
                    pixels.setPixelColor(i, pixels.Color(0,0,0));
                    pixels.show();               
                  }
                  break;
             case 'd':
                  dance();
                  break;
             default:
                  for(int i=0;i<NUMPIXELS;i++){
                    pixels.setPixelColor(i, pixels.Color(255,255,255));
                    pixels.show(); 
                  }
                break;
          }
}

void lightOn(int n)
{
                  for(int i=0;i<NUMPIXELS;i++){
                    pixels.setPixelColor(i, pixels.Color(0,0,0));
                    pixels.show();               
                  }
}

void dance()
{
  // Some example procedures showing how to display to the pixels:
  colorWipe(strip.Color(255, 0, 0), 50); // Red
  colorWipe(strip.Color(0, 255, 0), 50); // Green
  colorWipe(strip.Color(0, 0, 255), 50); // Blue
  colorWipe(strip.Color(255, 255, 255), 50); // White
  whiteOverRainbow(20,75,5);  
  pulseWhite(5); 

  rainbowFade2White(3,3,1);


}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
}
}

void pulseWhite(uint8_t wait) {
  for(int j = 0; j < 256 ; j++){
      for(uint16_t i=0; i<strip.numPixels(); i++) {

          strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
        }
        delay(wait);
        strip.show();
      }

  for(int j = 255; j >= 0 ; j--){
      for(uint16_t i=0; i<strip.numPixels(); i++) {

          strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
        }
        delay(wait);
        strip.show();
      }
}


void rainbowFade2White(uint8_t wait, int rainbowLoops, int whiteLoops) {
  float fadeMax = 100.0;
  int fadeVal = 0;
  uint32_t wheelVal;
  int redVal, greenVal, blueVal;

  for(int k = 0 ; k < rainbowLoops ; k ++){
    
    for(int j=0; j<256; j++) { // 5 cycles of all colors on wheel

      for(int i=0; i< strip.numPixels(); i++) {

        wheelVal = Wheel(((i * 256 / strip.numPixels()) + j) & 255);

        redVal = red(wheelVal) * float(fadeVal/fadeMax);
        greenVal = green(wheelVal) * float(fadeVal/fadeMax);
        blueVal = blue(wheelVal) * float(fadeVal/fadeMax);

        strip.setPixelColor( i, strip.Color( redVal, greenVal, blueVal ) );
    
      }

      //First loop, fade in!
      if(k == 0 && fadeVal < fadeMax-1) {
          fadeVal++;
      }

      //Last loop, fade out!
      else if(k == rainbowLoops - 1 && j > 255 - fadeMax ){
          fadeVal--;
      }
        
        strip.show();
        delay(wait);
    }
  
  }



  delay(500);


  for(int k = 0 ; k < whiteLoops ; k ++){

    for(int j = 0; j < 256 ; j++){

        for(uint16_t i=0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
          }
          strip.show();
        }

        delay(2000);
    for(int j = 255; j >= 0 ; j--){

        for(uint16_t i=0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, strip.Color(0,0,0, gamma[j] ) );
          }
          strip.show();
        }
  }

  delay(500);


}

void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength ) {
  
  if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;

  int head = whiteLength - 1;
  int tail = 0;

  int loops = 3;
  int loopNum = 0;

  static unsigned long lastTime = 0;


  while(true){
    for(int j=0; j<256; j++) {
      for(uint16_t i=0; i<strip.numPixels(); i++) {
        if((i >= tail && i <= head) || (tail > head && i >= tail) || (tail > head && i <= head) ){
          strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
        }
        else{
          strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
        }
        
      }

      if(millis() - lastTime > whiteSpeed) {
        head++;
        tail++;
        if(head == strip.numPixels()){
          loopNum++;
        }
        lastTime = millis();
      }

      if(loopNum == loops) return;
    
      head%=strip.numPixels();
      tail%=strip.numPixels();
        strip.show();
        delay(wait);
    }
  }
  
}
void fullWhite() {
  
    for(uint16_t i=0; i<strip.numPixels(); i++) {
        strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
    }
      strip.show();
}


// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256 * 5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
      
    }
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3,0);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3,0);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0,0);
}

uint8_t red(uint32_t c) {
  return (c >> 8);
}
uint8_t green(uint32_t c) {
  return (c >> 16);
}
uint8_t blue(uint32_t c) {
  return (c);
}

Thanks in advance.

Rather than "break from function" you should write functions that don't block other activities. Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. Also look at the demo Several Things at a Time to see how non-blocking functions can do long-running actions.

If you want a responsive program don't use delay() or any FOR or WHILE loop that takes longer than a few microseconds to complete. Your line 210 while(true){ is a complete NO NO.

...R

void readserial(int inByte)

This is a dumb name for a function that does not read anything, and does nothing with the serial port.

Thanks Robin, I will check those out..

Yes Paul, I agree. It was a mash up of code, I moved the actual serial events to their own function but when it wasn't doing what I wanted - I moved that part of it back again. Thanks for your input.