Receiving serial data as string?

So I have a mega2560 connected with a pump that communicated via serial, so I am using Serial for computer and Serial1 for pump. The "PIN_STOP" will trigger the pump to stop and then the "Serial1.println("/1?29");" tells the pump to send back the position of the pump. I am using the MultiSerialMega code as well to see what is going on via Serial Monitor.

This is what is expected to be returned, where 4522 is the value that I am looking for.

/
0
@
4
5
2
2

y

With the current sketch this is what I am actually getting using MultiSerialMega. The DEC value for "/" is 47 so I am guessing that is where that came from. Without the MultiSerialMega code I end up getting "47" for pump_return.

47
0
@
4
5
2
2

y
if (fluid == true){
  if (frequency >= 6000){                        //Number will change after calibration
  Serial.println("stop");
  digitalWrite(PIN_STOP, LOW);                     // Stop syringe
  analogWrite(BLUE_LED, 0);                     //Turn off LED
  digitalWrite(SENSOR_ON, LOW);                    //Turn sensor off
  fluid=false;
  lcd.clear();
  selected = false;                                //Go to main menu
  Serial1.println("/1?29");                           // Querry syringe position
  if (Serial1.available()){
    pump_return = Serial1.read();
    Serial.println(pump_return);

What I really need is a way to receive the 4522 value and set it to "pump_return" to be used for other purposes. I am guessing I need to receive some type of string? Maybe use a modified version of this http://arduino.cc/en/Tutorial/SerialEvent

http://snippets-r-us.com might be able to help you with the snippets. From what you posted, we can't see the type of pump_return.

I am guessing I need to receive some type of string?

Yes. You need to store each character received in an array, followed by a NULL. When the end of packet marker arrives, or the correct number of characters for a packet, then you can parse the string to get the data that you want.

Here is a description of the response from the pump.

The http://snippets-r-us.com link does not work for me. Thanks

Byte#      Description           ASCII           Hex
1          Start Character          /            2F
2          Controller Address       0            30
3          Status Byte              @ or '
4 to N     Response
N+1      End of Text              <ETX>          03
N+2      Carriage Return         <CR>            0D
N+3      Line Feed                 <LF>          0A
N+4      End (Blank)               <Blank>       FF
Explanation of bytes:
Byte 1: The starting character, 2F hex, which signals the beginning of a new
packet, is the front slash character "/" on a computer keyboard,.
Byte 2: The host address, 30 hex (ASCII 0), is the address number for the
host computer.
Byte 3: The status and error byte describes the device status. This can be either
@ for busy or ' for not busy.
Byte 4: There may or may not be response byte(s) for a command. In
general, all query commands, "read an input value" commands, and
configuration query commands (~A, ~B, ~P, ~V, etc) cause response
bytes. Other commands do not cause a response. This is where the value 4522 is.
Byte 4+n: The end-of-response mark is 03 hex.
Byte 4+n+1: Carriage return is 0D hex.
Byte 4+n+2: End of packet character is the line feed character, 0A hex.
Byte 4+n+3: The extra ending character, FF hex, is an extra character to ensure
the packet is properly sent. This character might not be displayed by
the host terminal.

The http://snippets-r-us.com link does not work for me.

Or anybody else. That's a clue. Glad you tripped over it.

Very simple delimited serial capture code. You show that at the end of the data string you receive there is a "y". You could try using a "y" instead of the comma "," used in the code and see if you capture your basic String.

//zoomkat 3-5-12 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,
  
  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      //do stuff
      Serial.println(readString); //prints string to serial port out
      readString=""; //clears variable for new input      
     }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

zoomkat:
Very simple delimited serial capture code. You show that at the end of the data string you receive there is a "y". You could try using a "y" instead of the comma "," used in the code and see if you capture your basic String.

Well I tried this code but it did not really work for me. I am still really new to arduino and I tried a few characters in for "," but didn't really get anything. Since I really didn't know much about strings, I decided to start reading lots of other threads to learn more about them. I ended up finding another code that you posted in another thread that I was able to modify to get what I needed.
http://forum.arduino.cc/index.php?topic=71590.0

I didn't know that substring existed and also would have no clue how to convert the characters into numbers without your sketch so thanks alot.

String content = "";
  char character;

  while(Serial1.available()) {
      character = Serial1.read();
      content.concat(character);
  }
  if (content != "") {
    preturn = content.substring(24, 30);
    Serial.println(preturn);
    
    char carray1[6];                    //magic needed to convert string to a number 
      preturn.toCharArray(carray1, sizeof(carray1));
      pump_return = atoi(carray1);
     Serial.println(pump_return);
    Alk_value = (((4800-pump_return)*0.00020833)*0.1*50000)/2;
content="";
preturn="";
}

I didn't know that substring existed and also would have no clue how to convert the characters into numbers without your sketch so thanks a lot.

Below is where you can get more info on various String (note the capital S) functions. The code below shows how to convert a character String to an integer number using the function int value = inString.toInt();

// Serial Servo Tester 10/28/11
// Use the Serial Monitor to write a value from 0 to 180
// Set Serial Monitor line ending to Newline
// for writeMicroseconds, use values from  544 to 2400

#include <Servo.h> 

Servo myservo;  // create servo object to control a servo 
String inString;

void setup()
{
  Serial.begin(9600);
  myservo.attach(9);  //the pin for the servo control 
  Serial.println("Enter angle between 0 and 180 (values > 544 written as Microseconds)");  
}

void loop() {

  while (Serial.available()> 0) {
    int inChar = Serial.read();
    if (isDigit(inChar)) 
    {
      // if the incoming character is a digit, add it to the string
      inString += (char)inChar; 
    }
    else
    {
      // here on the first character that is not a digit   
      int value = inString.toInt(); 
      if(value >= 544)
      {
        Serial.print("writing Microseconds: ");
        Serial.println(value);
        myservo.writeMicroseconds(value);
      }
      else
      {   
        Serial.print("writing Angle: ");
        Serial.println(value);
        myservo.write(value);
      }
      // clear the string for new input:
      inString = "";   
    }
  }
}

Fieroguy19:
So I have a mega2560 connected with a pump that communicated via serial, so I am using Serial for computer and Serial1 for pump. The "PIN_STOP" will trigger the pump to stop and then the "Serial1.println("/1?29");" tells the pump to send back the position of the pump. I am using the MultiSerialMega code as well to see what is going on via Serial Monitor.

This is what is expected to be returned, where 4522 is the value that I am looking for.

/

0
@
4
5
2
2

y




With the current sketch this is what I am actually getting using MultiSerialMega. The DEC value for "/" is 47 so I am guessing that is where that came from. Without the MultiSerialMega code I end up getting "47" for pump_return.


47
0
@
4
5
2
2

y






if (fluid == true){
  if (frequency >= 6000){                        //Number will change after calibration
  Serial.println("stop");
  digitalWrite(PIN_STOP, LOW);                     // Stop syringe
  analogWrite(BLUE_LED, 0);                     //Turn off LED
  digitalWrite(SENSOR_ON, LOW);                    //Turn sensor off
  fluid=false;
  lcd.clear();
  selected = false;                                //Go to main menu
  Serial1.println("/1?29");                           // Querry syringe position
  if (Serial1.available()){
    pump_return = Serial1.read();
    Serial.println(pump_return);




What I really need is a way to receive the 4522 value and set it to "pump_return" to be used for other purposes. I am guessing I need to receive some type of string? Maybe use a modified version of this http://arduino.cc/en/Tutorial/SerialEvent

You don't really need to make a string and use a function to turn that into a number.

serial inputs 4-5-2-2

start off with a variable to hold your number and another to hold the serial entry
int value = 0;
char serIn;

1st I get '4' (ASCII 52) into serIn and have already checked it is >= '0' and <= '9'
// serIn == '4'
value = value * 10 + serIn - '0'; // value == 4
// serIn == '5'
value = value * 10 + serIn - '0'; // value == 45
// serIn == '2'
value = value * 10 + serIn - '0'; // value == 452
// serIn == '2'
value = value * 10 + serIn - '0'; // value == 4522

We could pack the whole thing into a loop that waits for each character to arrive but we already have loop() going and may want to do other things at the same time.

There is a method called Finite State Machine where you use a variable to keep track of the process going on and use that to determine which code to respond to changes, in this case the serial data.

Using the pump code doc, the initial state would look for '/' and reject all else. Once it finds '/' the state changes. You write a separate section of state code for each operation you need along the way. The states do not have to be 0-1-2-3-... they can be 10-20-21-22-30-etc so that printing out the state value at the start of loop() can tell you at a glance what your process is doing.

For serial processing, put your state machine inside a switch-case block inside an if block:
if ( Serial.available())
{
switch ( state )
{
case 0 : // looking for message start
{
if ( serIn == '/' ) state = 10;
}
break;

case 10 : // here we go
{
// more code
}
break;

// more cases

default : // all errors go here
{
// print or whatever your error indications
state = 0;
}
}
}

All that fits in loop() and only runs when a serial character arrives.

You can have different processes with different state variables "running at the same time" if your MCU is doing more than just communication with the pump. One thing that I do is have led 13 blink 1 second on, 1 second off as a yup it's still running indicator.

Dealing with the pump codes is moderately difficult. Just be happy it's logical. But do not expect that serial data will all always arrive uncorrupted. Maybe it will but if your code does not deal with errors then every error will be a bad one.

Byte# Description ASCII Hex
1 Start Character / 2F
2 Controller Address 0 30
3 Status Byte @ or '
4 to N Response
N+1 End of Text 03
N+2 Carriage Return 0D
N+3 Line Feed 0A
N+4 End (Blank) FF
Explanation of bytes:
Byte 1: The starting character, 2F hex, which signals the beginning of a new
packet, is the front slash character "/" on a computer keyboard,.
Byte 2: The host address, 30 hex (ASCII 0), is the address number for the
host computer.
Byte 3: The status and error byte describes the device status. This can be either
@ for busy or ' for not busy.
Byte 4: There may or may not be response byte(s) for a command. In
general, all query commands, "read an input value" commands, and
configuration query commands (~A, ~B, ~P, ~V, etc) cause response
bytes. Other commands do not cause a response. This is where the value 4522 is.
Byte 4+n: The end-of-response mark is 03 hex.
Byte 4+n+1: Carriage return is 0D hex.
Byte 4+n+2: End of packet character is the line feed character, 0A hex.
Byte 4+n+3: The extra ending character, FF hex, is an extra character to ensure
the packet is properly sent. This character might not be displayed by
the host terminal.

zoomkat:
Very simple delimited serial capture code. You show that at the end of the data string you receive there is a "y". You could try using a "y" instead of the comma "," used in the code

I suspect the trailing "y" is actually the 0xFF which is the last byte in the response and would be rendered by the serial monitor as ÿ. In that case it would be reasonable to use the 0xFF byte as the end-of-message marker.

One could use something like below to see just what is the last byte being sent.

byte INFO;

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

void loop ()
{
  if(Serial.available ())  
  {
    INFO = Serial.read();
    Serial.println(INFO, DEC);
    Serial.println(INFO, HEX);
    Serial.println();
  }
}

But print a space or other separator between the DEC and HEX to make it easier to read.

GoForSmoke:
But print a space or other separator between the DEC and HEX to make it easier to read.

Or just chose one that is easiest for you to recognize.

I prefer HEX with leading zeroes and a space, rarely do I look at just one serial char per line especially when I'm looking for patterns in data.

zoomkat:
One could use something like below to see just what is the last byte being sent.

One could, but the documentation states that the last byte is 0xFF and we already know that this is rendered as ÿ in the serial monitor, so I don't see any reason to doubt that this is the value being received.