Go Down

Topic: arduino gsm door alarm (Read 3211 times) previous topic - next topic

mark7w

:~
I need some help with my arduino uno code. I am trying to get a sms sent to my mobile whenever the door is opened.
the goodnews is, that i can get it to send an sms when the door FIRST opens. but if i shut the door and open it again say 30 Seconds later, I dont get a new SMS.
The only way to get a new SMS sent is to re-set the Arduino. Am i missing something in my code. The code I have has be cut and paste from a couple of web sites.
at the moment when the Arduino is powered ON, There is a delay of 35 secs to allow to gsm to register on the network. Then if the door is opened for more than 3 sec, the sms is sent
I'm using and Arduino uno R3, Sparkfun SM5100B GSM, and a reed swith as the door contact. Here is the CODE

Code: [Select]


#include <SoftwareSerial.h>
SoftwareSerial module(2,3);  // We need to create a serial port on D2/D3 to talk to the GSM module
char mobilenumber[] = "078xxxxxxx4";  // Replace xxxxxxxx with the recipient's mobile number

int sensor = 12; // pin sensor is attached to
int time = 0;
int time_threshold = 3000; //time in ms => 10 sec.
int val = 0;
int led = 11;




void setup()

  module.begin(9600); //Initialize serial ports for communication.
  pinMode(sensor,INPUT);
  pinMode(led,OUTPUT);
  digitalWrite(sensor,HIGH);


  delay(35000); // give the GSM module time to initialise, locate network etc.
}


void loop()
{
  digitalWrite(led,HIGH);
  val = digitalRead(sensor);
  while(val == LOW){
    val = digitalRead(sensor);
      }

  time = 0;
  while((val == HIGH)&&(time < time_threshold)){
    time = time + 100;
    val = digitalRead(sensor);
    delay(100);
    digitalWrite(led,HIGH);
   
   
  }
  if (time >= time_threshold){
    digitalWrite(led,LOW);
    for (int i=100;i>5000;i++);
   

    module.println("AT+CMGF=1"); // set SMS mode to text
    module.print("AT+CMGS=");  // now send message...
    module.write(34); // ASCII equivalent of "
    module.print(mobilenumber);
    module.write(34);  // ASCII equivalent of "
    module.println();
    delay(500); // give the module some thinking time
    module.println("Door Open Alert");   // our message to send
    module.write(26);  // ASCII equivalent of Ctrl-Z
    module.flush();
    delay(10000); // the SMS module needs time to return to OK status
   
    do // You don't want to send out multiple SMSs.... or do you?
    {
      delay(1);
    }
    while (1>0);
   
  }
}

PaulS

Code: [Select]
int time_threshold = 3000; //time in ms => 10 sec.
Wrong. If you are going to have comments, make them match the code.

Code: [Select]
int sensor = 12; // pin sensor is attached to
Variable names for pins really should have pin somewhere in the name. Did you really go to Radio Shack (or equivalent) and ask for a sensor? Or did you buy a switch? Make the name reflect the actual thing connected to the pin.

Code: [Select]
    for (int i=100;i>5000;i++);
WTF?

Code: [Select]
    do // You don't want to send out multiple SMSs.... or do you?
    {
      delay(1);
    }
    while (1>0);

Well, this would be why you never get another SMS.

mark7w

points taken on board.

guess i dont need

"for (int i=100;i>5000;i++);"

if i remove this code should i expect to get SMS each time the door is opened?

"do // You don't want to send out multiple SMSs.... or do you?
    {
      delay(1);
    }
    while (1>0);"


PaulS

Quote
if i remove this code should i expect to get SMS each time the door is opened?

No. You should expect to get that over and over as long as the door is open.

Now, you need to learn about saving the previous state of a pin, and detect transitions. You want to send the message only when the switch pin transitions from released to pressed.

mark7w

Thanks, will learn as advised

mark7w

so here's an updated code with revisions.

Code: [Select]
#include <SoftwareSerial.h>
SoftwareSerial module(2,3);  // We need to create a serial port on D2/D3 to talk to the GSM module
char mobilenumber[] = "078xxxxxxx4";  // Replace xxxxxxxx with the recipient's mobile number

int ledPin = 11;
int doorContactPin = 12; // pin door contact is attached to

//door delay
int time = 0;
int time_threshold = 3000; //time in ms => 3 sec.
int val = 0;

//pin state.
int current_val = 0; // val wil be used to store the state of the input pin.
int old_val = 0; // this variable stores the previous value of "val".
int state = 0; // 0 = doorContactPin open while 1 = doorContactPin closed.


