Set variable based on SMS string

I’m pretty new to Arduino so pardon my lack of knowledge. I am in the process of building a temp alarm that will send me an SMS when the temp falls below a certain temp. That part is working however I am going to use a smaller portion of code here to work through my next scenario. Now I’m trying to build the ability to send a text to the Arduino with a message like “Tempsetpoint 50” and have it set a variable to 50 that will be used in the other code that I have to alert on any temp below 50. I am building it all into 1 major sketch but building smaller sketch's for testing portions as I go. Below is the start of some code that I have worked up that turns an led on if an SMS with a1 is received and turns the led off if a0 is received.

First problem is how do I replaced ‘a’ with a string of characters like “Tempsetpoint” or maybe I can make it 1 step easier and leave ‘a’ as a single integer and then just have 2 digits for the temp setpoint after ‘a’ set the variables value? Can anyone give me some advice on how to change it from a single digit to a string of 2 digits for the second value and then set a variable?

I am using an Arduino Uno with a Geeetech GSM shield.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 8);

char inchar = 0;
int led1 = 4;

void setup()
{
  pinMode(led1, OUTPUT);
  Serial.begin(19200); // for serial monitor
  mySerial.begin(19200); // for GSM shield
  SIM900power();  // turn on shield
  delay(10000);  // give time to log on to network.

  mySerial.print("AT+CMGF=1\r");  // set SMS mode to text
  delay(100);
  mySerial.print("AT+CNMI=2,2,0,0,0\r");
  // blurt out contents of new SMS upon receipt to the GSM shield's serial out
  delay(100);
}


void loop()
{
  //If a character comes in from the mySerialular module...
  if (mySerial.available() > 0)
  {
    delay(10);
    inchar = mySerial.read();
    if (inchar == 'a')
    {
      delay(10);
      inchar = mySerial.read();
      if (inchar == '0')
      {
        digitalWrite(led1, LOW);
      }
      else if (inchar == '1')
      {
        digitalWrite(led1, HIGH);
      }
      delay(10);
    }
  }
}


void SIM900power()
// Powers on the GSM card
{
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
  delay(1000);
  digitalWrite(9, HIGH);
  delay(2000);
  digitalWrite(9, LOW);
  delay(3000);
}

The way forward would probably to insert the individual characters your receive into a null terminated character array (string), then compare with a known value. Don't be tempted to use the String class, it can cause problems with fragmentation of memory (amongst other things).

Alternatively, save the SMS to memory instead of 'blurting it out', then you can access the whole message in one go.

First problem is how do I replaced 'a' with a string of characters like "Tempsetpoint"

Replace 'a' where? Here?

    if (inchar == 'a')

If that is where you are referring to, you can't. The ONE letter you read won't have a snowball's chance in hell of equaling "Tempsetpoint".

