Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Nos complace que haya decidido conocer más sobre la Alarma Vecinal Técnica 1, una alarma
vecinal en curso de alcanzar calidad comercial con el aporte de usuarios y desarrolladores
independientes.
Basado en tecnología abierta, este dispositivo le permite que como usuario se interiorice en su
funcionamiento y pueda construirlo, mejorarlo, repararlo y adaptarlo a sus necesidades sin pedir
permiso ni pagar ningún tipo derecho de propiedad.
Si necesita ayuda puede comenzar leyendo la documentación, luego puede consultar a la comunidad
de desarrolladores, y también puede contactar a los desarrolladores originales. Tenga en cuenta, sin
embargo que es un esfuerzo comunitario y será muy valorado su aporte tanto en mejoras, como en
la solución de problemas. También tenga muy presente que este dispositivo, si bien fue diseñado, y
programado con dedicación y cuidado, ES EXPERIMENTAL, NO TIENE ABSOLUTAMENTE
NINGÚN TIPO DE GARANTÍA, NI SIQUIERA LA DE UTILIDAD O USO PARA UN FIN EN
PARTICULAR, Y USTED USA EL DISPOSITIVO Y/O EL DISEÑO A SU ENTERO RIESGO.
Todo el dispositivo tiene que colocarse en una caja estanca del tipo que se usa en las instalaciones
eléctricas y proveer las conexiones necesarias con el cable correspondiente, sellando los orificios
con silicona de buena calidad, si es que se colocará el dispositivo a la intemperie.
Para su adecuado funcionamiento se requiere una tarjeta SIM activa y se debe garantizar que
siempre esté en condiciones de emitir mensajes SMS. Este es un gasto fijo para la operación de la
alarma. El otro gasto fijo es el consumo eléctrico, pero la potencia consumida es mínima.
Una vez armado se deben revisar todas las conexiones eléctricas,cargar el software y luego verificar
que todo funcione. Esto se puede hacer de varias maneras, pero un camino posible es:
1. Revisar las conexiones eléctricas y asegurarse que llegue la alimentación adecuada a todos
los módulos, junto con el resto de las señales.
2. Insertar una tarjeta telefónica tipo SIM con una línea activa y capaz de emitir mensajes SMS
3. Con una computadora personal y un cable usb, cargar el software de la alarma en la placa
Wemos D1.
4. Cargar la app y conectar mediante Bluetooth. Si se pide un pin al conectar introducir 1234.
5. Verificar la conexión encendiendo y apagando la chicharra desde la app.
6. Dar de alta por lo menos un usuario y vincular por lo menos un llavero.
7. Accionar el llavero y verificar que encienda la chicharra y que llega el SMS de pedido de
ayuda.
8. A partir de este punto se puede instalar la alarma en su lugar definitivo.
9. Si hubo problemas, ver en este manual la sección “Solución de problemas”
Se sugiere colocar la alarma en un lugar despejado y con contacto visual con todos los sitios desde
donde se pretende activarla con los controles remotos.
Si bien las compañías comerciales suelen colocar sus dispositivos en postes telefónicos, de
iluminación, de distribución de energía, etc. se recomienda evitar estos emplazamientos por motivos
tanto legales como de posible riesgo eléctrico u otros. En su lugar será preferible un sitio adecuado
en la casa de un vecino, que además de estar despejado y ofrecer resguardo para el dispositivo, sea
accesible con facilidad ante la eventualidad de una reparación, expansión, etc.
Operación
La alarma debe tener suministro eléctrico permanente, debido a que debe permanecer siempre
encendida. Ante la eventualidad de un corte de energía eléctrica, el equipo cuenta con un paquete de
baterías de respaldo para continuar operativo, pero en tanto no haya electricidad de red, la chicharra
no estará disponible, aunque seguirá funcionando el envío de mensajes SMS para dar aviso de
cualquier evento.
La administración de la alarma estará a cargo del primer usuario ingresado, quien validará su
identidad accionando su llavero cuando desee entrar al modo de administrador. Este usuario será el
que dará de alta, o de baja a los demás usuarios.
Cada control remoto (llavero) habilitado, si es accionado hará que la alarma haga sonar la sirena por
cierto tiempo, y que luego envíe mensajes SMS a todos los demás usuarios solicitando ayuda. Si
esto ocurre, será la comunidad la que debe definir un protocolo de atención de este suceso. La
alarma sigue operativa luego de ser activada y no requiere ninguna atención especial.
Información para el desarrollador
Un usuario interesado puede convertirse en desarrollador si lo desea. De este modo, las
comunidades pueden adaptar este producto a sus necesidades agregando, modificando, quitando, o
mejorando características. Además, pueden corregir cualquier error ni bien se presenta, sin pedir
autorización a nadie.
Nuestra alarma es propiedad de cada una de las comunidades que las usan, y nos complace pensar
que nos enriqueceremos con los aportes de todos para conseguir un producto cada vez más
competitivo y fiable.
A continuación presentamos información para que los desarrolladores puedan comenzar su trabajo
de manera eficaz.
En principio podemos dividir el software en tres partes: 1) Configuración inicial, 2) bucle principal
y 3) Funciones. Esta organización se muestra en la figura siguiente
La configuración inicial determina los ajustes del hardware y del software necesarios para que el
equipo comience a trabajar.
El Bucle Principal es la parte del programa que se encarga de esperar las órdenes y de procesar los
acontecimientos conforme se van presentando.
Las funciones son procedimientos encargados de tareas específicas que se repiten varias veces a lo
largo del programa, y que por lo tanto, escriben una vez para que se usen cada vez que sea
necesario.
Modificar o corregir el programa puede significar interactuar con una o varias de estas partes.
1. Órdenes
2. Eventos
Las órdenes son instrucciones que le da el operador, ya sea por Bluetooth o por medio de una
computadora conectada por USB.
Los eventos implementados hasta ahora son las señales recibidas desde los llaveros.
Trama de órdenes
La trama se definió en etapas tempranas del proyecto y de ahí los nombres y el formato. Si bien
resulta útil y funcional, es posible que se modifique en el futuro. La trama es una secuencia de bytes
que está estructurada en un formato específico tal como se muestra
Los 2 primeros bytes representan la acción que se espera que ejecute el equipo y son obligatorios.
El resto de los bytes no es necesario usarlos todos, pudiendo utilizarse sólo los que hagan falta.
Comandos
Un comando es una secuencia de caracteres que el dispositivo interpreta realizando alguna acción
determinada. Los comandos vienen desde un dispositivo conectado por USB o Bluetoot contenidos
en la trama de órdenes
Los comandos se envían como una trama de bytes desde un programa terminal (como
HyperTerminal en plataforma PC, CuteCom en GNU/Linux, o Bluetooth terminal en Android -solo
modo administrador-) mediante una conexión USB (PC o GNU/Linux) o Bluetooth (Android).
El programa terminal debe configurarse a 9600 bps, 1 bit de stop, sin paridad, sin control de flujo y
para que envíe los caracteres CR/LF (Retorno de carro, línea nueva) al enviar la cadena de
caracteres.
Lista de comandos
0xAA: Envía un comando AT crudo al módulo SIM900 contenido en los bytes de mensaje de la
trama.
Ejemplo:
AA1234567890AT+CREG?
--o0o--
Ejemplo:
A1
--o0o--
Ejemplo:
A2
--o0o--
Ejemplo:
A3
--o0o--
Ejemplo:
BB
Ejemplo:
1A
--o0o--
Ejemplo:
1B
--o0o--
0x1C: Agrega un nuevo número de difusión para solicitar ayuda. El número debe venir contenido
en el campo de número telefónico de la trama. El número de llavero debe venir en los 10 bytes
siguientes. Y en los 40 bytes que siguen al número de llavero, debe venir el nombre y apellido del
usuario. Si en la los bytes de número de llavero se pone AAAAAAAAAA o aaaaaaaaaa, la alarma
pedirá capturar llavero.
1C11547028821593578521Juan Perez
1C1154702882AAAAAAAAAAJuan Perez
--o0o--
1D
Comentario: Muestra la lista completa de usuarios, con sus número telefónicos, sus
nombres y código de llavero.
--o0o--
Ejemplo:
1E
--o0o--
0x20: Busca si existe el número de llavero entre los guardados en el archivo de usuarios
Ejemplo:
20
Comentario: No implementado
--o0o--
Ejemplo:
21
--o0o--
Ejemplo:
30
Comentario: Activa el relé que enciende la bocina, sirena u otro medio de aviso de
potencia.
--o0o--
Ejemplo:
31
Comentario: Desactiva el relé que enciende la bocina, sirena u otro medio de aviso de
potencia.
--o0o--
0x40: En desuso
Ejemplo:
DD
--o0o--
3. Bucle principal
A continuación veremos qué código compone cada parte . Notar que al tratarse de un programa en
desarrollo, puede haber código innecesario o bajo prueba.
// Centro de mensajes
#define PIN_RF D3
// Pin donde se conecta el pin pwrkey del SIM900
// Pin donde se conecta el pin netlight del SIM900 (no se usa ahora)
// Para el caso de las cadenas, recordar que llevan los caracteres útiles
#define MAX_NUM 11
#define MAX_COM 3
#define RELE D0
/*
* pertenecer a un usuario
* *lista.
*/
/*
* Campos:
*
* Los campos son los siguientes:
*/
char trama_ord[MAX_TRA];
struct orden {
};
struct usuario {
};
Ajuste de parámetros de configuración
En la plataforma Arduino compatible es usual poner todos los parámetros de inicialización en la
función setup, como una manera de organizar el código. En este caso se inicializan los puertos de
comunicación con el módulo SIM900 (módulo celular) y el módulo Bluetooth. También se
inicializa el sistema de archivos SPIFFS.
void setup () {
receptorRF.enableReceive (D3);
Serial.begin (9600);
while (!Serial){
SerialSim.begin (115200);
while (!SerialSim) {
Serial.print (".");
if (SerialSim) {
delay (10);
SerialBT.begin (9600);
while (!SerialBT) {
Serial.print (".");
if (SerialBT) {
if (SPIFFS.begin ()){
}
else {
Bucle principal
El bucle principal es la parte del programa que procesa las órdenes y atiende los eventos. En la plataforma
Arduino compatible, no es necesario crear explícitamente un bucle, si no que de eso se ocupa la función
loop que se repite en tanto haya alimentación.
void loop () {
int c; // Caracter
int x = 0;
float llavero = 0;
usuario usuario; // estructura de datos del usuario
orden a; // estructura de la trama de control
//Inicio la estructura de control a valores por defecto
a.comando[0] = '\0';
a.numero[0] = '\0';
a.mensaje_sms[0] = '\0';
trama_ord[0] = '\0';
}
}
}
// Borro cualquier lectura previa del llavero
receptorRF.resetAvailable ();
// Si leí una trama, la muestro. Sólo para depuración.
if (*trama_ord)
{
Serial.println (trama_ord);
a = procesarTrama ();
trama_ord[0] = '\0';
Serial.println ("------main------");
Serial.println (a.comando);
Serial.println (a.numero);
Serial.println (a.mensaje_sms);
Serial.print ("Comando::");
Serial.println (aNumero (a.comando, 16));
}
case 0x30:
// Encender bocina
Serial.println ("Bocina encendida...");
digitalWrite (D8, HIGH);
break;
case 0x31:
// Apagar bocina
Serial.println ("Bocina apagada...");
digitalWrite (D8, LOW);
break;
case 0x40:
//aCadena(12345678);
break;
case 0xDD:
// Quita un número de difusión
bajaDifusion (a.numero);
break;
default:
break;
}
usuarios.close (); //Cierro el archivo de usuarios y me voy ;-)
}
Funciones
Las funciones son bloques de código que hacen una tarea específica y por lo general se usan varias veces en
el programa. Se escriben para ordenar y ahorrar código. Las funciones están comentadas lo mejor posible,
de manera que cada una tiene una explicación de qué y como cumple determinada tarea. Sin dudas, la mayor
parte del código reside en las funciones.
/*
* =======================================
* leerTrama()
* =======================================
*/
int leerTrama () {
// Relleno el array de la trama con el flujo de datos que viene desde
// la PC o el celu
int x = 0;
// Leo un comando desde la terminal del PC
while (Serial.available () > 0 && x < MAX_TRA)
{
trama_ord[x] = Serial.read ();
delay (5);
x++;
}
// Agrego terminador de cadena
trama_ord[x] = '\0';
// Si leí caracteres, salgo.
if (x) {
return 1; // verdadero
} else {
//return 0; // falso
}
/*
* =======================================
* procesarTrama()
* =======================================
*/
orden procesarTrama () {
// Toma la cadena 'trama_ord' que viene desde el móvil o la PC y la usa
// para rellenar los campos de la estructura 'orden'
// La variable 'trama_ord' tiene el siguiente formato (hasta ahora)
// byte 0 y 1: orden. Campo de longitud fija obligatoria
// byte 2 a 15: nro de teléfono. Campo de longitud fija obligatoria.
// byte 16 y siquientes: mensaje. Campo de longitud variable
// Declaro variables
// x es una variable de uso general;
// offset mantiene el desplazamiento sobre la variable trama_ord
// orden guarda los distintos campos de la trama trama_rod
int x = 0, offset = 0;
orden a;
// Comienzo a explorar trama_ord
// Copio los caracteres 0 a 1 a a.comando; en el caracter 2 de a.comando
coloco un '\0'
for (x = 0; x < (MAX_COM - 1) && trama_ord[x]; x++) {
a.comando[x] = trama_ord[x];
}
a.comando[x] = '\0'; // terminador
offset = x;
for (x = offset; trama_ord[x]; x++) {
a.mensaje_sms[x - offset] = trama_ord[x];
}
a.mensaje_sms[x - offset - 2] = '\0'; // Descuento dos porque parece que
cuenta dos veces el terminado
return a;
}
/*
* =======================================
* escribirSIM900
* =======================================
*/
/*
* =======================================
* aNumero
* =======================================
*/
long int aNumero (char *cadena, int base) {
// Pasa una cadadena que representa un número de base 'base', a un
// entero decimal. En este momento 'base' sólo puede ser 16 porque sólo
// se ha implementado la función hexaAdecimal(); Habría que implementar
// las funciones decimalAdecimal(), binarioAdecimal() y octalAdecimal().
int longitud = 0; // longitud de la cadena
int pos = 0; // posición de un dígito dentro del número,
// comenzando por la posición cero en la extrema
// derecha y creciendo hacia la izquierda.
long int numero = 0;
// Base 16 y base 10 deberían poder calcularse
// Obtengo la longitud de la cadena contando hasta que encuentro el
// terminador nulo
for (longitud = 0; *(cadena + sizeof (char) * longitud); longitud++){
}
// Recorro la cadena de derecha a izquierda. Es decir suponiendo que la
// cadena representa un número, comienzo por el dígito 0
// (menos significativo), y termino por el que está más
// a la izquierda (el más significativo), 'pos' representa la posición
// de un dígito
/*
* =======================================
* leerSIM900()
* =======================================
*/
void leerSIM900 () {
// Leo desde el SIM900 y escribo al celu vía el módulo
// Bluetooth
int x = 0;
char c;
for (;SerialSim.available () && x <100; x++) {
if (x > 100) {
Serial.println ("\nMuchos datos!");
return;
}
delay (5);
c = SerialSim.read ();
delay (5);
//yield();
// Hago eco al móvil
SerialBT.write (c);
// Hago eco a la PC
Serial.write (c);
//yield();
}
}
/*
* =======================================
* escribirSIM900_RAW
* =======================================
*/
void escribirSIM900_RAW (char *cadena) {
// Esta función escribe al SIM900 pero sin los carateres de retorno de
// carro y nueva línea
int x = 0;
char c;
//Serial.print("escribirSIM900::"); Serial.println(cadena);
// Escribo al SIM900 desde la compu. Hago eco a la PC y al móvil
while (*(cadena + sizeof (char) * x))
{
// Leo el comando de un caracter a la vez.
c = *(cadena + sizeof (char) * x);
// Hago eco a la PC
Serial.write (c);
// Envío al sim900
SerialSim.write (c);
yield ();
// Hago eco al móvil
SerialBT.write (c);
x++;
}
}
/*
* =======================================
* pwrkeySIM900
* =======================================
*/
void pwrkeySIM900 (int pwrkey_pin) {
// Actualmente esta función no se usa. Probablemente se elimine en nuevas
// versiones del software
// Lleva el pin pwrkey (pin 1) del SIM900 a BAJO por 1 segundo y luego
// lo deja en ALTO. Esto tiene como efecto conmutar el estado del
// SIM900 de encendido a apagado o viceversa.
// Serial.println("\pwrkey");
pinMode (PIN_PWRKEY, OUTPUT);
digitalWrite (PIN_PWRKEY, LOW);
delay (1200);
digitalWrite (PIN_PWRKEY, HIGH);
pinMode (PIN_PWRKEY, INPUT);
}
/*
* =======================================
* sincronizarSIM900()
* =======================================
*/
// Actualmente esta función no se usa. Probablemente se elimine en nuevas
// versiones del software
void sincronizarSIM900 () {
delay (1000);
pwrkeySIM900 (PIN_PWRKEY); // Apago SIM900
delay (1000);
leerSIM900 ();
pwrkeySIM900 (PIN_PWRKEY); // Prendo SIM900
delay (1000);
escribirSIM900 ("AT+CPOWD=1"); // Apago por software
delay (1000);
pwrkeySIM900 (PIN_PWRKEY); // Prendo SIM900
}
/*
* =======================================
* formatearFlash()
* =======================================
*/
int formatearFlash () {
/*
* Formatea la memoria flash de la Wemos D1
* retorna true para éxito y true para fracaso
*/
Serial.println ("\n formatearFlash()");
if (SPIFFS.format ()) {
Serial.println ("SPIFFS: formateado");
return true;
} else {
Serial.println ("SPIFFS: Error al formatear");
return false;
}
}
/*
* =======================================
* crearArchivo()
* =======================================
*/
int crearArchivo () {
/*
* Crea un archivo nuevo para escribir. El nombre del archivo está codificado en
* el programa para evitar problemas
*/
usuarios = SPIFFS.open (lista, "w");
if (!usuarios) {
Serial.println ("Error: No se pudo crear el archivo");
return false; // Error
} else {
Serial.println ("Archivo creado!");
usuarios.close ();
Serial.println ("Archivo cerrado");
return true;
}
}
/*
* =======================================
* escribirArchivo()
* =======================================
*/
int escribirArchivo (char *cadena) {
// Esta función escribe una cadena que contiene los datos del usuario
// de acuerdo al formato siguiente
/*
* Campos:
* [10- NNLLLLLLLL];[8 - llavero];[45- Nombre y apellido];
*
*/
//Aviso a la PC
Serial.println ("Escribiendo...");
//Escribo en el archivo
usuarios.print (cadena);
usuarios.print ("; ; \0\n");
return 0;
}
/*
* =======================================
* altaDifusion()
* =======================================
*/
void altaDifusion (char *cadena) {
// Esta función ingresa un usuario nuevo. Y si corresponde también vincula
// un llavero.
/*
* Campos:
* [10- NNLLLLLLLL];[10 - llavero];[40- Nombre y apellido];
*
* Los campos son los siguientes:
* 10 caracteres para el número de teléfono: dos de código de área y 8
* del número local
*
* 10 caracteres para guardar el número de llavero
*
* 43 caracteres para el nombre y apellido u otros datos futuro
*
* 1 caracter para el terminador nulo.
*
* En esta función se descarta todo lo que hay después del primer punto y coma
*/
int x = 0, z=0;
char c, llavero[11];
File usuarios = SPIFFS.open (lista, "a");
if (!usuarios) {
Serial.println ("Error al abrir archivo");
SerialBT.println("Error al abrir archivo");
} else {
Serial.println ("Escribiendo...");
SerialBT.println("Escribiendo...");
//Escribo en el archivo
//Descarto los dos bytes del comando de la trama de entrada
cadena++;
cadena++;
// Escribo a la flash
for (x = 0; x < 64 && (*cadena); x++){
// Tomo un valor de la trama de entrada
c = (char) (*cadena);
if((c=='A' || c=='a') && (x>=10 && x<=17)){
// Estoy en la parte del número de llavero
// Si en la trama viene una 'a' o una 'A' pido llavero
aCadena(capturarLlavero(), llavero );
for(;x<=17;x++){
usuarios.write(llavero[x-10]);
Serial.write(llavero[x-10]);
SerialBT.write(llavero[x-10]);
cadena++;
}
}else{
Serial.write (c);
SerialBT.write(c);
usuarios.write (c);
cadena++;
}
}
// Si la cadena se termina antes de ocupar los 63 bytes, completo
// con ceros hasta los 64
for (; x <= 64; x++){
usuarios.write (0x0);
}
usuarios.close ();
Serial.println ("Archivo cerrado");
}
}
/*
* =======================================
* bajaDifusion()
* =======================================
*/
void bajaDifusion (char *cadena) {
// Todavía no esta completamente implementada
/*
* En 'cadena' viene el n2úmero que se quiere borrar. Este número
* se busca entre los archivados. Si se encuentra, se sobreescribe con
* ceros, lo cual hará que esa entrada no sea tenida en cuenta por las
* funciones que envían los sms de ayuda. Sin embargo,
* una entrada con número puesto a cero, estará libre para ser
* sobre escrita para almacenar una nueva entrada.
*/
File usuarios = SPIFFS.open (lista, "r");
int x;
char c, *p;
int long_cadena = 0;
p = cadena;
if (!usuarios) {
Serial.println ("No se pudo abrir el archivo");
} else {
Serial.println ("Leyendo...");
Serial.println (cadena);
Serial.println ("--Loop--");
/*
* =======================================
* listarUsuarios()
* =======================================
*/
void listarUsuarios () {
// Lista los usuarios grabados en el archivo de usuarios
File usuarios = SPIFFS.open (lista, "r");
int x;
char c;
if (!usuarios) {
Serial.println ("No se pudo abrir el archivo");
} else {
Serial.println ("Leyendo...");
for (x = 0; x < usuarios.size (); x++) {
c = (char) usuarios.read ();
if (c) {
Serial.write (c);
};
}
usuarios.close ();
Serial.println ("Archivo cerrado");
}
}
/*
* =======================================
* buscarLlavero()
* =======================================
*/
struct usuario buscarLlavero (long int llavero) {
// Busca si un llavero está en la lista de usuarios
File usuarios = SPIFFS.open (lista, "r");
struct usuario usuario;
int x, n = 1;
char a;
Serial.println("===buscarLlavero()===");
if (!usuarios) {
Serial.println ("No se pudo abrir el archivo");
} else {
Serial.println ("Leyendo...");
// Exploro el archivo completo
for (n = 1; (n * 64) <= usuarios.size (); n++){
for (x = 0; x <= 64; x++){
a = (char) usuarios.read ();
// guardo el teléfono
if (x >= 0 && x<10){
usuario.telefono[x] = a;
usuario.telefono[10] = '\0'; // terminador
}
/*
* =======================================
* solicitarAyuda()
* =======================================
*/
void solicitarAyuda (char *mensaje_de_ayuda) {
/* Versión vieja. En desuso. Se eliminará en nuevas ediciones.
* Envía un SMS de solicitud de ayuda a todos los usuarios
*/
File usuarios = SPIFFS.open (lista, "r");
int x, n = 0;
char numero[20], c = 0;
if (!usuarios)
{
Serial.println ("No se pudo abrir el archivo");
}
else
{
Serial.println ("Leyendo...");
for (x = 0; x < usuarios.size (); x++) // Recorro todo el archivo byte
a byte
{
c = (char) usuarios.read (); // Leo un byte del archivo
numero[n] = c; // Guardo los caracteres de a uno en un vector
n++; // Incremento el índce del vector para guardar
el caracter siguiente
if (c == ';' || n == 10)
{ // Si encuentro un punto y coma, se terminó el
// número
numero[n] = 0x0; //Agrego terminador nulo
n = 0;
Serial.print("Numero::");
Serial.println (numero);
}
usuarios.close (); // Cierro el archivo y me voy
Serial.println ("Archivo cerrado");
}
}
/*
* =======================================
* solicitarAyuda2()
* =======================================
*/
void solicitarAyuda2 (char *mensaje_de_ayuda) {
/* Versión nueva
* Envía un SMS de solicitud de ayuda a todos los usuarios
*/
int x, n = 0;
char numero[10], a = 0;
if (!usuarios){
Serial.println ("No se pudo abrir el archivo");
} else {
Serial.println ("Leyendo...");
for (n = 1; (n * 64) <= usuarios.size (); n++){
for (x = 0; x <= 64; x++){
a = (char) usuarios.read ();
// guardo el teléfono
if (x >= 0 && x<10){
numero[x] = a;
}
if(x==10){
//Solicitar ayuda
numero[10] = 0x0; // terminador
delay(200);
enviarSMS (numero, CENTRO_DE_MENSAJES,
mensaje_de_ayuda);
}
}
}
}
usuarios.close (); // Cierro el archivo y me voy
Serial.println ("Archivo cerrado");
return;
}
/*
* =======================================
* enviarSMS()
* =======================================
*/
void enviarSMS (char *numero, char *centro_de_mensajes, char *texto) {
// Envía un SMS compuesto por *texto, al *numero indicado, y con el
// *centro_de_mensajes
}
/*
* =======================================
* testSIM900()
* =======================================
*/
void testSIM900(){
// Interroga y muestra varios datos del SIM900
Serial.println("Probando SIM900...");
Serial.println ("Estado del PIN");
escribirSIM900 ("AT+CPIN?");
delay (200);
leerSIM900 ();
Serial.println ("Versión:");
escribirSIM900 ("AT+CGMR");
delay (100);
leerSIM900 ();
/*
* =======================================
* capturarLlavero()
* =======================================
*/
unsigned long capturarLlavero(){
//Entro en un loop hasta que aparece un llavero
//La alarma queda desactivada mientras no se salga de esta función
Serial.println("CUIDADO: ALARMA DESACTIVADA HASTA TERMINAR CAPTURA");
SerialBT.println("CUIDADO: ALARMA DESACTIVADA HASTA TERMINAR CAPTURA");
unsigned long valor;
for(; !receptorRF.available ();){
delay(10);
}
valor = receptorRF.getReceivedValue ();
receptorRF.resetAvailable ();
return valor;
/*
* =======================================
* aCadena()
* =======================================
*/
void aCadena(unsigned long n, char (&s)[11]){
/*
* Esta función toma un entero largo y lo convierte en una cadena de
* 8 dígitos. Se usa para convertir el número del código del llavero
* en una cadena y guardarlo en un archivo
*/
float a;
int c, x;
//static char s[11];
a = (float)n;
for(x = 0;x<8; x++){
c = ((int)(n/pow(10,x)))*pow(10,x) - ((int)(n/pow(10,x+1)))*pow(10,x+1);
c = c/(pow(10,x));
switch (c) {
case 0:
s[7-x]='0';
break;
case 1:
s[7-x]='1';
break;
case 2:
s[7-x]='2';
break;
case 3:
s[7-x]='3';
break;
case 4:
s[7-x]='4';
break;
case 5:
s[7-x]='5';
break;
case 6:
s[7-x]='6';
break;
case 7:
s[7-x]='7';
break;
case 8:
s[7-x]='8';
break;
case 9:
s[7-x]='9';
break;
}
}
s[x]='\0';
Serial.println(s);
return;
}