sim900 and arduino. send sms if button is pressed?

hello all

i am trying to do a simpel “send sms if button is pressed” code on an uno and this gsm shield:
http://www.geeetech.com/wiki/index.php/Arduino_GPRS_Shield

i am actually going to use a water level switch, which shall send an alarm if the water level goes up to high.
(and maybe start a pumpe at some point to)

Normally i use the RF Solutions EZTEXT Remote Control System or the CONTA CLIP GSM PRO to do this.
But they can not do any logic operation.

So i wanted to give this a try.

The uno and the shield works to the point, where i can send a sms using the tutorial code.

This is the code i am trying to get to work.

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

int inPin = 7;   // choose the input pin (for a pushbutton)
int val = 0;     // variable for reading the pin status

void setup()
{
  SIM900.begin(19200);
  SIM900power();
  delay(20000);  // give time to log on to network.
  pinMode(3, INPUT); // button pin
  
}

void SIM900power()
// software equivalent of pressing the GSM shield "power" button
{
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(5000);
}

void sendSMS()
{
  SIM900.print("AT+CMGF=1\r");                                                        // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"+xxxxxxxxxx\"");                                     // recipient's mobile number, in international format
  delay(100);
  SIM900.println("A button has been pushed.");        // message to send
  delay(100);
  SIM900.println((char)26);                       // End AT command with a ^Z, ASCII code 26
  delay(100);
  SIM900.println();
  delay(5000);                                     // give module time to send SMS
  SIM900power();                                   // turn off module
}

void loop()
{
  val = digitalRead(inPin);  // read input value
  if (val == HIGH) {         // check if the input is HIGH (button released)
    sendSMS();
  } else {
    do {} while (1);}
int inPin = 7;   // choose the input pin (for a pushbutton)

  pinMode(3, INPUT); // button pin

  val = digitalRead(inPin);  // read input value

Which pin is the switch really attached to?

How is the switch actually wired?

  if (val == HIGH) {         // check if the input is HIGH (button released)
    sendSMS();
  } else {
    do {} while (1);}

If the switch is not pressed (assuming that it is connected to pin 7, not pin 3, and is wired in a pulldown configuration - neither assumption am I willing to agree to)m stuff your head in the sand forever, never caring whether the switch BECOMES pressed later.

How is THAT a reasonable thing to do?

Look at the state change detection example. Send the message when the switch becomes pressed.

PaulS:

int inPin = 7;   // choose the input pin (for a pushbutton)

pinMode(3, INPUT); // button pin

val = digitalRead(inPin);  // read input value



Which pin is the switch really attached to?

How is the switch actually wired?



if (val == HIGH) {         // check if the input is HIGH (button released)
   sendSMS();
 } else {
   do {} while (1);}



If the switch is not pressed (assuming that it is connected to pin 7, not pin 3, and is wired in a pulldown configuration - neither assumption am I willing to agree to)m stuff your head in the sand forever, never caring whether the switch BECOMES pressed later.

How is THAT a reasonable thing to do?

Look at the state change detection example. Send the message when the switch becomes pressed.

#############

Thank you for your reply.

I tried to adapt state change detection example to the code with some success.

But it do not send en sms every time i sets pin 3 to high.
it only once sent a sms on state change.

i am going to use a switch witch will turn on and stay on, till the water level drops again.
Will this be problematic when using the state change detection way?

i was hoping that i would be able to turn on the shield, only on state change, to conserve energy.
But that is may not possible.

Thank you for taking the time to help me

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

// this constant won't change:
const int  buttonPin = 3;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {

  SIM900.begin(19200);
  SIM900power_on();
  pinMode(buttonPin, INPUT);

  //Serial.begin(9600);

}

void SIM900power_on()
// software equivalent of pressing the GSM shield "power" button
{
  digitalWrite(9, HIGH);
  delay(1000);
}

void SIM900power_off()
// software equivalent of pressing the GSM shield "power" button
{
  digitalWrite(9, LOW);
  delay(5000);
}

void sendSMS()
{
  SIM900.print("AT+CMGF=1\r");                                           // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"xxxxxxxxxx\"");                         // recipient's mobile number, in international format
  delay(100);
  SIM900.println("sms test");                                            // message to send
  delay(100);
  SIM900.println((char)26);                                              // End AT command with a ^Z, ASCII code 26
  delay(100);
  SIM900.println();
  delay(5000);                                                          // give module time to send SMS
  
}

void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
     
      SIM900power_on();                                                 // turn on GSM shield
      sendSMS();                                                        // send sms
      SIM900power_off();                                                // turn on GSM shield
     
    } else {
      
      SIM900power_off();                                                //turn off GSM shield
    
    }
    // Delay a little bit to avoid bouncing
    delay(500);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;

}

