String vs string vs char + Arrays? Correct approach?

@sterretje

thank you for the reply… and the example…

with some minor edits (naming convention updates… and removal of the -1 in the array loop/output (I couldnt get my last item to output with it there still)… I believe I have something I can work with.

I do have a question however… before this update I was only at (roughly 6%-8% of dynamic memory… with this few lines/updates… I am now @ 26%! (and I havent even added in any stepper motor stuff…or anything else!) LOL…

Is there anything I can do to trim this down with my current sketch/approach? (casting things a different way…or something?)

Current sketch that is working as I expect so far.: (some refactoring still needs to be applied)

#define SOP '<'
#define EOP '>'
bool hasStarted = false;
bool hasEnded = false;

char incomingSerialData[100];
byte index;

char *actionPacket;
byte packetCounter;

int positionValue = 0;
int amountValue = 0;

void setup() {
  //serial monitor output
  Serial.begin(9600);
}


//example recipie format  (paste into serial monitor for output example)
//<b=1:1,b=2:1,m=6:200> = bottle#1/1 shot, bottle#2/1 shot, mixer#6/200ms



void loop(){
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0){
    char incomingCharacter = Serial.read();
    //Serial.println(incomingCharacter);
    if(incomingCharacter == SOP){
      index = 0;
      incomingSerialData[index] = '\0';
      hasStarted = true;
      hasEnded = false;
    }else if (incomingCharacter == EOP){
      hasEnded = true;
      break;
    }else{
      if (index < 100) {
        incomingSerialData[index] = incomingCharacter;
        index++;
        incomingSerialData[index] = '\0';
      }
    }
  }

 // Packet data done...parse/evaluate data
  if(hasStarted && hasEnded){
      
    Serial.println("");
    Serial.print("TOTAL COMMAND PACKET (CP) CHECK: ");
    Serial.println(incomingSerialData);
    Serial.println("");
    
    //packet counter reset
    packetCounter = 0;

    // array to store 10 texts (tokens)
    char *actionData[10];
    // position where to store a token
    int packetIndex = 0;

    //get first delimited packets from command string
    actionPacket = strtok(incomingSerialData, ","); //split action packets from command string

    //keep parsing these delimited packets from the command string until there are none left to parse
    while(actionPacket != NULL){
      packetCounter++;
      Serial.println("-----------------------------------");
      Serial.print("PARSED ACTION PACKET (AP) ");      
      Serial.print(packetCounter);
      Serial.print(": ");
      Serial.println("");      
      Serial.println(actionPacket);
      Serial.println("");    

      // copy token pointer to text array
      actionData[packetIndex++] = actionPacket;

      if(packetIndex == 10){
        break;
      }
      
      //update parsing params to next comma delimited chunk/action packet
      actionPacket = strtok(NULL, ",");     
      
      //send off to parse function/loop for processing      
      //parseAction(actionPacket); //problem stems from here!!!!
           
    }

    //check whats in 'array'
    Serial.println("");    
    for (uint8_t arrayIndex = 0; arrayIndex < packetIndex; arrayIndex++){
      Serial.print("Chunk Data: ");
      Serial.println(actionData[arrayIndex]);
      //send off to parse function/loop for processing      
      parseAction(actionData[arrayIndex]);
    }
    Serial.println("---");

    //parsing complete
    Serial.println("");
    Serial.print("PARSING PACKETS COMPLETE");
         
    // Reset for the next packet
    hasStarted = false;
    hasEnded = false;
    index = 0;
    incomingSerialData[index] = '\0';
    
  }

}



void parseAction(char *packetData) {
  Serial.println("");
  Serial.print("TOTAL ACTION PACKET (AP) RECEIVED CHECK: ");
  Serial.println(packetData);
  char *actionToken = strtok(packetData, "="); //split action value from location/amount values
  if(actionToken){
    Serial.print("ACTION COMMAND: ");
    Serial.println(actionToken);  
        
    //check if bottle 'action' data coming over
    if(strcmp(actionToken, "b") == 0){      
      //grab position value    
      char *positionToken = strtok(NULL, ":");
      if(positionToken){
        Serial.print("BOTTLE #: ");
        Serial.println(positionToken);
        positionValue = atoi(positionToken);

        //now grab 'amount' value
        char *amountToken = strtok(NULL, "\0");
        //char *amountToken = strtok(NULL, ",");
        if(amountToken){
          Serial.print("SHOT COUNT: ");
          Serial.println(amountToken);
          amountValue = atoi(amountToken);
        }
      }
    }

    //check if mixer action data coming over
    if(strcmp(actionToken, "m") == 0){
      char *positionToken = strtok(NULL, ":");
      if(positionToken){
        Serial.print("VALVE #: ");
        Serial.println(positionToken);
        positionValue = atoi(positionToken);
        //now grab 'amount' value
        char *amountToken = strtok(NULL, "\0");
        //char *amountToken = strtok(NULL, ",");
        if(amountToken){
          Serial.print("OPEN TIME: ");
          Serial.println(amountToken);
          amountValue = atoi(amountToken);
        }
      }
    }
  }

   //update parsing params
   //actionPacket = strtok(NULL, ",");
}

Using the F macro for printed string literals will save some SRAM.

Serial.print(F("This just in ... "));
Serial.print(F("TOTAL COMMAND PACKET (CP) CHECK: "));

xl97:
Thanks MorganS for the reply.

I’m not quite following the pointer issue…

In my mind… I am moving the pointer once… (to get the first ‘chunk’ of comma delimited data)…

I thought I was moving the same pointer again in another function (to break down/sub-parse that trimmed out comma delimited snippet)

Help me understand?

Once called in the main loop… and once called in the parseAction() function…

Is the one in the parseAction() function not seen because of scope or something? (ie: I accidentally created a new pointer reference or something?)

There is only one strtok() function. You call it once with a pointer and it remembers where it is up to.

You called it once on the big string and then again on another string. It doesn’t matter that the second string is inside the first. It is the same effect as using a totally different string anywhere else.

By using it inside parseAction(), you have thrown away the memory of where it was up to in the bigger string.