Alarm with pic 16f628, ds275 transceiver, motion sensor and old modem

Sin categoría 1 Comentario

I have an old external 2400 b.p.s. modem that somebody gave me and I had the idea of creating an alarm with it. The advantage of modems is that you can interact with the phone line for making calls.

A passive infrared sensor (PIR) is waiting for a person to enter a room. If some movement is detected, it reports to a pic microcontroller. Finally the pic dials a phone number through the modem to alert the user.

Stuff I have used:

To make the circuit as easy as possible I have used a 16f628a pic because I don’t have to use a quartz crystal, I can disable the MCLR pin and use the integrated USART (also a 16f88 pic should use). In the same way I used the ds275 because it can communicate with a serial port without a capacitor (unlike MAX232). I have soldered some wires directly to the modem (1 for GND, 1 for 5 v. and 1 for 9 v.), so It doesn’t need an external power supply.

This is the circuit schema:

The PIR sensor has a digital output and it’s connected to the RB0 pin of the pic, which can be programmed as interrupt, so the pic can be in sleep mode until it receives a signal from the sensor. When this happens, it starts sending AT commands to make the alarm call. As the pic can’t talk directly to a serial port, the transceiver converts the pic signals to RS232 signals for both receiving and sending. Once the call has been made and the modem detects that the call is ended, it returns a numeric code that the pic receives and change to detection mode again.

A picture of the whole system:

A demostration video:

What you can see in the video is: The modem is turned on and the pic configures it to disable command echo, change to return numeric responses and turn off the volume of the modem speaker. The user has 15 seconds to leave the room, then the pic waits a motion detection. When it is detected the pic dials a fixed phone number and the user will receive the alert.

The pic is programmed in CCS and the source code is this:

main.h

#include <16F628A.h>
 
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC                    //Internal RC Osc
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
 
#use delay(clock=4000000)
#use fast_io(b)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)
 
typedef enum {INICIO, DETECTA, ALARMA, LLAMADO} ESTADOS;

main.c

#include "main.h"
 
ESTADOS estado;
volatile int8 dato;
 
// A movement has been detected and we change to ALARMA state
#INT_EXT
void movimiento()
{
   if(estado == DETECTA)
   {
      estado = ALARMA;
   }
}
 
// A character has been received
#INT_RDA
void lectura()
{
   int8 valor;
   if(kbhit())
   {
      valor = getc();
      if(valor != '\r')
      {
         dato = valor;
      }
   }
}
 
// generic function which changes to DETECTA state removing any old interrupt and re-enabling it
void deteccion()
{
   estado = DETECTA;
   clear_interrupt(int_ext);
   enable_interrupts(int_ext);
}
 
void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ);
   // Every pin from B port is an input except the USART output pin
   set_tris_b(0xFB);
   // We begin with INICIO state
   estado = INICIO;
   // The interrupt must be raised from low level to high level
   ext_int_edge( L_TO_H );
   enable_interrupts(int_rda);
   enable_interrupts(global);
 
   for(;;)
   {
      switch(estado)
      {
 
         // In INICIO state we initialize the modem to avoid command echo, changing into numeric 
         // responses and disable speaker, wating 15 seconds altogether and then passing to 
         // detection state
         case INICIO:
            delay_ms(2000);
            printf("ATE0V0M0\r");
            delay_ms(13000);
            deteccion();
            break;
         // In DETECTA state the pic goes to sleep mode until an interrupt activates it again.
         case DETECTA:
            sleep();
            break;
         // The interrupt is disabled and the phone number we want to alert is dialed
         case ALARMA:
            disable_interrupts(int_ext);
            dato = 'A';
            printf("ATDTXXXXXXXXX\r");
            estado = LLAMADO;
            break;
         // We wait until the end of the call to return to detection state
         case LLAMADO:
            if(dato != 'A')
            {
               deteccion();
            }
      }
   }
 
}

You have to replace XXXXXXXXX by the phone number you want to call.