I love timer.h but it won't let me parse a string

Long story short: I am parsing a string from the kbd pretty well, but when I try to execute that in a timer I only get zeros.

Please help, here is the code

#include <timer.h>
auto timer_NoBlock = timer_create_default();

String Kbd_Str;
uint8_t K_Vals[7];  // PID VALUES To be written

void setup() {
  // initialize both serial ports:
  Serial.begin(115200);
  timer_NoBlock.every(3 , Read_All_Enc);
}



void loop() {
  timer_NoBlock.tick();


  if (Serial.available()) {
    Kbd_Str = Serial.readStringUntil('\n');
    //Serial.println(Kbd_Str);
    //DataSplit_PID();  // this works

  }

}

///P 11 120 55 85 33 85 35 // this is what I am writing to be split in the Ser out for example


void DataSplit_PID()

{ String c = Kbd_Str ;
  // String c = FromTablet.remove(0,2);
  String PID_KStr[20];

  int var;



  if (c[0] == 'P') {            // if the command trigger word is detect

    //Serial.println(c.length());  // display start of message
    for (int i = 1; i <= c.length(); i++) { // a for loop is set to run as many time as the # of characters in a string

      if (c[i] == ' ') { // SPace is used for Separation
        var++;           // Everytime space is detected, the variable index is incread
      }


      if (var == 1) {    // variable index one is used for base
        PID_KStr[1] = PID_KStr[1] + c[i];    // characters are added as a string to represent base value
      }
      if (var == 2) { ///ect....
        PID_KStr[2] = PID_KStr[2] + c[i];
      }
      if (var == 3) {   // ect...
        PID_KStr[3] = PID_KStr[3] + c[i];
      }
      if (var == 4) { ///ect....
        PID_KStr[4] = PID_KStr[4] + c[i];
      }
      if (var == 5) { ///ect....
        PID_KStr[5] = PID_KStr[5] + c[i];
      }
      if (var == 6) { ///ect....
        PID_KStr[6] = PID_KStr[6] + c[i];
      }
      if (var == 7) { ///ect....
        PID_KStr[7] = PID_KStr[7] + c[i];
      }

    }

    K_Vals[1] = PID_KStr[1].toInt(); // motor ID
    K_Vals[2] = PID_KStr[2].toInt();
    K_Vals[3] = PID_KStr[3].toInt();
    K_Vals[4] = PID_KStr[4].toInt();
    K_Vals[5] = PID_KStr[5].toInt();
    K_Vals[6] = PID_KStr[6].toInt();
    K_Vals[7] = PID_KStr[7].toInt();

    var = 0;
    /// mot Id, PosKp Ki, Sp Kp Ki, Cu Kp Ki



    for (int i = 1; i < 8; i++)
    {
      Serial.print(i);
      Serial.print(" ");
      Serial.println(K_Vals[i]);

    }



  }  //
  Kbd_Str = "  ";  // reseting the incoming string
}

bool Read_All_Enc(void *)   // this is for repeat reading
{ // The EncPair_increment comes from the function above

  DataSplit_PID();

  return true;

}

Loose the String class - it will only lead to headaches.
Read Robin2's great tutorial Serial Basic Inputs to learn how to to it well.

Hi LaptopHead,

I'm pretty new to c++ and I'm examining the PString-library.
The PString-library avoids memory-overflow which could be caused by the String-class over time
This link explains why
the-evils-of-arduino-strings/

I'm currently working on a ini-string-parser
that shows the use of PStrings

#include <PString.h>

/* the library PString offers convenient string-assignment combined with
Runtime safety
PStrings do not “own” their own buffers. 
Instead, they rely on pre-allocated static buffers 
that are passed in at the point of construction. 
PStrings never allocate memory dynamically, even when the result of a print(), 
assignment, or concatenation operation would seem to exceed the current buffer’s size. 
In these cases, the excess data is simply discarded and the string correctly terminated.

Because of these constraints, PStrings can make three key guarantees:
1. They will never cause a buffer overflow
2. A string’s buffer will always be valid memory, i.e. the original buffer
3. buffers will always contain valid (i.e. NULL-terminated) C string data.
*/

// the code below is an example how strings in a style of Window *.ini-files
// can be parsed to extract the Identifier and the value
// example MyIdentifier=1234567890

//my personal naming-convention suffix "_AoC" indicates a variable of type ArrayOfChar
// suffix _PS  indicates an object ("variable") of type PString
char    TextLine_AoC[81] = " "; 
PString TextLine_PS(TextLine_AoC, sizeof(TextLine_AoC));

char    ID_AoC[81] = " ";
PString ID_PS(ID_AoC, sizeof(ID_AoC));

char    Value_AoC[81] = " ";
PString Value_PS(Value_AoC, sizeof(Value_AoC));

char    Separator_AoC[5] = "<=>>";
PString Separator_PS(Separator_AoC, sizeof(Separator_AoC));