void setup()

  module.begin(9600); //Initialize serial ports for communication.
  delay(35000); // give the GSM module time to initialise, locate network etc.
  pinMode(doorContactPin,INPUT);
  pinMode(ledPin,OUTPUT);
  digitalWrite(doorContactPin,HIGH);
}


void loop()
{
  //door delay code.
  digitalWrite(ledPin,HIGH);
  val = digitalRead(doorContactPin);
  while(val == LOW){
    val = digitalRead(doorContactPin);
  }
  time = 0;
  while((val == HIGH)&&(time < time_threshold)){
    time = time + 100;
    val = digitalRead(doorContactPin);
    delay(100);
    digitalWrite(ledPin,HIGH); 
  }
  if (time >= time_threshold){
    digitalWrite(ledPin,LOW);
  }

  //door state
  current_val = digitalRead(doorContactPin); // read input value and store it.
  // check if there was a transition.
  if ((current_val == HIGH) && (old_val == LOW)){
    state = 1 - state;
    delay(10);
  }
  old_val = current_val; // val is now old, let's store it
  if (state == 1) {
    digitalWrite(doorContactPin, HIGH); // doorContactPin closed.
  }
  else {
    digitalWrite(doorContactPin, LOW); // doorContactPin open.
  }
  //send sms message

  module.println("AT+CMGF=1"); // set SMS mode to text
  module.print("AT+CMGS=");  // now send message...
  module.write(34); // ASCII equivalent of "
  module.print(mobilenumber);
  module.write(34);  // ASCII equivalent of "
  module.println();
  delay(500); // give the module some thinking time
  module.println("Door Open Alert");   // our message to send
  module.write(26);  // ASCII equivalent of Ctrl-Z
  delay(5000); // the SMS module needs time to return to OK status 
}


still feels like I'm not doing something right.. I get the sms everytime the door is open but I dont think the code for the door state is actually doing anything.
As was mentioned before. I still get sms for the duration of the door been open.
What other code do i need?

PaulS

Those while loops to read the doorContactPin state are too confusing. All you need to do is detect a transition from open to closed or from closed to open.

Code: [Select]
  val = digitalRead(doorContactPin);
  while(val == LOW){
    val = digitalRead(doorContactPin);
  }

This looks like you want loop() to block (do nothing) until the door is opened. Why? What if you decide that you also want to monitor a window? Then, you're screwed because you will end up blocking until the door is opened and the window is opened. Not a good idea.

Code: [Select]
  time = 0;
  while((val == HIGH)&&(time < time_threshold)){
    time = time + 100;
    val = digitalRead(doorContactPin);
    delay(100);
    digitalWrite(ledPin,HIGH); 
  }

Opening and closing the door within 3 seconds doesn't count as an entry?

When a pin, such as doorContactPin, is INPUT, writing HIGH or LOW to the pin turns on or off the pullup resistor. Why you want to do that in loop is a mystery.

Put your code to send the SMS in a function. Define your requirements for sending an SMS. It appears that you only want to send an SMS if the door is open for 3 seconds or more.

So, detect the transitions from closed to open and from opened to closed. When they happen, record the time. When the SMS is sent, clear the times. When the times are less than 3 seconds apart, clear the times.

Code: [Select]
unsigned long doorOpenTime = 0;
unsigned long doorClosTime = 0;

int currDoorState;
int prevDoorState = LOW; // Assumes that LOW means closed and that the door is closed when the Arduino starts

void loop()
{
   currDoorState = digitalRead(doorContactPin);
   if(currDoorState != prevDoorState)
   {
     // Door was closed and is now open or door was open and is now closed
     if(currState == LOW)
     {
        // Door is now closed
        doorClosTime = millis();
     }
     else
     {
        // Door is now open
        doorOpenTime = millis();
     }
   }
   prevDoorState = currDoorState;

   // Now see if the door was opened
   if(doorOpenTime > 0)
   {
      // It was. Was it closed?
      if(doorClosTime > 0)
      {
         // Yes. How far apart?
         if(doorClosTime - doorOpenTime >= time_threshold)
         {
            SendSMS("Door closed after more than 3 seconds");
            doorOpenTime = 0;
            doorClosTime = 0;
         }
      }
      else
      {
         // Door is still open. How long has it been open?
         if(millis() - doorOpenTime >= time_threshold)
         {
            SendSMS("Door still open after more than 3 seconds");
//         doorOpenTime = 0;
//         doorClosTime = 0;
         }
      }
   }
}