i am going to use a switch witch will turn on and stay on, till the water level drops again. Will this be problematic when using the state change detection way?

No. The time between state changes is immaterial.

i was hoping that i would be able to turn on the shield, only on state change, to conserve energy. But that is may not possible.

Why not? You have a SIM900power_on() function. Figure out what belongs in a SIM900power_off() function, write the function, and call it after sending the message. Of course, you'd need to call SIM900power_on() before sending the message.

On the other hand, if you are monitoring the level in a tank, something is adding liquid to the tank, which suggests that there is a pump and power for the pump, so powering the Arduino from the same source seems reasonable.

I've not got access to the library to see, but outside of the initial setup I dont see any delays/checks to ensure that a network has been registered, before you try to send the message? Your main loop powers up the module, then immediately tries to send the sms, if you want quick and dirty just build a delay in there.

Otherwise AT+CREG? would give you information on network registration.

So i finally had time to look at the project again.

Thank you all for your suggestion.

I made two versions of the code.

The first version uses the state change detection.
But i am having problems getting more input til send different sms on activation

This is the first code:

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

// this constant won't change:
const int  buttonPin = 3;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:

int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {

  SIM900.begin(19200);
  //SIM900power_on();
  pinMode(buttonPin, INPUT);
  
 }

void SIM900power()
{
        digitalWrite(9, HIGH);
        delay(1000);
        digitalWrite(9, LOW);
        delay(5000);
  
}


void sendSMS()
{
  SIM900.print("AT+CMGF=1\r");                                           // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"xxxxxxxxxx"\"");                         // recipient's mobile number, in international format
  delay(100);
  SIM900.println("sms test");                                            // message to send
  delay(100);
  SIM900.println((char)26);                                              // End AT command with a ^Z, ASCII code 26
  delay(100);
  SIM900.println();
  delay(10000);                                                          // give module time to send SMS
  
}

void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:

      SIM900power();                                                 // turn on GSM shield
      delay(15000);
      sendSMS();                                                     // send sms
      delay(50000);
      SIM900power();                                                 // turn on GSM shield
     
                                               
    
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;

}

This is the second code, using a simple debounce.
This code works with multi input, but it is a bit quick and dirty.
So any ideas to clean it up, would greatly be appreciated.

#include <Arduino.h>

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

// this constant won't change:
const int  Pin3 = 3;   
const int  Pin4 = 4;    

// Variables will change:

int pin3State;             // the current reading from the input pin
int lastpin3State = HIGH;   // the previous reading from the input pin

int pin4State;             // the current reading from the input pin
int lastpin4State = HIGH;   // the previous reading from the input pin

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers


void setup() {

  SIM900.begin(19200);
  pinMode(Pin3, INPUT);
  pinMode(Pin4, INPUT);
}


void sendSMS_pin3()
{
  SIM900.print("AT+CMGF=1\r");                                           // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"xxxxxxxxxxx\"");                         // recipient's mobile number, in international format
  delay(100);
  SIM900.println("High Water Alarm 3");                                      // message to send
  delay(100);
  SIM900.println((char)26);                                              // End AT command with a ^Z, ASCII code 26
  delay(100);
  SIM900.println();
  delay(10000);                                                          // give module time to send SMS
}



void sendSMS_pin4()
{
  SIM900.print("AT+CMGF=1\r");                                           // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"xxxxxxxxxx\"");                         // recipient's mobile number, in international format
  delay(100);
  SIM900.println("High Water Alarm 4");                                      // message to send
  delay(100);
  SIM900.println((char)26);                                              // End AT command with a ^Z, ASCII code 26
  delay(100);
  SIM900.println();
  delay(10000);                                                          // give module time to send SMS
}