https://forum.arduino.cc/index.php?topic=288234.0

  if (mySerial.available() > 0)
  {
    delay(10);
    inchar = mySerial.read();
    if (inchar == 'a')
    {
      delay(10);
      inchar = mySerial.read();

If there is 1 character toy read, delaying for 20 milliseconds does NOT guarantee that another character will have arrived.

First problem is how do I replaced 'a' with a string of characters like "Tempsetpoint"

You capture the characters into a string of characters that can be evaluated. If the SMS message has some end of text marker, then you probably could use a character capture setup like below.

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

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, I'll just be sending the SMS messages to the Arduino from my cell so they can be formatted anyway.

With the code that I posted above. Is their any easy way to get it so it will accept an SMS something like a50 and have it run that section of code if a comes in and then set a variable if 50 comes in. Even if I had to write if statements for each value after a that I want to expect for 50 such as 50, 55, 60, 65, 70, etc.

Something something like:
if (inchar == 'a')
{
delay(10);
inchar = mySerial.read();
if (inchar == '50')
{
variable = 50
}
if (inchar == '55')
{
variable = 55
}
if (inchar == '60')
{
variable = 60
}

I get an error with having 2 characters in the if (inchar == '60') even if I change it to if (inchar == "60").

SMS something like a50 and have it run that section of code if a comes in and then set a variable if 50 comes in.

Below is some servo control code. The data packet consist of a numeric position value, a servo identifier, and an end of packet marker. This may be similar to what you want to do.

//zoomkat 11-22-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo 

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

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control 
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}
  if (inchar == '50')

Single quotes are for single characters. Please post a picture of your keyboard with the 50 key circled.

Getting to the point, more than one character requires double quotes like below.

if (inchar == "50")

zoomkat:
Getting to the point, more than one character requires double quotes like below.

if (inchar == "50")

Of course, the character in the inchar variable will never match the string "50" even if == was the right operation to perform.

A simple example demonstrating the capture and compare concept.

// zoomkat 8-6-10 serial I/O string test
// type on or off in serial monitor. then send or enter
// for IDE 0019 and later

int ledPin = 13;
String readString;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  Serial.println("serial on/off test 0021"); // so I can keep track
}

void loop() {

  while (Serial.available()) {
    delay(3);  
    char c = Serial.read();
    readString += c; 
  }

  if (readString.length() >0) {
    Serial.println(readString);

    if (readString == "on")     
    {
      digitalWrite(ledPin, HIGH);
      Serial.println("LED ON");
    }
    if (readString == "off")
    {
      digitalWrite(ledPin, LOW);
      Serial.println("LED OFF");
    }
    readString="";
  } 
}

Zoomkat, your example has helped.

I'm now trying to use the string to check if a GSM shield with a SIM900 on it is powered up and responding to AT commands. I'm wanting to send the command AT to the shield and have it return OK and then turn an LED on if it receives OK else turn on a different LED if it doesn't receive OK. Long term the goal would be to send the commands to the GSM shield to power up if an OK isn't returned.

Using the sketch below if I send a "p" through the serial monitor it then runs the GSMCheckpower function and send AT to the GSM card and returns an OK to the serial monitor. When it receives OK back on serial it isn't acting on the OK that it receives and instead completes the else statement and turns on ledPin2 because OK wasn't meet. Any idea what I am missing so it catch's the OK and turn on the ledPin when the GSM shield is on instead of always using the else statement?

#include <SoftwareSerial.h>
#include <String.h>
SoftwareSerial mySerial(52, 53);
String readString;
int ledPin = 41; //Green LED
int ledPin2 = 43; //Red LED

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  mySerial.begin(19200);               // the GPRS baud rate
  Serial.begin(19200);    // the GPRS baud rate
  delay(500);
  mySerial.print("AT+CMGF=1\r"); //Because we want to recieve the SMS in text mode
}
void loop()
{
  if (Serial.available())
    switch (Serial.read())
    {
      case 'p':
        GSMCheckpower();
        break;
    }
  if (mySerial.available())
    Serial.write(mySerial.read());
}

//--------------Check Power Status---------------
void GSMCheckpower()
{
  mySerial.print("AT");    //AT Status
  delay(100);
  mySerial.println();
 
  while (mySerial.available())
  {
    delay(3);
    char c = mySerial.read();
    readString += c;
  }
  if (readString.length() > 0)
  {
    mySerial.println(readString);
    if (readString == "OK")
    {
      digitalWrite(ledPin, HIGH); //Green LED
      delay(3000);
      digitalWrite(ledPin, HIGH); //Green LED
    }
    else
    {
      digitalWrite(ledPin2, HIGH); //Red LED
      delay(3000);
      digitalWrite(ledPin2, LOW); //Red LED
    }
   readString = "";
  }
}

Thanks,
Guru

    mySerial.println(readString);

Why would you then send "OK" to the GSM thing?

PaulS:

    mySerial.println(readString);

Why would you then send "OK" to the GSM thing?

Paul I removed mySerial.println(readString); from the sketch however it didnt have any effect on the correction of the sketch.

