Need help with Strings.

Hello everyone. I am having trouble with String manipulation / extraction in my program. I would like to use charAt(n), or substring(n,n) to access certain characters in a string. Everything compiles fine but results are not what I expect. I either get the whole string back, or nothing at all. Even when I use string.length(), I get 111111111. Here is what I use. At the beginning I initialize my sting variable. Further down in the void loop section I have a char type variable getting Serial.read(). Then I convert it to a string by using the String variable initialized earlier with +=, then the char that got the read from the serial. If I tell it to serial print the String variable, it shows it fine. If I try extracting certain parts of the string, it fails. Can anyone shed some light? Your helpful and considerate response will be greatly appreciated and my thanks in advance. Please let me know if you need more info. I will respond A.S.A.P.

Read http://forum.arduino.cc//index.php?topic=97455.0 then post some working code that shows the problem.

Can anyone shed some light?

Sure. Don't use Strings. Strings are for people too lazy to learn to use strings (aka NULL terminated arrays of chars).

PaulS:

Can anyone shed some light?

Sure. Don't use Strings. Strings are for people too lazy to learn to use strings (aka NULL terminated arrays of chars).

Well, code has to be posted for any useful help. Also be aware that using Strings grinds a broomstick in certain peoples *ss.

instead of just saying "don't use String object" , it may help to tell why ;)

have a look at this link, and make your decision http://miscsolutions.wordpress.com/2011/10/16/five-things-i-never-use-in-arduino-projects/

The problem is that String operations allocate memory dynamically and in ways that are hard to predict when the inputs to the program are variable, combined with the fact that Arduinos have a very limited amount of RAM (2K on the Arduino Uno)....... ....... .....

if you still want to use it, and need help, yes, post your code here between code tags, please :)

Thank you everyone who responded to my post. It sounds like I should be using chars instead of Strings. I am trying to read 2 rotary encoders and write motor commands to the Arduino mega 2560. The code is in it’s early development stage and in testing. Then encoder reading works great. Receiving the motor command codes into a String variable is the issue. Please review the code below. Go easy on me please. I am very new to this.