// my personal naming-convention parameter of functions start with prefix "p_"
void ExtractUntilSeparator(char* p_PointerToTarget, char* p_PointerToSeparator, char* p_PointerToSource)
{
  Serial.println("entering ExtractUntilSeparator");
  
  // function strstr delivers a pointer to that byte in memory where the delimiter-string begins
  // Substracting the pointer to that byte where the source-string begins gives the position 
  // of the delimiter-string relative to the first character of the source-string. 
  // Adding 1 is the offset-correction because the array begins at zero
  unsigned int LengthUntilDelimiter = strstr(p_PointerToSource,p_PointerToSeparator) - p_PointerToSource + 1;

  // copy a number of characters from Source-string into target-string
  // therefore the pointers of these strings and the number of bytes 
  // is handed over to function strlcpy  (str)ing-of-certain-l)ength-is-copyed)
  strlcpy(p_PointerToTarget,p_PointerToSource,LengthUntilDelimiter);

  Serial.print("p_PointerToSource:>#");
  Serial.print(p_PointerToSource);
  Serial.println("#");

  Serial.print("p_PointerToTarget:>#");
  Serial.print(p_PointerToTarget);
  Serial.println("#");
  
  Serial.print("p_PointerToSeparator:>#");
  Serial.print(p_PointerToSeparator);
  Serial.println("#");
  
  Serial.println("leaving ExtractUntilSeparator");
}

// my personal naming-convention parameter of functions start with "p_"
void ExtractValueBehindSeparator(char* p_PointerToTarget, char* p_PointerToSeparator, char* p_PointerToSource)
{
  Serial.println("entering ExtractValueBehindSeparator");
  
  // function strstr delivers a pointer to that byte in memory where the delimiter-string begins
  // Substracting the pointer to that byte where the source-string begins gives the position 
  // of the delimiter-string relative to the first character of the source-string. 
  // Adding the length of the delimiter-string gives the position of that byte where the rest of the source-string
  // BEHIND the delimiter begins
  unsigned int PosOfSeparatorEnd = strstr(p_PointerToSource,p_PointerToSeparator) - p_PointerToSource + strlen(p_PointerToSeparator);
  // if separatorstring was  found   
  if (PosOfSeparatorEnd < strlen(p_PointerToSource) )
  {
    Serial.print("PosOfSeparatorEnd:>#");
    Serial.print(PosOfSeparatorEnd);
    Serial.println("#");
    unsigned int NoOfBytesUntilEoString = strlen (p_PointerToSource) - PosOfSeparatorEnd + 1; 
    
    // copy a number of characters from Source-string into target-string
    // therefore the pointers of these strings and the number of bytes is handed over to function strlcpy  
    strlcpy(p_PointerToTarget, p_PointerToSource + PosOfSeparatorEnd, NoOfBytesUntilEoString);
  }
  else 
  { 
    p_PointerToTarget = ""; // if no separator was found there is nothing behind the separator
  }

  Serial.print("p_PointerToSource:>#");
  Serial.print(p_PointerToSource);
  Serial.println("#");

  Serial.print("p_PointerToTarget:>#");
  Serial.print(p_PointerToTarget);
  Serial.println("#");
  
  Serial.print("p_PointerToSeparator:>#");
  Serial.print(p_PointerToSeparator);
  Serial.println("#");
  
  Serial.println("leaving ExtractValueBehindSeparator");
}


void setup() 
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("setup-Start");

  TextLine_PS = "MyIDentifierForTesting=123456789012345678901234567890"; 
  //TextLine_PS = "MyID=1234567890"; 
  
  Separator_PS = "=";

  ExtractUntilSeparator(ID_AoC, Separator_AoC, TextLine_AoC);
  Serial.print("ID_PS:>#");
  Serial.print(ID_PS);
  Serial.println("#");

  ExtractValueBehindSeparator(Value_AoC, Separator_AoC, TextLine_AoC);
  Serial.print("Value_PS:>#");
  Serial.print(Value_PS);
  Serial.println("#");

}

void loop() {
  // put your main code here, to run repeatedly:

}

best regards

Stefan

Thank you ,
I was not aware of the evils of the String.

However I discovered that if I don't use the Timer.h and use an old fashion delay with mills,
I can execute my functions well.

 if(millis() - previousMillis > 3) {
    // save the last time you blinked the LED 
      previousMillis = millis();
    DataSplit_PID();
     
    //Serial.println(previousMillis);
  }


  if (Serial.available()) {
    Kbd_Str = Serial.readStringUntil('\n');
    //Serial.println(Kbd_Str);
    //DataSplit_PID();  // this works

  }

Stefan,
I wish your code would show how to receive a string from serial.

BLH
I ended up using the Example 5 from your link and it works well, thank you, Life saver

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, " ");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[1] = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[2] = atoi(strtokIndx);     // convert this part to an integer
  
    strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[3] = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[4] = atoi(strtokIndx);     // convert this part to an integer

  
  strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[5] = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[6] = atoi(strtokIndx);     // convert this part to an integer
  
    strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[7] = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
  K_Vals[8] = atoi(strtokIndx);     // convert this part to an integer

  // strtokIndx = strtok(NULL, " ");
  // floatFromPC = atof(strtokIndx);     // convert this part to a float

}