Below is the working sketch. I change the == to = in "if (readString = "OK")". I also moved an } up before the else statement so the else statement would run correctly. The Green LED now turns on if the GSM Shield is on and responding the AT commands and the Red LED turns on if it the shield is off or doesn't respond.

#include <SoftwareSerial.h>
#include <String.h>
SoftwareSerial mySerial(52, 53);
String readString;
int ledPin = 41; //Green LED
int ledPin2 = 43; //Red LED

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  mySerial.begin(19200);               // the GPRS baud rate
  Serial.begin(19200);    // the GPRS baud rate
  delay(500);
  mySerial.print("AT+CMGF=1\r"); //Because we want to receive the SMS in text mode
}

void loop()
{
  if (Serial.available())
    switch (Serial.read())
    {
      case 'p':
        GSMCheckpower();
        break;
    }
  if (mySerial.available())
    Serial.write(mySerial.read());
}

//--------------Check Power Status---------------
void GSMCheckpower()
{
  mySerial.print("AT");    //AT Status
  delay(100);
  mySerial.println();
  while (mySerial.available())
  {
    delay(3);
    char c = mySerial.read();
    readString += c;
  }
  if (readString.length() > 0)
  {
    if (readString = "OK")
    {
      digitalWrite(ledPin, HIGH); //Green LED
      delay(3000);
      digitalWrite(ledPin, LOW); //Green LED
    }
  }
  else
  {
    digitalWrite(ledPin2, HIGH); //Red LED
    delay(3000);
    digitalWrite(ledPin2, LOW); //Red LED
  }
  readString = "";
}
SoftwareSerial mySerial(52, 53);

Why do you need to use SoftwareSerial on a device with 4 hardware serial ports?

String readString;

You do NOT need to piss away resources on the String class.

  mySerial.begin(19200);               // the GPRS baud rate
  Serial.begin(19200);    // the GPRS baud rate

Just because the GPRS speaks slowly does not mean that you have to speak slowly to the PC.

  while (mySerial.available())
  {
    delay(3);
    char c = mySerial.read();
    readString += c;
  }

The delay() is the worst possible way to read serial data. ASSuming that 3 milliseconds is enough is foolish.

Below is the working sketch.

that still has

    if (readString = "OK")

so it is hard to believe that it actually works.

YMMV.

PaulS:
Why do you need to use SoftwareSerial on a device with 4 hardware serial ports?

The reason for Software Serial is I'm going to be using the end result on my UNO. I'm just testing this sketch on my Mega because I'm testing another sketch on my UNO at the time being. Post #1 was on the UNO.

PaulS:

String readString;

You do NOT need to piss away resources on the String class.

Can bark but offer no alternatives? We're on the forum for help not just to be criticized for our lack of knowledge. I have done a lot of searching for my own fixes and only turn to opening a new thread if I cant find what I need.

PaulS:

  while (mySerial.available())

{
   delay(3);
   char c = mySerial.read();
   readString += c;
 }



The delay() is the worst possible way to read serial data. ASSuming that 3 milliseconds is enough is foolish.

Your right 3ms isn't time to do anything. I'm using zoomkat's sketch in post #9 as the base.

By the way thanks zoomkat. Thanks for the input and offering up examples and alternatives to a guy(ME) that's not a programmer by trait and has only been learning Arduino and C++ for just over 2 months.

I'm sure after I have been doing this for a while I'll also look back at the sketch's I have built so far and think what was I thinking. But having only been working and learning this stuff for just over 2 months and having a combined sketch that sends SMS messages if my house gets below a certain temp or motion is detected or power goes out(Yes I built a battery backup into this thing) and to receive SMS messages that can turn the temp detection, power detection or motion detection portions of the sketch on or off, and also the ability to send an SMS to the device to change the temp threshold. The sketch that I have been working with in this thread works consistently checking and verifying the shield is on and responding and turning the shield on if its off or not responding.

If the data being sent has an end of data marker included, then use it. If it doesn't ave an end of data marker, then a delay may be the only way to capture the data. Always start with simple code first to verify the hardware is working, then refine the code.