Substring command adding extra characters to the end of the string

Hey good morning all,
Quick question about a weird thing I noticed with the substring() function.

I am using an arduino micro hooked up to an LCD screen. When I use the following command:

else if (userInput.startsWith("lcdwrite"))
  {
    Serial.println("Sent " + userInput.substring(9,userInput.length()-2));
    LCD_MoveCursor(0x00);
    LCD_WriteString(userInput.substring(9,userInput.length()-2));
  }

Everything works perfectly. However the original code I was using:

else if (userInput.startsWith("lcdwrite"))
  {
    Serial.println("Sent " + userInput.substring(9));
    LCD_MoveCursor(0x00);
    LCD_WriteString(userInput.substring(9));
  }

adds to weird characters to the end on the LCD screen - one that is just two vertical bars and one that is like an H with a crooked middle line. I could not identify the characters by looking at the ascii chart, but they do not show up when the string is repeated back to the serial monitor screen.

I have looked at the substring documentation but I don’t see anything implying there would be extra characters added behind-the-scenes.

Here’s the relevant code blocks for reference that may help:

#define LCD_SPEED 100000
#define LCD_DATAORDER MSBFIRST
#define LCD_DATAMODE SPI_MODE3

void loop()
{
  if (Serial.available() > 0)
  {
    parseSerialInput(Serial.readString());
  }
}

inline void LCD_WriteString(String text) //using the default send command here would add extra on/off calls, this function is specialized and low-level for speed writing
{
  SPI_Start();

  delayMicroseconds(100);
  int charpos = 0;
  while (charpos < text.length())
  {
    SPI.transfer(text.charAt(charpos));
    charpos++;
    delayMicroseconds(100);
  }
  
  SPI_End();
}
inline void SPI_Start()
{
  digitalWrite(CS_LCD, LOW);
  SPI.beginTransaction(SPISettings(LCD_SPEED, LCD_DATAORDER, LCD_DATAMODE));
  delayMicroseconds(100);
}

inline void SPI_End()
{
  SPI.endTransaction();
  delayMicroseconds(100);
  digitalWrite(CS_LCD, HIGH);
}

Anybody know where these extra characters are coming from?

I'll guess that they are carriage return and line feed.

From the Arduino reference:

substring()

Description
Get a substring of a String. The starting index is inclusive (the corresponding character is included in the substring), but the optional ending index is exclusive (the corresponding character is not included in the substring). If the ending index is omitted, the substring continues to the end of the String.

So, as Wildbill said, if the older version displays weird characters, it means that these characters are present within your String. They must be CR and LF related...

Well I thought about that, but interestingly enough if I do substring(9,string.length()) it still produces the same (bad) result. Does the length include the CR and NL characters? My expectation was that it wouldn't.

Ah, just confirmed with a quick test it does indeed include the CR and NL. Thanks.

else if (userInput.startsWith("length"))
  {
    String l = userInput.substring(7,userInput.length());
    Serial.println("Length is ");
    Serial.println(l.length()); //outputs 2 more characters than you typed
  }

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

...R

Really? :o What is the problem that causes that?

Arduino's string library is very good which is part of the reason I use it. C's default string functionality is less intuitive.

JPlanck:
Really? :o What is the problem that causes that?

Memory gets fragmented and there is no operating system with a garbage collector.

There's a big difference programming for 2k of SRAM instead of 2GB

...R

Ah ok then, I'll have to do a lot of converting but it won't be the end of the world I guess. Better than corrupting the memory I guess :slight_smile:

It depends what you're doing and how important it is. String objects have on occasion been a holy war here, with (a few) participants postulating that they've used Strings many times and never had any issues.

If your sketch does something unimportant and runs for a few hours and you've observed it working correctly on multiple occasions, by all means, accept the risk.

If it's important, and more especially, if you want it to run forever, run screaming from Strings.