Weird ÿ symbol in Serial iput.

I have written the below program to receive text messages and interpret them. I only have 4 possible messages for it to interpret. <on##.##> The last one is giving me troubles. This section of my code starts with void evaluate(). For some reason when I text it something like <on12.65> I get the following result outputted to my serial monitor.

First Char
<
Second Char
o
Third Char
n
Fourth Char
1
Fifth Char
2
Sixth Char
.
Seventh Char
5
Eighth Char
6
Ninth Char
ÿ

Obviously my code is looking to receive > on the ninth character but this stupid ÿ symbol comes across. WHY? and how to I fix it? When I type in or or it works perfectly. Also this ÿ thing stops my program from receiving any more text messages.

Thanks for your help in advance.
Jake

[b]void evaluate()
  {
    static char input_line [4];
    inchar=SIM900.read();  //First char
    Serial.println("First Char");
    Serial.println(inchar);
    if (inchar=='<')
    {
        inchar=SIM900.read(); //Second char
        Serial.println("Second Char");
        Serial.println(inchar);
      if (inchar=='o')
      {
          inchar=SIM900.read();  //Third char
          Serial.println("Third Char");
          Serial.println(inchar);
        if (inchar=='n')
        {
            inchar=SIM900.read();  //fourth char
            Serial.println("Fourth Char");
            Serial.println(inchar);
          if (inchar=='>')
           {
             conditional=LOW;
             digitalWrite(led, HIGH);
              textForSMS = "Device Turned On";
               sendSMS(textForSMS);
           }
          else if (inchar=='1' || inchar=='2' || inchar=='3' || inchar=='4' || inchar=='5'|| inchar=='6'|| inchar=='7'|| inchar=='8'|| inchar=='9'|| inchar=='0')
          {
              input_line [1]=inchar;
              inchar=SIM900.read();  //fifth char
              Serial.println("Fifth Char");
              Serial.println(inchar);

            if(inchar=='1' || inchar=='2' || inchar=='3' || inchar=='4' || inchar=='5'|| inchar=='6'|| inchar=='7'|| inchar=='8'|| inchar=='9'|| inchar=='0')
            {
                input_line [2]=inchar;
                inchar=SIM900.read();  //sixth char
                Serial.println("Sixth Char");
                Serial.println(inchar);
              if (inchar='.')
              {
                  inchar=SIM900.read();  //seventh char
                  Serial.println("Seventh Char");
                  Serial.println(inchar);             
                if(inchar=='1' || inchar=='2' || inchar=='3' || inchar=='4' || inchar=='5'|| inchar=='6'|| inchar=='7'|| inchar=='8'|| inchar=='9'|| inchar=='0')
                {
                    input_line [3]=inchar;
                    inchar=SIM900.read();  //eighth char
                    Serial.println("Eighth Char");
                    Serial.println(inchar);

                  if(inchar=='1' || inchar=='2' || inchar=='3' || inchar=='4' || inchar=='5'|| inchar=='6'|| inchar=='7'|| inchar=='8'|| inchar=='9'|| inchar=='0')
                  {
                      input_line [4]=inchar;
                      inchar=SIM900.read();//ninth char
                      Serial.println("Ninth Char");
                      Serial.println(inchar);


                    if (inchar=='>')
                    {
                      
                      inchar=SIM900.read();//tenth
                      Serial.println("Tenth Char");
                      Serial.println(inchar);
                      digitalWrite(led, HIGH);
                      int val = (input_line [1]-'0')*1000+(input_line [2]-'0')*100+(input_line [3]-'0')*10+(input_line [4]-'0')*1;
                      Serial.println(val);
                      time(val);[/b]
                     
                    }
                    
                  }
                }
              }
            } 
          }
        }
        
  }
void loop(void) 
{


  if(SIM900.available() >0) evaluate();

The y with the two dots isn't stupid. Reading from a serial port without checking to see if there is anything to read is.

PaulS:
The y with the two dots isn't stupid. Reading from a serial port without checking to see if there is anything to read is.

Good point... so are you suggesting that I add to each if statement && SIM900.available() >0 ????

This is code I use to read packets delimited by < and >, as yours are. It is reading from Serial, but the same principles apply to other Stream subclasses.

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

PaulS:
This is code I use to read packets delimited by < and >, as yours are. It is reading from Serial, but the same principles apply to other Stream subclasses.

Paul,

If I am understanding your code correctly I think it will work perfectly. If you don't mind let me see if I understand it. What you are doing is basically creating an array called inData and inputting all the serial into it assuming that the index is less than 79. Now if within the serial input you happen to receive a < you will reset the index to be 0 and start reading in the data. If within 79 characters you receive a > your data will be processed. So I would simply evaluate each position in the array (i.e.) if (inData [1] == 'o' && inData [2] == 'n') (for " on") then..do something.. Is that right?

Forgive my ignorance but what is the purpose of the '\0' ? Google calls it a stack overflow character. What does it do here?

If I am not mistaken if I were to receive a < then 1000 characters and then receive a > it would try and evaluate whatever was stored inside that array. Could I put in the else if (inChar == EOP && index < 79). That way it would only try and evaluate it if it received a < and a > within that 80 character allotment?

Thanks again for your help!
Jake

There is probably no real reason to have a start character for the data. The coding is a bit simpler using a single end of data delimiter.

zoomkat:
There is probably no real reason to have a start character for the data. The coding is a bit simpler using a single end of data delimiter.

Wait without a start character how will the code know when to start recording the data in the array? Or is there someway to magically read back a couple characters for your end character? The problem is that with the SMS there is a ton of other characters that come in before my input. Can you get around that your way?

So I would simply evaluate each position in the array (i.e.) if (inData [1] == 'o' && inData [2] == 'n') (for " on") then..do something.. Is that right?

Look up strncmp(). Much more understandable asking if the array starts with "on".

Forgive my ignorance but what is the purpose of the '\0' ? Google calls it a stack overflow character. What does it do here?

In C, a string is a NULL terminated array of chars. inData is an array of chars. '\0' is a NULL.

If I am not mistaken if I were to receive a < then 1000 characters and then receive a > it would try and evaluate whatever was stored inside that array. Could I put in the else if (inChar == EOP && index < 79). That way it would only try and evaluate it if it received a < and a > within that 80 character allotment?

If you were to send a '<' followed by 1000 characters followed by a '>', the first 79 characters would be stored in the array. The other 921 would hit the bit bucket.

You don't need to test for (and don't want to) inChar equal EOP and index less then 79. You still want to recognize the EOP marker when it (finally) arrives.

Hey thanks everybody for the input my code is working nice and I learned a lot tonight.

Problem Resolved!
Jake

PaulS:
This is code I use to read packets delimited by < and >, as yours are. It is reading from Serial, but the same principles apply to other Stream subclasses.

#define SOP '<'

#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
  Serial.begin(57600);
  // Other stuff...
}

void loop()
{
 // Read all serial data available, as fast as possible
 while(Serial.available() > 0)
 {
   char inChar = Serial.read();
   if(inChar == SOP)
   {
      index = 0;
      inData[index] = '\0';
      started = true;
      ended = false;
   }
   else if(inChar == EOP)
   {
      ended = true;
      break;
   }
   else
   {
     if(index < 79)
     {
       inData[index] = inChar;
       index++;
       inData[index] = '\0';
     }
   }
 }

// We are here either because all pending serial
 // data has been read OR because an end of
 // packet marker arrived. Which is it?
 if(started && ended)
 {
   // The end of packet marker arrived. Process the packet

// Reset for the next packet
   started = false;
   ended = false;
   index = 0;
   inData[index] = '\0';
 }
}

Paul and whom ever else can help me,

I tried to expand your above mentioned code to aid me in overcoming another issue. The serial output that gets sent to the arduino by my gsm shield looks like this.

+CMT: "+18014145218","","14/01/18,15:09:14-28"

To remind you before I only cared about capturing the portion between the <> but I have also now realized that I need to capture the phone number between the + and the " so that I can send a reply back to the phone number advising them as to what events took place due to their text. Okay seems simple enough all I needed to do was modify your code to read another part of the serial input as well. I tried doing just that and thankfully it can grab the phone number quite nicely. Sadly it is now having issues grabbing the correct information between the <>. (it doesn't grab the o or the n it seems to grab part of the phone number.??) If you can see what might be causing this problem and help me learn how to fix it that would be very helpful.

Thanks for everything.
Jake

{#include <SoftwareSerial.h> 
char inchar; // Will hold the incoming character from the GSM shield
SoftwareSerial SIM900(7, 8);
#define SOP '<'
#define EOP '>'
#define STPHNUM '+'
#define ENDPHNUM '"'

int led = 13;
bool started = false;
bool ended = false;
bool PhNumStarted = false;
bool PhNumEnded = false;
char inData[15];
char phNumber[15];
byte index;
byte index2;
int clearcounter=0;

void loop(void)
  //If a character comes in from the cellular module...
  // Read all serial data available, as fast as possible
  while(SIM900.available() > 0)
  {
    char inChar = SIM900.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       index=index+1;
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else if(inChar == STPHNUM)
    {
      index2 = 0;
      phNumber[index2] = '\0';
      index2=index2+1;
      PhNumStarted = true;
      PhNumEnded = false;
    }
    else if(inChar == ENDPHNUM)
    {
      PhNumEnded = true;
      //break;
    }
    else
    {
      if(index < 14 || index2 < 14)
      {
        inData[index] = inChar;
        index++;
        phNumber[index2] = inChar;
        index2++;
        inData[index] = '\0';
        phNumber[index2] = '\0';
        clearcounter=clearcounter+1;
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(PhNumStarted && PhNumEnded)
  {
    Serial.print(phNumber[1]);
    Serial.print(phNumber[2]);
    Serial.print(phNumber[3]);
    Serial.print(phNumber[4]);
    Serial.print(phNumber[5]);
    Serial.print(phNumber[6]);
    Serial.print(phNumber[7]);
    Serial.print(phNumber[8]);
    Serial.print(phNumber[9]);
    Serial.print(phNumber[10]);
    Serial.print(phNumber[12]);
    Serial.print(phNumber[13]);
    Serial.print(phNumber[14]);
    Serial.println(phNumber[15]);
    PhNumStarted = false;
    PhNumEnded = false;
    index2 = 0;
    phNumber[index2] = '\0';
  }
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
    evaluate(inData);
  }
 }

You seem to be writing a '\0' into the first ( zeroth ) element of the phone number array, and then filling in the characters of the phone number after that, and then putting another '\0' at the end.

If you do this, and then try and print the array later, it will see the '\0' at the first element and therefore assume that there is nothing in the string.

Basic code to capture the data string being sent. Test by copy/paste the data string in the serial monitor and send.

//zoomkat 3-5-12 simple delimited '>' string  
//from serial port input (via serial monitor)
//and print result out serial port

String readString, substring;
int loc; 

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

void loop() {

  //expected string:  +CMT: "+18014145218","","14/01/18,15:09:14-28"<on>

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    //if (c == '\n') {  //looks for end of data packet marker

    if (c == '>') {
      Serial.print("readString is: ");
      Serial.println(readString); //prints string to serial port out
      //do stuff      
      loc = readString.indexOf("<");
      //Serial.println(loc);
      substring = readString.substring(loc+1, loc+4);
      Serial.print("status is: ");
      Serial.println(substring);

      loc = readString.indexOf("CC");
      //Serial.println(loc);
      substring = readString.substring(8, 19);
      Serial.print("phone # is: ");
      Serial.println(substring);

      readString=""; //clears variable for new input
      substring=""; 

    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

zoomkat:
Basic code to capture the data string being sent. Test by copy/paste the data string in the serial monitor and send.

Zoomkat,

I tested your code as you suggested and it seems to kick butt. I only have one concern. Often times I need to take my text input and take integers out of them. For example one of my commands is <##.##> on (ie 12.75on) I previously liked the character array just because I could capture each digit and do what I wanted with it. For example I could take 12.75on and convert it to 1275 and then convert that number to a set amount of time that the device should be on. (12.65 hours) Also I probably will need to convert the phone number to an integer. I think I should be able to do this with a toInt() command but with the 12.75on I think that the integer conversion will promptly stop as soon as it hits the decimal. Also this string could have 9999 possibilities which makes a string comparison very difficult. I like the string way because I can simply do a string comparison, as seen in my code if(substring == "on") , vs an individual character comparison. I am willing to learn more about strings please help me know where I need to go from here.

All commands to be given



<##.##on>
maybe , ,

//zoomkat 3-5-12 simple delimited '>' string  
//from serial port input (via serial monitor)
//and print result out serial port

String readString, substring;
int loc; 

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

void loop() {

  //expected string:  +CMT: "+18014145218","","14/01/18,15:09:14-28"<on>

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    //if (c == '\n') {  //looks for end of data packet marker

    if (c == '>') {
      Serial.print("readString is: ");
      Serial.println(readString); //prints string to serial port out
      //do stuff      
      loc = readString.indexOf("<");
      //Serial.println(loc);
      substring = readString.substring(loc+1, loc+8);
      Serial.print("status is: ");
      Serial.println(substring);
      if(substring == "on") Serial.println("sweet this might work!");
      if(substring == "off") Serial.println("Okay now what?");

      loc = readString.indexOf("CC");
      //Serial.println(loc);
      substring = readString.substring(8, 19);
      Serial.print("phone # is: ");
      Serial.println(substring);

      readString=""; //clears variable for new input
      substring=""; 

    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

Note that there is a difference between a String and a c-string. The below link has the String functions with examples. You will need develop parsing methods for the data format you decide to use.

You have two things, mutually exclusive, that can start the capture of data - SOP and STPHNUM (which I would have called SON, start of number, because I like symmetry and short names). You have two things, mutually exclusive, that can end the capture of data - EOP and ENDPHNUM.

Which one triggers the start of capture and which one ends the capture matters only to the extent that they define whether the captured stuff is data or a phone number.

So, create a boolean variable, isPhoneNumber. Set it to true if the character is SON and false if the character is SOP. Use started and ended and inData for both cases to know that capture has started and has ended, and to hold the data.

Then, in the if(started && ended) block, use isPhoneNumber to decide what to do with what is in inData.

No need to use Strings at all.