Tenía un modem externo antiguo de 2400 b.p.s. que me regalaron y se me ocurrió la idea de usarlo para crear una alarma. Los bueno de los modems es que puedes interactuar con la línea telefónica para hacer llamadas.
La idea consiste en que un sensor de movimiento piroeléctrico de infrarrojos (PIR) detecte el movimiento de una persona en una sala, este informaría de la detección a un pic y este sería el encargado de llamar a un número de teléfono a través del modem.
El matería que he usado es:
- Sensor de movimiento piroeléctrico de infrarrojos (PIR) de sure electronics DC-SS502 ( http://www.sureelectronics.net/goods.php?id=932 )
- Microcontrolador PIC 16f628A ( http://www.microchip.com/wwwproducts/devices.aspx?ddocname=en010210 )
- Transceptor ds275 ( http://www.maxim-ic.com/datasheet/index.mvp/id/2929 )
- Una placa de topos, cable, un conector serie db9 macho y un modem externo
Para hacer el circuito lo más sencillo posible he usado un pic 16f628a dado que con él podemos ahorrarnos el poner un cristal de cuarzo externo, poder desactivar el pin MCLR y usar la USART que trae consigo (podría haber usado un pic 16f88 igualmente). También he usado el transceptor ds275 porque se puede comunicar con un puerto serie como el del modem sin añadirle ningún condensador como ocurre con el MAX232. Como no quería depender de una fuente de alimentación externa, he soldado unos cables al modem para obtener de este los 5 voltios necesarios para el pic y el transceptor y para la alimentación de 9 voltios del sensor PIR.
Este es el esquema del circuito:
El sensor PIR tiene una salida digital que va conectada al pin RB0 del pic, que se puede programar como interrupción, por lo que el pic puede permanecer en modo sleep hasta que recibe la interrupción del sensor y empezar a mandar los comandos AT para hacer la llamada de alarma. Como el PIC no puede por sí sólo interactuar con un puerto serie, el transceptor convierte las señales del PIC a señales RS232 para enviárselas al puerto serie del modem y viceversa. Una vez que se ha hecho la llamada y el modem detecta que se ha colgado la linea, devolverá un código numérico que el pic recibirá para volver a dejar el sistema en modo de detección.
Foto del conjunto:
Un video de demostración:
Lo que sucede en el video es lo siguiente: Se enciende el modem y el pic configura este para que no tenga eco los comandos, para que devuelva respuestas numéricas y que el altavoz esté desactivado, después de 15 segundos de espera para que el usuario pueda abandonar la habitación el pic se pone a esperar la detección de movimiento, cuando la detecta llama a un número de móvil prefijado para que el usuario reciba la alerta.
El código fuente del pic esta programado en CCS y es el siguiente:
main.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
#include "main.h" ESTADOS estado; volatile int8 dato; // se ha detectado un movimiento y se pasa al estado de alarma #INT_EXT void movimiento() { if(estado == DETECTA) { estado = ALARMA; } } // se ha detectado un carácter en la cola la USART #INT_RDA void lectura() { int8 valor; if(kbhit()) { valor = getc(); if(valor != '\r') { dato = valor; } } } // función genérica que pasa al estado de detección borrando cualquier interrupción anterior y activándola 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); // Ponemos a todos los pines del puerto B como entrada excepto el de salida de la USART set_tris_b(0xFB); // Empezamos por el estado de inicio estado = INICIO; // La interrupción debe ser cuando pasa de nivel bajo a nivel alto ext_int_edge( L_TO_H ); enable_interrupts(int_rda); enable_interrupts(global); // TODO: USER CODE!! for(;;) { switch(estado) { // En el estado de inicio inicializamos el modem para que no haga eco de los comandos, // los valores de respuesta sean numéricos y apague el altavoz del modem, esperando // 15 segundos para dejar salir al usuario de la sala y pasamos al estado de detección case INICIO: delay_ms(2000); printf("ATE0V0M0\r"); delay_ms(13000); deteccion(); break; // En el estado de detección esperamos la interrupción en modo sleep para consumir menos case DETECTA: sleep(); break; // Se desactiva la interrupción y marcamos el número de teléfono que queramos alertar case ALARMA: disable_interrupts(int_ext); dato = 'A'; printf("ATDTXXXXXXXXX\r"); estado = LLAMADO; break; // Esperamos a que termine la llamada para que vuelva al estado de detección case LLAMADO: if(dato != 'A') { deteccion(); } } } } |
Sólo comentar que XXXXXXXXX hay que sustituirlo por el número de teléfono al que queramos dar la alarma.