Repeat calling of a function

Hi

I'm trying to repeatedly call a function, which is defined by a serial input.

I want the function to run again and again, until another, different call is made.

So far, when a string is received, the function is called and runs. I need to monitor the serial for another string and then change to that particular function.

If no change is made then nothing happens. The function does its thing then looks for a change, if no change then run again.

At the moment, the string received is just adding whatever string I send, to the string already received and so not resetting.

Code so far:

#include <Adafruit_NeoPixel.h>

#define DATA_PIN 6
#define numLed 24  // Define number of LED in string
String readString;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(numLed, DATA_PIN, NEO_GRB + NEO_KHZ800);

  int runTime(0);
  int runTimer (300);
  int wipeSpeed (50);
  
void setup() {

 strip.begin();
  strip.show(); // Initialize all pixels to 'off'
Serial.begin(9600);
}

void loop() {
  
    while ( Serial.available() )
{    // While there is data in the buffer
    delay( 3 ); 
    char c = Serial.read();
    readString += c;    // build the string - “on” or “off”   
}
   {
    Serial.println( readString );
    if ( readString == "whitestrobe" )
     {
Whitestrobe(20,20);
}
    if ( readString == "colourstrobe" )
     {
Colourstrobe(20,20);
}
       if ( readString == "wipe" )
     {    
colorWipe(strip.Color(255, 0, 0), wipeSpeed); // Red
colorWipe(strip.Color(0, 255, 0), wipeSpeed); // Green
colorWipe(strip.Color(0, 0, 255), wipeSpeed); // Blue
     }
   // readString="";
   }
}

// WHITE STROBE

void Whitestrobe(int onDel, int offDel)
{
 for (int y=0; y<3; y++){ 
  int pixelNumToDisplay = random(numLed);    
      strip.setPixelColor(pixelNumToDisplay, 255, 255, 255);
  strip.show();

delay(onDel);
strip.setPixelColor(pixelNumToDisplay, 0, 0, 0);
  strip.show();
  delay(offDel);
  if (y>2){
    y=0;
  }
}
}
// COLOUR STROBE

void Colourstrobe(int onDel, int offDel) {
  for (int x=0; x<100; x++){
  int colourOn = random (1,7);
  int pixelNumToDisplay = random (numLed);
  if (colourOn == 1)
  {
    strip.setPixelColor(pixelNumToDisplay, 255, 0, 0);
  strip.show();
  }
  else if (colourOn == 2)
  {
    strip.setPixelColor(pixelNumToDisplay, 0, 255, 0);
  strip.show();
  }
  else if (colourOn == 3)
  {
    strip.setPixelColor(pixelNumToDisplay, 127, 127, 0);
  strip.show();
  }
  else if (colourOn == 4)
  {
    strip.setPixelColor(pixelNumToDisplay, 0, 127, 127);
  strip.show();
  }
  else if (colourOn == 5)
  {
    strip.setPixelColor(pixelNumToDisplay, 0, 255, 0);
  strip.show();
  }
  else
  {
   strip.setPixelColor(pixelNumToDisplay, 0, 0, 255);
  strip.show(); 
  }
  delay (onDel);
  strip.setPixelColor(pixelNumToDisplay, 0, 0, 0);
  strip.show();
  delay (offDel);
  if (x>99){
    x=0;
  }
        if (readString="colourstrobe"){}
  else{
    readString="";
    break;
  }
  }
}


// COLOUR WIPE

void colorWipe(uint32_t c, int wipeSpeed) {

 for(int i=0; i<numLed; i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wipeSpeed);
      char d = Serial.read();
    readString += d;    // build the string
    Serial.println( readString );
      if (readString="wipe"){}
  else{
    readString="";
    break;
  }
 }
}

I now its sloppy at the moment, but when I get it working correctly, I'll tidy it up.

You need some way of knowing that a new transmission is starting so you can clear that string.

The normal thing is to use a start packet and end packet marker. Some special character (I like to use < for start and > for end but pick whatever you like) that indicates that the transmission is beginning or ending. SO instead of sending "colourstrobe" you would send "". Then, when your program sees the '<' it knows that a new transmission is starting and it can clear the string.

If your code compiles, there's no need to wait. Just use Ctrl-T inside the IDE. While tidying things up may not matter to you, it makes it more difficult for us since we don't know your code.

Delta_G's idea of packet markers is a good one. Also, you can use a different method if you know the packet terminates with a certain character. In the following demo, I assume the user input ends with a newline character ('\n', they pressed the Enter key). I'm also assuming that no command is longer than 19 bytes, and I got rid of the String class since it wastes too much memory.

char incomingStr[20];
int charsRead;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    charsRead = Serial.readBytesUntil('\n', incomingStr, sizeof(incomingStr) - 1);  // Need room for null
    incomingStr[charsRead - 1] = '\0';                  // Make it a string

    memcpy(incomingStr, &incomingStr[1], charsRead);    // Copy over the leading '<' and move down
    Serial.print("string = ");
    Serial.println(incomingStr);
  }
}

If you type in "<12345>", you should see "12345" displayed.

Thanks guys.

The problem, I think doesn't seem to lie with the actual receiving of the command or knowing what to do with the received string, but the execution of the functions.

If the function, say, lights a string of WS2811's from one end to another, it would complete that function and then return to the void loop{}.

Then if no change in data his been received, run the same function again.

If in the mean time, it has received a new command, it should stop calling that function and call another.

My code needs to clear the received string variable to stop it re-calling the same function, but if I do that then it won't know which new function to call within the void loop.

As it stands, if I call "colourstrobe", then call "wipe", the serial print gives me colourstrobewipe". Even though I assumed it would be handled and cleared within the IF ELSE at the end of the function.

BTW Cheers for the CTRL-T thing