Arduino Nano GSM SMS Temp Request and Alarm

Hello everyone.
I m trying to make a project which is monitoring Temp and Humid. with a DHT11 sensor. If Temp goes under 15 C then sends me a SMS. The same happens if Temp goes over 26C.
The code works fine in this part
I m trying also to send me a SMS with real time conditions. If I send "Q" character to GSM module, I want to answer through SMS with the sensor measurements.
But my code is not working...
I appreciate for any help
Thanks a lot

#include <DHT.h>
#include <SoftwareSerial.h>

#define DHTPIN 6     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor


// GSM TxD ---> ARDUINO RxD  GSM RxD ---> ARDUINO Tx1
// TO UPLOAD SKETCH TO ARDUINO, CABLES RxD and TxD MUST BE DISCONNECTED 
 
DHT dht(DHTPIN, DHTTYPE, 6);

// Create global varibales to store temperature and humidity
float t; // temperature in celcius
float f; // temperature in fahrenheit
float h; // humidity
float hi; 

SoftwareSerial SIM900(7, 8); //GSM Tx--> D7, GSM Rx--> D8

char incomingChar; // Create variable to store incoming SMS characters
  
void setup() {
  Serial.begin(9600);
  SIM900.begin(9600);  
 
  dht.begin();

  delay(20000);

  // AT command to set SIM900 to SMS mode
  SIM900.print("AT+CMGF=1\r"); 
  delay(100);
  // Set module to send SMS data to serial out upon receipt 
  SIM900.print("AT+CNMI=2,2,0,0,0\r");
  delay(100);

}

void loop() {
  // Wait a few seconds between measurements.
  delay(1000);
    readData(); 
  
     if(t>26)    
     { 
      alarmHighTemp();
      delay(60000); 
      }

         else if(t<15)
      {
        alarmLowTemp();
        delay(60000); 
        }    

        else if (t >= 15 and t <= 26)
        {
          if (smsrequest())
          {
            Replay();
            delay(10000);
          }
        }
}


void alarmHighTemp()
{
   readData();
  SIM900.print("\r");
  delay(1000);                  
  SIM900.print("AT+CMGF=1\r");    
  delay(1000);
  SIM900.print("AT+CMGS=\"+30**********\"\r");    //Number to which you want to send the sms
  delay(1000);
  SIM900.print("ALARM!!!HIGH TEMP" + String(t) + "*C " + String(h) + "%");   //The text of the message to be sent
  delay(1000);
  SIM900.write(0x1A);
  delay(1000); 
}


void alarmLowTemp()
{
   readData(); 
  SIM900.print("\r");
  delay(1000);                  
  SIM900.print("AT+CMGF=1\r");    
  delay(1000);
  SIM900.print("AT+CMGS=\"+306972291609\"\r");    //Number to which you want to send the sms
  delay(1000);
  SIM900.print("ALARM!!!LOW TEMP"+ String(t) + "*C " + String(h) + "%");   //The text of the message to be sent
  delay(1000);
  SIM900.write(0x1A);
  delay(1000); 
}

void Replay()
{
  readData(); 
  SIM900.print("\r");
  delay(1000);                  
  SIM900.print("AT+CMGF=1\r");    
  delay(1000);
  SIM900.println("AT + CMGS = \"+306972291609\"");
      delay(100);
      
      String dataMessage = ("Temperature: " + String(t) + "*C " + " Humidity: " + String(h) + "%");
           
      
      // Send the SMS text message
      SIM900.print(dataMessage);
      delay(100);
      // End AT command with a ^Z, ASCII code 26
      SIM900.println((char)26); 
      delay(100);
      SIM900.println();
      // Give module time to send SMS
      delay(5000);  
} 

boolean smsrequest()
{
if(SIM900.available() >0) {
    incomingChar=SIM900.read();
    if(incomingChar=='Q') {
      delay(10);
      Serial.print(incomingChar);
      Serial.print("...Request Received \n");
              return true;
    }
}
  return false;
}