You can see that there are two places where an SMS is sent, for two different reasons. Either or both may be important to you. You may care, or not, that the door was finally closed. If so, leave them both in, and leave the door times commented out in the second block. If not, remove the first block containing the SendSMS() call, and uncomment the door time resets in the second block.

mark7w

Thanks again. The end goal here for me is to have a keypad and LCD with the door contact.
The keypad arms and dis-arms the system and the lcd shows if the alarm is set or un-set. the door contact triggers the alarm (sms) if the pin number has not been entered in a set time.

I am just working on getting the door contact to send an sms when the door has been open for 3 seonds at the moment. As this will give me time to turn the unit off before sms is sent. Eventually, I will  add a keypad and LCD.

It works to a degree, but only need one sms sent when door is open beyound 3 seconds and not additional sms for duration door is open.

i'm no programmer, but trying to understand syntax of code.  Thanks for the help. :D

mark7w

I have changed some code around but also left some old code in as i was'nt sure how to edit it to the correct form.
Code: [Select]


#include <SoftwareSerial.h>
SoftwareSerial module(2,3);  // We need to create a serial port on D2/D3 to talk to the GSM module
char mobilenumber[] = "07xxxxxxxx4";  // Replace xxxxxxxx with the recipient's mobile number


int doorContactPin = 4; // pin door contact is attached to

// NEW CODE
unsigned long doorOpenTime = 0;
unsigned long doorClosTime = 0;
unsigned long time_threshold = 3000; //time in ms => 3 sec.
int currDoorState;
int prevDoorState = LOW; // Assumes that LOW means closed and that the door is closed when the Arduino starts

//door delay
int time = 0;
int val = 0;





void setup()

  module.begin(9600); //Initialize serial ports for communication.
  delay(35000); // give the GSM module time to initialise, locate network etc.
  pinMode(doorContactPin,INPUT);
  digitalWrite(doorContactPin,LOW);


  //door delay code.

  digitalWrite(doorContactPin,LOW);
  val = digitalRead(doorContactPin);
  while(val == HIGH){
    val = digitalRead(doorContactPin);
  }
  time = 0;
  while((val == LOW)&&(time < time_threshold)){
    time = time + 100;
    val = digitalRead(doorContactPin);
    delay(100);
    digitalWrite(doorContactPin,LOW);
  }
  if (time >= time_threshold){
    digitalWrite(doorContactPin,HIGH);
  }
}
void sendSMS()
{
  //send sms message

  module.println("AT+CMGF=1"); // set SMS mode to text
  module.print("AT+CMGS=");  // now send message...
  module.write(34); // ASCII equivalent of "
  module.print(mobilenumber);
  module.write(34);  // ASCII equivalent of "
  module.println();
  delay(500); // give the module some thinking time
  module.println("Door Open Alert");   // our message to send
  module.write(26);  // ASCII equivalent of Ctrl-Z
  delay(5000); // the SMS module needs time to return to OK status 
}

void loop()
{



  //new code
  currDoorState = digitalRead(doorContactPin);
  if(currDoorState != prevDoorState)
  {
    // Door was closed and is now open or door was open and is now closed
    if(currDoorState == LOW)
    {
      // Door is now closed
      doorClosTime = millis();
    }
    else
    {
      // Door is now open
      doorOpenTime = millis();
    }
  }
  prevDoorState = currDoorState;

  // Now see if the door was opened
  if(doorOpenTime > 0)
  {
    // It was. Was it closed?
    if(doorClosTime > 0)
    {
      //Yes. How far apart?
      if(doorClosTime - doorOpenTime >= time_threshold)
      {
        sendSMS();
        doorOpenTime = 0;
        doorClosTime = 0;
      }
    }
    else
    {
      // Door is still open. How long has it been open?
      if(millis() - doorOpenTime >= time_threshold)
      {
        sendSMS();
        doorOpenTime = 0;
        doorClosTime = 0;
      }
    }
  }
}


I put your code in but have tried various ways since then to get the required delay after the door has opened. I have returned to the code above as what i have tried just does'nt work. The "millis()" function i assume is looking at the time_threashold, am I correct? I think my "delay code" is still messing things up but could not find answer from your previous advice on this.  My brain is turning to liquid on this.

PaulS

Code: [Select]
  digitalWrite(doorContactPin,LOW);
  val = digitalRead(doorContactPin);

The doorContactPin pin is defined as an input. Setting it HIGH or LOW turns on or off the pullup resistor. Turning the pullup resistor on an off in the code makes no sense. You either want it always on, or always off.

Code: [Select]
  val = digitalRead(doorContactPin);
  while(val == HIGH){
    val = digitalRead(doorContactPin);
  }

Some comments that describe why this code is here, in setup(), would be a good idea.