void loop() {
  {

    int reading = digitalRead(Pin3);

    // If the switch changed, due to noise or pressing:
    if (reading != lastpin3State) {
      // reset the debouncing timer
      lastDebounceTime = millis();
    }

    if ((millis() - lastDebounceTime) > debounceDelay) {
      // whatever the reading is at, it's been there for longer
      // than the debounce delay, so take it as the actual current state:

      // if the pin3 state has changed:
      if (reading != pin3State) {
        pin3State = reading;


        if (pin3State == HIGH) {

          digitalWrite(9, HIGH);
          delay(1000);
          digitalWrite(9, LOW);
          delay(5000);                                          // turn on GSM shield

          delay(25000);
          sendSMS_pin3();                                                        // send sms

          digitalWrite(9, HIGH);
          delay(1000);
          digitalWrite(9, LOW);
          delay(5000);
        }
      }

    }
    lastpin3State = reading;

  }
  {

    int reading = digitalRead(Pin4);

    // If the switch changed, due to noise or pressing:
    if (reading != lastpin4State) {
      // reset the debouncing timer
      lastDebounceTime = millis();
    }

    if ((millis() - lastDebounceTime) > debounceDelay) {
      // whatever the reading is at, it's been there for longer
      // than the debounce delay, so take it as the actual current state:

      // if the pin3 state has changed:
      if (reading != pin4State) {
        pin4State = reading;


        if (pin4State == HIGH) {

          digitalWrite(9, HIGH);
          delay(1000);
          digitalWrite(9, LOW);
          delay(5000);                                          // turn on GSM shield

          delay(25000);
          sendSMS_pin4();                                       // send sms

          digitalWrite(9, HIGH);
          delay(1000);
          digitalWrite(9, LOW);
          delay(5000);
        }
      }

    }
    lastpin4State = reading;
  }
}

About the AT+CREG?
It looks like a really good idea, but it looks a bit complex for my abilities.
If you have a good idea to implement it, i would like to hear it.

thank you all for any help

But i am having problems getting more input til send different sms on activation

What problems? Please explain this statement better.

How is the switch wired? It would probably be simpler to use INPUT_PULLUP as the mode.

PaulS: What problems? Please explain this statement better.

How is the switch wired? It would probably be simpler to use INPUT_PULLUP as the mode.

i am not sure how to do it.

// read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH)

how would you add more input pin to this code?

i am not sure how to do it.

How to do what? To change INPUT to INPUT_PULLUP? Or to wire the switch when the mode is INPUT_PULLUP?

The first is incredibly simple. So is the second, for that matter - one leg of the switch goes to the digital pin, while the other leg goes to ground.

how would you add more input pin to this code?

Rename buttonState to currSwitchState1. Rename buttonPin to switchPin1. Rename lastButtonState to lastSwitchState1. Then, add currSwitchState2, switchPin2, and lastSwitchState2. Copy the block of code, and change 1 to 2 in the copy.

Thank you for your help, Paul!

i finally got it to work :slight_smile:

This is the resulting code:

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

// this constant won't change:
const int  buttonPin3 = 3;    // the pin that the pushbutton is attached to
const int  buttonPin4 = 4;

const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:

int buttonState3 = 0;         // current state of the button
int lastButtonState3 = 0;     // previous state of the button

int buttonState4 = 0;         // current state of the button
int lastButtonState4 = 0;     // previous state of the button

void setup() {

  SIM900.begin(19200);
  //SIM900power_on();
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
}

void SIM900power()
{
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(5000);

}


void sendSMS3()
{
  SIM900.print("AT+CMGF=1\r");                                           // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"xxxxxxxxxx\"");                         // recipient's mobile number, in international format
  delay(100);
  SIM900.println("sms test3");                                            // message to send
  delay(100);
  SIM900.println((char)26);                                              // End AT command with a ^Z, ASCII code 26
  delay(100);
  SIM900.println();
  delay(10000);                                                          // give module time to send SMS
}