boolean readData()
{
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
   h = dht.readHumidity();
  // Read temperature as Celsius
   t = dht.readTemperature();
  // Read temperature as Fahrenheit
   f = dht.readTemperature(true);

  hi = dht.computeHeatIndex(f, h);
    
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return true;
  }


}

This syntax is incorrect

else if(15<=t<=26)

Instead, use

else if (t >= 15 and t <= 26)

Thanks a lot Cattledog. But is not working again...

If I send "Q" character to GSM module, I want to answer through SMS with the sensor measurements.
But my code is not working...

You need to isolate your issue.

Have you run a simple test sketch to see if you can receive an sms? How do you send the letter Q?

What do your serial prints tell you?

Is smsrequest() seeing the incoming message?
Is Replay() being called? Does Replay() send the correct message if tested alone in a simple test sketch?

With the serial monitor opened, Im receiving nothing. I didnt check the Replay().

If smsrequest() were receiving 'Q' you would see some serial output.

Work on a simple test program to receive an sms.

if(SIM900.available() >0) {
    incomingChar=SIM900.read();
    if(incomingChar=='Q') {
      delay(10);
      Serial.print(incomingChar);
      Serial.print("...Request Received \n");
              return true;
    }
}

This is not correct to read an incoming sms. There is much more sent than 'Q'.

A received message starts with +CMT. All the fields in the response are comma-separated with first field being phone number. The second field is the name of person sending SMS. Third field is a timestamp while forth field is the actual message. You need to read an entire message, and then look for the 'Q' in the message field.

See if the code below can receive and print a complete message. If it is correct, then you can work on detecting the 'Q' .

if (SIM900.available() > 0) //If there is stuff in the buffer
 {
   char textMessage[100] = {};
   byte numChars = SIM900.readBytes(textMessage, 100);//.readBytes returns number read
   textMessage[numChars] = '\0';//null Terminator
   Serial.println(textMessage); // Print the new message
 }

Cattledog, I use your code and its receiving my message.

What is the exact message received?

Depending on the number of 'Q' s appearing in the message you may want to look for it with different methods.

If there is only one 'Q' you could use strchr which is the c string function to find a character. Do some google search for documentation.

if (SIM900.available() > 0) //If there is stuff in the buffer
{
  char textMessage[100] = {};
  byte numChars = SIM900.readBytes(textMessage, 100);//.readBytes returns number read
  textMessage[numChars] = '\0';//null Terminator
  Serial.println(textMessage); // Print the new message
  char * pch = strchr(textMessage, 'Q'); //pch is pointer to 'Q'
  if (pch) //found 'Q', pch is not NULL
  { Serial.println("found 'Q'");
    //send outgoing sms
    Replay();
  }
  else
    Serial.println("No 'Q' found in message");
}

With your last code the Serial seems like this:

GPRS ready...
AT+CMGF=1
AT+CNMI=2,2,0,0,0

OK

No 'Q' found in message

+CMT: "+30**********","","20/03/25,23:27:59+08"
Q

found 'Q'

AT+CMGF=1

OK
AT + CMGS = "+30**********"
Temperature: 23.7
No 'Q' found in message

Tested with a little modification. It seems to work. Tomorrow I will check it again
Thanks a lot Cattledog.

#include <DHT.h>
#include <SoftwareSerial.h>

#define DHTPIN 6     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor


// GSM TxD ---> ARDUINO RxD  GSM RxD ---> ARDUINO Tx1
// TO UPLOAD SKETCH TO ARDUINO, CABLES RxD and TxD MUST BE DISCONNECTED 
 
DHT dht(DHTPIN, DHTTYPE, 6);

// Create global varibales to store temperature and humidity
float t; // temperature in celcius
float f; // temperature in fahrenheit
float h; // humidity
float hi; 

SoftwareSerial SIM900(7, 8); //GSM Tx--> D7, GSM Rx--> D8