Code: [Select]
  time = 0;
  while((val == LOW)&&(time < time_threshold)){
    time = time + 100;
    val = digitalRead(doorContactPin);
    delay(100);
    digitalWrite(doorContactPin,LOW);
  }
  if (time >= time_threshold){
    digitalWrite(doorContactPin,HIGH);
  }

Ditto for this code. Turning the INPUT pin off and on makes no sense, as I mentioned.


mark7w

#10
Nov 11, 2012, 08:34 pm Last Edit: Nov 11, 2012, 09:11 pm by mark7w Reason: 1
Thanks for the help. Am i getting confussed with HIGH and LOW. If the pin is HIGH then the pullup resistor pulls the pin  from 0v to 5V and LOW  pulls the the pin down to 0v
:smiley-red:

Code: [Select]
digitalWrite(doorContactPin,LOW);
  val = digitalRead(doorContactPin);

Quote
The doorContactPin pin is defined as an input. Setting it HIGH or LOW turns on or off the pullup resistor. Turning the pullup resistor on an off in the code makes no sense. You either want it always on, or always off.





Code: [Select]
Code:
  val = digitalRead(doorContactPin);
  while(val == HIGH){
    val = digitalRead(doorContactPin);
  }

Quote
Some comments that describe why this code is here, in setup(), would be a good idea.

should this NOT be in setup()

PaulS

Quote
Am i getting confussed with HIGH and LOW. If the pin is HIGH then the pullup resistor pulls the pin  from 0v to 5V and LOW  pulls the the pin down to 0v

You are getting confused about what digitalRead() and digitalWrite() are for, and when to use each one. The digitalWrite() function, for an INPUT pin, turns the pullup resistor on or off. The way that the switch is connected defines whether the pullup resistor should be on or off. The resistor should be turned on or off ONCE.

For an OUTPUT pin, the digitalWrite() function turns the pin on or off.

The digitalRead() function is for reading from an INPUT pin. It returns HIGH or LOW.

Look at the direction of the pin defined in doorContactPin. It is defined as an INPUT pin. That means that you would call digitalWrite() on that pin exactly once (or less) in the sketch. Not a bazillion times like you are doing now.

You WOULD call digitalRead() on that pin a lot; any time you want to know whether the door is open or closed, call digitalRead().

Quote
should this NOT be in setup()

As near as I can tell, in the absence of any comments, the place for that code is the bit bucket/round file/recycle bin (or whatever other euphemism for trash can that you like).

mark7w

Code: [Select]
unsigned long doorOpenTime = 0;
unsigned long doorClosTime = 0;

int currDoorState;
int prevDoorState = LOW; // Assumes that LOW means closed and that the door is closed when the Arduino starts

void loop()
{
   currDoorState = digitalRead(doorContactPin);
   if(currDoorState != prevDoorState)
   {
     // Door was closed and is now open or door was open and is now closed
     if(currState == LOW)
     {
        // Door is now closed
        doorClosTime = millis();
     }
     else
     {
        // Door is now open
        doorOpenTime = millis();
     }
   }
   prevDoorState = currDoorState;

   // Now see if the door was opened
   if(doorOpenTime > 0)
   {
      // It was. Was it closed?
      if(doorClosTime > 0)
      {
         // Yes. How far apart?
         if(doorClosTime - doorOpenTime >= time_threshold)
         {
            SendSMS("Door closed after more than 3 seconds");
            doorOpenTime = 0;
            doorClosTime = 0;
         }
      }
      else
      {
         // Door is still open. How long has it been open?
         if(millis() - doorOpenTime >= time_threshold)
         {
            SendSMS("Door still open after more than 3 seconds");
//         doorOpenTime = 0;
//         doorClosTime = 0;
         }
      }
   }
}


You can see that there are two places where an SMS is sent, for two different reasons. Either or both may be important to you. You may care, or not, that the door was finally closed. If so, leave them both in, and leave the door times commented out in the second block. If not, remove the first block containing the SendSMS() call, and uncomment the door time resets in the second block.
[/quote]

silly question but where does the first block of code start for SendSMS() is it.
Code: [Select]
{
            SendSMS("Door closed after more than 3 seconds");
            doorOpenTime = 0;
            doorClosTime = 0;
         }


mark7w

thanks now i see, I'll play with the code alittle more a see what happens,

PaulS

Quote
silly question but where does the first block of code start for SendSMS() is it.

Yes. And the second one is:

Code: [Select]
            SendSMS("Door still open after more than 3 seconds");
//         doorOpenTime = 0;
//         doorClosTime = 0;

Go Up