/* Encoder Library - TwoKnobs Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>
String readString;
String block;

// Change these pin numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder knobLeft(5, 6);
Encoder knobRight(7, 8);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(9600);
   
pinMode(12,OUTPUT); //Initiates Motor Channel A pin
pinMode(9,OUTPUT); //Initiates Brake Channel A pin
pinMode(3,INPUT);//PWM for Motor Ch. A
digitalWrite(9, HIGH);//Engage the motor brake
}

long positionLeft  = -999;
long positionRight = -999;

void loop() {
  long newLeft, newRight;
  newLeft = knobLeft.read();
  newRight = knobRight.read();
  if (newLeft != positionLeft || newRight != positionRight) {
    Serial.print("Left = ");
    Serial.print(newLeft);
    Serial.print(", Right = ");
    Serial.print(newRight);
    Serial.println();
    positionLeft = newLeft;
    positionRight = newRight;
  }

   //============== MOTOR ROUTINES START HERE ===============
// THIS IS THE CODE THAT IS GIVING ME PROBLEMS...... 
while (Serial.available()>0)
{
char val = Serial.read();//Works ok here. 
readString += val;//Assign char val to String initialized readString. Seems to work ok here.
block = (readString.substring(3,7));// Fails to show anything when variable 'block' is displayed.
Serial.print(block); //If I ask to see readString, it works find. Hmmm.???

readString = "";
}

} // end of loop

Thank you all again for your patience and understanding. If you recommend working with chars instead of String, then I will look into that and not waste time struggling with String stuff. Best wishes and God bless.

If you recommend working with chars instead of String, then I will look into that and not waste time struggling with String stuff.

Well, I do.

bott17:

/* Encoder Library - TwoKnobs Example

#include <Encoder.h>
String readString;
String block;

// THIS IS THE CODE THAT IS GIVING ME PROBLEMS…
while (Serial.available()>0)
{
char val = Serial.read();//Works ok here.
readString += val;//Assign char val to String initialized readString. Seems to work ok here.
block = (readString.substring(3,7));// Fails to show anything when variable ‘block’ is displayed.
Serial.print(block); //If I ask to see readString, it works find. Hmmm.???

readString = “”;
}

} // end of loop




Thank you all again for your patience and understanding. If you recommend working with chars instead of String, then I will look into that and not waste time struggling with String stuff. Best wishes and God bless.

Yes, I do too :wink:
Anyway, in the while(Serial.available()) loop, there are 2 or 3 things you should be aware of, even if you don’t use String :

  • read your code again… you read 1 char, that you add to an empty string (you delete it at the end of the loop), and you try to read 4 chars in that string that contains only one :wink:
  • you say it prints OK (!?) , but "it fails to show … " where should it be displayed ?
  • where do the serial datas come from ? What strings are supposed to be sent ?

If you work with char arrays, remember that you must not overwrite the terminating null character, and never write any character after it !! You must know how exactly the maximum length of the string, and initialize it correctly .
There is a little description in the Reference part of this site, and a lot of others on the web :wink:

Hello Alnath, and Thank you for your help. I want to send a fixed length string from VB.Net (VB 10) through the serial port to my program. The string I want to communicate to the Arduino IDE is always going to be 10 letters in length. Then, I would like to pick apart the string in the Arduino IDE to command and control 2 DC motors. So basically, I would be sending a string in parallel to the IDE to be de-coded into separate control codes for the motors. Thank again for any and all help. Best wishes.

http://www.gammon.com.au/serial

I was about to post the link Nick has just posted ;) I suggest you read it thoroughly and you come back here with questions...... if any :)

bott17:
Hello Alnath, and Thank you for your help. I want to send a fixed length string from VB.Net (VB 10) through the serial port to my program. The string I want to communicate to the Arduino IDE is always going to be 10 letters in length. Then, I would like to pick apart the string in the Arduino IDE to command and control 2 DC motors. So basically, I would be sending a string in parallel to the IDE to be de-coded into separate control codes for the motors. Thank again for any and all help. Best wishes.

Below is some simple servo test code that might be of use. A string of characters is sent from the serial monitor to the arduino. The arduino captures the characters into a String. Then String functions are used to break the captured String into the two desired Strings and convert the ascii characters in the smaller Strings into numbers for use in controlling two servos.

// zoomkat 11-22-10 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550

#include <Servo.h> 
String readString, servo1, servo2;
Servo myservo1;  // create servo object to control a servo 
Servo myservo2;

void setup() {
  Serial.begin(9600);
  myservo1.attach(6);  //the pin for the servo control 
  myservo2.attach(7);
  Serial.println("servo-test-21"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(2);  
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
      Serial.println(readString); //see what was received
      
      // expect a string like 07002100 containing the two servo positions      
      servo1 = readString.substring(0, 4); //get the first four characters
      servo2 = readString.substring(4, 8); //get the next four characters 
      
      Serial.println(servo1);  //print to serial monitor to see results
      Serial.println(servo2);
      
      myservo1.writeMicroseconds(servo1.toInt()); //set servo position
      myservo2.writeMicroseconds(servo2.toInt());
      
    readString="";
    servo1="";
    servo2="";
  } 
}
  while (Serial.available()) {
    delay(2);  
    if (Serial.available() >0) {

The delay is to give the data time to arrive, right?

http://www.gammon.com.au/serial

The delay is to give the data time to arrive, right?

Yes, as the arduino normally loops much faster than the serial buffer is normally filled. In this case time is used as a delimiter instead of adding an extra character to what ever is being sent from the serial monitor. Simplifies testing of the String functions using the serial monitor.

Thank you Zoomkat and Nick Gammon for your help. My code works great now. That example held the key. I will continue to test it and add to it as I build my project. My project by the way is an X,Y table using parts from a Cricut mini and 2 battery powered screwdrivers (plenty of torque). I will be adding a Z to the table after I get the X and Y operating correctly. It's a low budget project using garage sale bought supplies but that is what makes this project so much fun. I gutted a lot of old printers and scanners for belts, motors, encoders, and gears. I bought a bunch of old printers at an auction and I got busy gutting them. The trash pickup was extra heavy that week. Well, on with the tinkering. Any ideas would be greatly appreciated. Thanks again and best wishes.