void sendSMS4()
{
  SIM900.print("AT+CMGF=1\r");                                           // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"xxxxxxxxxxx\"");                         // recipient's mobile number, in international format
  delay(100);
  SIM900.println("sms test4");                                            // message to send
  delay(100);
  SIM900.println((char)26);                                              // End AT command with a ^Z, ASCII code 26
  delay(100);
  SIM900.println();
  delay(10000);                                                          // give module time to send SMS
}

void loop() {
  // read the pushbutton input pin:
  buttonState3 = digitalRead(buttonPin3);
  buttonState4 = digitalRead(buttonPin4);

  // compare the buttonState to its previous state
  if (buttonState3 != lastButtonState3) {

    // if the state has changed, increment the counter
    if (buttonState3 == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:

      SIM900power();                                                 // turn on GSM shield
      delay(10000);
      sendSMS3();                                                        // send sms
      delay(15000);
      SIM900power();                                                // turn on GSM shield

    }
    // Delay a little bit to avoid bouncing
    delay(50);

    // save the current state as the last state,
    //for next time through the loop
    lastButtonState3 = buttonState3;
  }
     
// compare the buttonState to its previous state
    if (buttonState4 != lastButtonState4) {

      // if the state has changed, increment the counter
      if (buttonState4 == HIGH) {
        // if the current state is HIGH then the button
        // wend from off to on:

        SIM900power();                                                 // turn on GSM shield
        delay(10000);
        sendSMS4();                                                        // send sms
        delay(15000);
        SIM900power();                                                // turn on GSM shield
      }
      // Delay a little bit to avoid bouncing
      delay(50);
    }
 
    // save the current state as the last state,
  //for next time through the loop
  lastButtonState4 = buttonState4;   
  
  
}

Once you have sent an SMS, I really don't see the need to turn the device's power on.

i am using the Power on/off code for the software switch, which i borrowed from the site http://www.geeetech.com/wiki/index.php/Arduino_GPRS_Shield

That is why it looks like i am powering it on again.

#include <SoftwareSerial.h>

SoftwareSerial mySoftUART(3,2); //RX ,TX
String CombineStr = “”;
unsigned int k = 0 ;
char Receive;

void _getResp() //Rcecive data from module
{
delay(100);
while (mySoftUART.available())
Serial.write(mySoftUART.read());
}

void setup()
{
pinMode(4,INPUT_PULLUP); //Set input with internal resistor
pinMode(5,INPUT_PULLUP);
pinMode(6,INPUT_PULLUP);

pinMode(7,OUTPUT); // Set output to blynk with receiving call

mySoftUART.begin(9600); //Using115200 baud to commute to sim
Serial.begin(9600); //9600 baud with Serial Monitor

}

void loop()
{

if(mySoftUART.available()) //If receive something

Receive = mySoftUART.read(); //Read that data , the data just 1 byte
//
if(Receive == ‘R’)
{
k++; // k = 1
CombineStr += Receive;
}
else if(Receive == ‘I’ && k == 1)
{
k++;
CombineStr += Receive;
}
else if(Receive == ‘N’ && k ==2)
{
k++;
CombineStr += Receive;
}
else if(Receive == ‘G’ && k==3)
{
k++; // k = 4
CombineStr +=Receive; //
}

if(CombineStr == “RING” && k == 4)

{
Serial.println(CombineStr);
digitalWrite(7,HIGH);
delay(1000);
digitalWrite(7,LOW);
delay(1000);
CombineStr = “”;
k=0;
}
if ( k == 4 )
{
Serial.println(CombineStr);
CombineStr = “”;
k=0;
}
Serial.print(Receive);

////////////////////////SEND
//TEST OK
if (digitalRead(4) == 0)
{
Serial.println("");
while(digitalRead(4) == 0);
mySoftUART.println(“AT”);
_getResp();
}

// MAKE A CALL
else if(digitalRead(5) == 0)
{
Serial.println("");
while(digitalRead(5) == 0);
mySoftUART.println(“ATD +88;”);
_getResp();
}

//SEND A MESSAGE
else if(digitalRead(6) == 0)
{
Serial.println("");
while(digitalRead(6) == 0);
mySoftUART.println(“AT+CMGF=1”);
_getResp();
mySoftUART.println(“AT+CMGS=”+88"");
_getResp();
mySoftUART.print(“TOKI”);
_getResp();

mySoftUART.write(26);
}

}