char incomingChar; // Create variable to store incoming SMS characters
  
void setup() {
  Serial.begin(9600);
  SIM900.begin(9600);  
 
  dht.begin();

  delay(10000);

Serial.print("GPRS ready...\r\n");  

  // AT command to set SIM900 to SMS mode
  SIM900.print("AT+CMGF=1\r\n"); 
  delay(100);
  // Set module to send SMS data to serial out upon receipt 
  SIM900.print("AT+CNMI=2,2,0,0,0\r\n");
  delay(1000);

}

void loop() {
  // Wait a few seconds between measurements.
  delay(1000);
    readData(); 
  
     if(t>26)    
     { 
      alarmHighTemp();
      delay(60000); 
      }

         else if(t<15)
      {
        alarmLowTemp();
        delay(60000); 
        }    

        else if (t >= 15 and t <= 26)
        {
          smsrequest();
            delay(10000);
          }
        
}


void alarmHighTemp()
{
   readData();
  SIM900.print("\r");
  delay(1000);                  
  SIM900.print("AT+CMGF=1\r");    
  delay(1000);
  SIM900.print("AT+CMGS=\"+306972291609\"\r");    //Number to which you want to send the sms
  delay(1000);
  SIM900.print("ALARM!!!HIGH TEMP" + String(t) + "*C " + String(h) + "%");   //The text of the message to be sent
  delay(1000);
  SIM900.write(0x1A);
  delay(1000); 
}


void alarmLowTemp()
{
   readData(); 
  SIM900.print("\r");
  delay(1000);                  
  SIM900.print("AT+CMGF=1\r");    
  delay(1000);
  SIM900.print("AT+CMGS=\"+30**********\"\r");    //Number to which you want to send the sms
  delay(1000);
  SIM900.print("ALARM!!!LOW TEMP"+ String(t) + "*C " + String(h) + "%");   //The text of the message to be sent
  delay(1000);
  SIM900.write(0x1A);
  delay(1000); 
}

void Reply()
{
  readData(); 
  SIM900.print("\r");
  delay(1000);                  
  SIM900.print("AT+CMGF=1\r");    
  delay(1000);
  SIM900.println("AT + CMGS = \"+30**********\"\r");
      delay(1000);
      
       SIM900.print( String(t) + "*C " + String(h) + "%");   //The text of the message to be sent
  delay(1000);
  SIM900.write(0x1A);
  delay(1000); 
} 

boolean smsrequest()
{
if (SIM900.available() > 0) //If there is stuff in the buffer
{
  char textMessage[100] = {};
  byte numChars = SIM900.readBytes(textMessage, 100);//.readBytes returns number read
  textMessage[numChars] = '\0';//null Terminator
  Serial.println(textMessage); // Print the new message
  char * pch = strchr(textMessage, 'Q'); //pch is pointer to 'Q'
  if (pch) //found 'Q', pch is not NULL
  { Serial.println("found 'Q'");
    //send outgoing sms
    Reply();
  }
  else
    Serial.println("No 'Q' found in message");
}

  return false;
}

boolean readData()
{
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
   h = dht.readHumidity();
  // Read temperature as Celsius
   t = dht.readTemperature();
  // Read temperature as Fahrenheit
   f = dht.readTemperature(true);

  hi = dht.computeHeatIndex(f, h);
    
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return true;
  }


}

Hello again
And what if I wanted to receive 2 or more characters for more capabilities, like to open or close a relay?

And what if I wanted to receive 2 or more characters for more capabilities, like to open or close a relay?

You can keep this pretty tight since you have control over the message and the command set.

If you can design your command set with single letters, it will be most simple. You can always send some other letter instead of 'Q', and test the message for all the letters in your command set. Can you work with a single letter command set?

If you always need to send a 'Q' and then following letters, you can look for the pointer to 'Q', and then the following letters will be a the location of pointer +1.

Thanks a lot Cattledog. I ll try, using your code, with "if" or "switch" and different letters. Thanks again for your help