También consideré el cambio de las pantallas LCD16x02 por unas Nokia LCD bastante mas curiosas, por la cantidad de lineas que presentan para poder presentar más datos. El integrar el módulo Nokia LCD 5110 es sencillo siguiendo el siguiente esquema:
Una vez conseguido esto, me he decidido también por colocar un buzzer que emita una señal de llamada para sustituir a los RING de los teléfonos, ya que es imposible evitar que al menos suenen dos veces antes de que el CallerID funcione. Así que he insertado código para que el sistema reconozca los RING recibidos, y haga sonar el buzzer como una llamada de teléfono, si el numero no está bloqueado, a partir del segundo RING. Los teléfonos deberían estar en mute o en ring muy bajo, para que no molestaran las llamadas bloqueadas. Realmente dichas llamadas se pueden bloquear para que no suenen haciendo que el modem coja la llamada entrante (hay una parte del sketch que contiene el código para hacerlo, en modo desactivado con slash, para activar si se desea), pero como en las pruebas usando el móvil vi que era factible el dejar las llamadas sin coger y a la vez impedir que el teléfono suene, pues me he decidido por esto último.
El sistema ya montado tiene el siguiente aspecto:
El resultado final del sketch es el siguiente:
/* Proyecto de discriminador de llamadas telefonicas no deseadas, tras la llamada se identifica el
numero llamante y se compara con los que están anotados en un fichero almacenado en una tarjeta SD. Si
coincide con alguno, la llamada es bloqueada. Ademas graba automáticamente los números que han llamado
y que posteriormente pueden seleccionarse con la botonadura para ser bloqueados. Al necesitar dos RING para
poder leer el CALLERID lleva un buzzer incorporado que suena a partir del tercer RING, para evitar
que suenen los telefonos siempre un par de veces (hacer mute en los telefonos para evitar el ring).
El hardware necesario es un Arduino Uno, un modem con CallerID (en mi caso US Robotics 56k o un Conceptronics
C55E de 56k), un modulo SD YL-30, una tarjeta SD, un modulo Serie HC05, un modulo LCD de 16x2 y
una botonadura tipo Keypad DIY de resistencias (una botonadura simple con tres resistencias de 3K en serie
conectando GND a Pin A0, p.e.).
Se usa un modulo HC05 master bluetooth para comunicarse con un modem bluetooth hc06 conectado al modem serie, que
a su vez está conectado a la linea de telefono.
La cadena del Caller ID detectada por el modem es siempre del tipo siguiente:
DATE = 0422 //MMDD
TIME = 1945 //HHMM
NMBR = 659278358 //Numero llamante
Conexion modulo hc05 a Arduino es : RX-TX(Pin digital 1) y TX-RX(Pin digital 0)
Conexion pines modulo SD a Arduino:
modulo: GND 3.3v 5v. CS MOSI SCK MISO GND
Arduino:GND 3.3V 5V. 10 11 13 12 GND
La botonadura es del tipo resistencias en serie unidas a pin A0 y GND, y boton uniendo PIN RESET a GND.
El buzzer está conectado al Pin A1 - GND - 5v
*/
// LCD5110_NumberFonts
// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
// web: http://www.RinkyDinkElectronics.com/
//
// This program is a demo of the included number-fonts,
// and how to use them.
//
// This program requires a Nokia 5110 LCD module.
//
// It is assumed that the LCD module is connected to
// the following pins using a levelshifter to get the
// correct voltage to the module.
// CLK/ SCK - Pin 7
// MOSI - Pin 6
// DC - Pin 5
// RST - Pin 3
// CE/CS - Pin 4
//
#include <LCD5110_Basic.h>
LCD5110 myGLCD(7,6,5,3,4);
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];
#include <SdFat.h>//CS en pin 10
SdFat sd;
SdFile myFile;
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btn3 0
#define btnUP 1
#define btn2 2
#define btnLEFT 3
#define btn1 4
#define btnNONE 5
/// Guardamos en que entrada de arduino esta conectado el pin CS del modulo.
const int chipSelect = 10;
char nmbrstring[ ] = "NMBR";
char ringstring[ ] = "RING";
char numerodete[10];
char numerotst[10];
char numllam[10];
char charBuf[10];
char charBuf2[10];
char charThree[10];
int numblock = 50;//cantidad de lineas de numeros del fichero
int i = 0;
int i2 = 0;
int llamadas = 0;// Contador de llamadas, debe ser 0. Otro valor es para pruebas.
int ringer = 2;// Contador de ring, los 2 primeros no se detectan
int pin = A1;//pin conexion buzzer
String stringThree;
byte Bin2;
unsigned long tAntes = 0;
unsigned long tAntes2 = 0;
unsigned long tAntes3 = 0;
unsigned long tAntes4 = 0;
unsigned long tAntes5 = 0;
unsigned long tAntes6 = 0;
long time_now = 0;
//Sonido del buzzer
void playNote(int noteInt, long length, long breath = 20) {
length = length - breath;
buzz(pin, 2000 , length); // Valor 2000 es agudo y fuerte, 50 es grave y flojo
if(breath > 0) { //take a short pause or 'breath' if specified
delay(breath);
}
}
void setup()
{
myGLCD.InitLCD();
//myGLCD.clrScr();
pinMode(A0, INPUT_PULLUP); // sets analog pin for input
//digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT); // set a pin for buzzer output
myGLCD.setFont(SmallFont);
myGLCD.print("LCD Activado", 0, 0); // print a simple messag
delay (2000);
// Configuramos el puerto serie (esta version NO usa Serie Virtual)
Serial.begin(38400);
while (!Serial) {
; // Espera para conexion puerto serie, solo necesario para leonardo
}
myGLCD.clrScr();
myGLCD.print("Setup is Ready", 0, 0);
delay(2000);
//Iniciamos la SD
//Serial.print("Iniciando SD...");
//Serial.print("\n");
myGLCD.clrScr();
myGLCD.print("Iniciando SD...", 0, 0);
// El pin CS por defecto de la placa arduino debe ser configurado como salida
// aunque no se use (10 en la mayoria de las placas, 53 en Arduino Mega).
pinMode(10, OUTPUT);
// Si ha habido error al leer la tarjeta informamos por el puerto serie.
if (!sd.begin(chipSelect, SPI_HALF_SPEED))
{
//Serial.println("Error inicializar SD!");
myGLCD.print("Error SD...", 0, 20);
sd.initErrorHalt();
delay(2000);
myGLCD.clrScr();
myGLCD.print("PULSE RESET", 0, 40);
pinMode(10, INPUT);
delay(1000);
return;
}
myGLCD.print("SD ini...OK", 0, 20);
delay(2000);
//REcreando fichero RECIB.TXT
if (!myFile.open("RECIB.TXT", O_RDWR)) {
myGLCD.print("Error SD write", 0, 20);
delay(2000);
}
myFile.println("111111111");
delay(200);
myFile.close();// close the file:
myGLCD.clrScr();
myGLCD.print("RECIB.TXT ini", 0, 10);
delay(2000);
myGLCD.print("OK", 0, 30);
delay(2000);
myGLCD.clrScr();
myGLCD.print("Start Modem....", 0, 0);
// Iniciamos los comandos Hayes para configurar el modem
Serial.print("ATZ\r\n");
delay(4000);
myGLCD.print("4.", 0, 20);
Serial.print("AT+VCID=1\r\n");//Conceptronics CID ON
//Serial.print("AT#CID=1\r\n");//USR Robotics CID ON
delay(2000);
myGLCD.print("3.", 10, 20);
Serial.print("ATS7=5\r\n");//USR Robotics Answer Wait 7 seg
delay(2000);
myGLCD.print("2.", 20, 20);
Serial.print("ATS0=0\r\n");//USR Robotics Auto Answer OFF
delay(2000);
myGLCD.print("1.", 30, 20);
Serial.print("AT+FAE=1\r\n");//USR Robotics Adaptative Answer/Silent Answer
delay(2000);
myGLCD.print("OK", 40, 20);
delay(2000);
digitalWrite(pin, HIGH);
playNote(1,100);
digitalWrite(pin, LOW);
}
void loop()
{
static char buffer[20];
buttonselect();// Selector botones
myGLCD.setFont(SmallFont);
if (readline(Serial.read(), buffer, 80) > 0)
{
//Deteccion del numero llamante leido por puerto serie
char* numero1 = strchr(buffer, 'NMBR =');
char* prefinmbr = strtok(buffer, " =");
char* numero2 = strchr(numero1, ' ');
if(strcmp(prefinmbr, nmbrstring) == 0)//Detectamos la cadena NMBR que contiene el numero llamante
{
//Lector de numero
char* numerodete = numero2;//detecta numero con 1 espacio al inicio
String stringOne = numerodete;//convierte numero char a string
stringOne.trim();//elimina el espacio del inicio del número
myGLCD.clrScr();
myGLCD.print("Num.llamante:", 0, 0);
myGLCD.print("*********", 0, 20);
//myGLCD.print(charBuf, 0, 20);
stringOne.toCharArray(charBuf, 10);//convierte el numero string a char para strcmp
//ringer = 2;//Pone a 0 el contador de rings
myGLCD.print(stringOne, 0, 20);//Presenta en numero detectado
//Inicio codigo escritura llamadas recibidas
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
// if the file opened okay, write to it:
if (!myFile.open("RECIB.TXT", O_RDWR | O_CREAT | O_AT_END)) {
myGLCD.print("Error SD write", 0, 30);
}
myFile.println(stringOne);
delay (200);
myFile.close();// close the file:
llamadas++;// acumulado de numero de llamadas
myGLCD.print("Llamadas.....", 0, 40);
myGLCD.printNumI(llamadas, 60, 40);
myGLCD.print("WCOK", 60, 20);//Presenta el OK de grabacion numero detectado
//Mantiene el tiempo a 0 mientras se pulsa boton lectura
long time_now = millis();
tAntes = time_now;
tAntes2 = time_now;
tAntes3 = time_now;
tAntes4 = time_now;
// fin codigo escritura llamadas recibidas
//Inicio seccion lectura fichero numeros bloqueados.
char Ruta[9] = {'B', 'L', 'O', 'Q', '.', 'T', 'X', 'T', '\0'};//establece nombre fichero tlfs bloqueados
for(int i = 0; i < numblock; i++)// secuencialmente se lee cada una de los numeros del fichero
{
//Leemos linea de archivo en la SD
String numerotst = ReadFile(i,Ruta);
String stringTwo = numerotst;
stringTwo.toCharArray(charBuf2, 10);// convertimos string to char para strcmp
if(strcmp(charBuf, charBuf2) == 0)// comparamos el numero detectado con el leido en el fichero
{
myGLCD.clrScr();
myGLCD.print("Numero detec.:", 0, 0);
myGLCD.print(stringTwo, 0, 20); // Muestra el numero bloqueado
myGLCD.print("**BLOQUEADO**", 0, 30);//Presenta señal numero bloqueado
ringer = 20;//Impide que suene el buzzer
/* //Codigo activacion del modem para contestar y colgar
Serial.print("ATA\r\n");//Coge el tlf
delay(2000);
Serial.print("ATH1\r\n");//Cuelga el tlf
*/
delay (4000);
}// Fin deteccion numero bloqueado
}//Fin bucle lectura numeros bloqueados SD
}//Fin deteccion de llamada NMBR
//Deteccion de los RING para activar el buzzer
if(strcmp(buffer, ringstring) == 0)//Detectamos la cadena RING
{
/* Test cadena detectada
lcd.clear();
lcd.setCursor(0,0);
lcd.print(buffer);
lcd.print(ringer);
*///Fin test
ringer++;
//myGLCD.printNumI(ringer, 0, 35);//Print num rings
if(ringer > 3 && ringer < 15)//detector de rings para hacer sonar el buzzer
{
digitalWrite(pin, HIGH);
playNote(1,100);
playNote(1,200);
playNote(1,100);
playNote(1,100);
playNote(1,200);
playNote(1,100);
playNote(1,100);
playNote(1,200);
playNote(1,100);
digitalWrite(pin, LOW);
}
}
//Fin deteccion RING
}//Fin lectura buffer serie
//Timer Reponedor a 0 de rings
long time_now = millis();
if ((long)(time_now - tAntes6) > 80000)//Temporizador 80 seg para poner rings a 0
{
tAntes6 = time_now;
ringer = 2;
}
/*Test rings status
lcd.setCursor(0,15);
lcd.print(ringer);
*///Fin test
}// Fin LOOP
// Codigo de lectura de los telefonos bloqueados en la SD
String ReadFile(int Linea,char Ruta[]){
int Lin=0;
String Resultado;
byte Bin;
if (!myFile.open(Ruta, O_RDWR)) {
myGLCD.print("SD Read Error", 0, 0);
delay (2000);
myFile.close();return Resultado;
}
while (myFile.available()){
Bin=myFile.read();
if (Bin==13){Lin++;myFile.read();}
else
{
if (Lin==Linea){Resultado=Resultado+(char(Bin));}
if (Lin>Linea){myFile.close();return Resultado;}
}
}
myFile.close();return Resultado;
}
/// AÑADIDO CONTROL BOTONADURA Y GRABADO NUMEROS BLOQUEADOS SD
void buttonselect()
{
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btn3:
{
myGLCD.clrScr();
//LcdCharacter(adc_key_in);
myGLCD.print("Numero Block", 0, 0);
bloquear();
delay(500);
break;
}
case btn2:
{
myGLCD.clrScr();
//gotoXY(0,1);
//LcdCharacter(adc_key_in);
myGLCD.print("Bloquear Numero?", 0, 0);
myGLCD.print("NO", 0, 40);
myGLCD.print("X", 30, 40);
myGLCD.print("SI", 60, 40);
delay(500);
break;
}
case btn1:
{
//gotoXY(7,0);
//myGLCD.print("Bloquear");
leer();
/*myGLCD.clrScr();
gotoXY(0,1);
LcdCharacter(adc_key_in);
myGLCD.print("SELECT");*/
break;
}
case btnNONE:
{
long time_now = millis();
if ((long)(time_now - tAntes) > 10000) // regulador de tiempo medida datos y presentacion lcd
{
myGLCD.clrScr();
myGLCD.print("Waiting call...", 0, 0);
myGLCD.print("Llamadas..", 0, 40);
myGLCD.printNumI(llamadas, 60, 40);
tAntes = time_now;
}
if ((long)(time_now - tAntes2) > 1000)//Blink de * para indicar funcionamiento normal
{
myGLCD.print("****************", 0, 10);
tAntes2 = time_now;
}
if ((long)(time_now - tAntes3) > 1500)
{
myGLCD.print("* * * * * * * * ", 0, 10);
tAntes3 = time_now;
}
//Reponedor a 0 de lectura llamadas si inactividad en botones
if ((long)(time_now - tAntes4) > 20000)
{
i2 = 0;
tAntes4 = time_now;
}
if ((long)(time_now - tAntes5) > 1800000) //RESETEO MODEM CADA 30 MINUTOS
{
modemreset();
tAntes5 = time_now;
ringer = 2;
}
break;
}
}
}
void leer()
{
char Ruta[10] = {'R', 'E', 'C', 'I', 'B', '.', 'T', 'X', 'T', '\0'};//establece nombre fichero tlfs bloqueados
String numllam = ReadFile(i2,Ruta);//Leemos linea de archivo como char en la SD
//Proceso conversion de string to char para poder grabar los datos leidos
String stringThree = numllam; //convertir char to string
stringThree.toCharArray(charThree, 10);// convertimos string to char
delay(500);
myGLCD.clrScr();
myGLCD.print("Numero Leido.....", 0, 0);
myGLCD.print(".................", 0, 10);
myGLCD.printNumI((llamadas + 5)- i2, 40, 10);
//gotoXY(0,1);
//myGLCD.print(" "); // Muestra el numero leido
myGLCD.print(charThree, 0, 30); // Muestra el numero leido
//myGLCD.print("..", 75, 0);
delay (500);
i2++;
//Mantiene el tiempo a 0 mientras se pulsa boton lectura
long time_now = millis();
tAntes = time_now;
tAntes2 = time_now;
tAntes3 = time_now;
tAntes4 = time_now;
if (i2 > (llamadas + 5))
{
i2 = 0;
llamadas = 0;
delay (1000);
myGLCD.clrScr();
myGLCD.print("Borrando las", 0, 0);
myGLCD.print("LLamadas...", 0, 10);
if (!myFile.open("RECIB.TXT", O_RDWR | O_CREAT)) {
myGLCD.clrScr();
myGLCD.print("Error SD write", 0, 10);
delay(2000);
myGLCD.print("PULSE RESET", 0, 20);
delay(2000);
}
//Borrando fichero RECIB.TXT
myFile.remove();//borra fichero
delay(2000);
myFile.close();
//REcreando fichero RECIB.TXT
if (!myFile.open("RECIB.TXT", O_RDWR | O_CREAT)) {
myGLCD.print("Error SD write", 0, 10);
delay(2000);
myGLCD.clrScr();
myGLCD.print("PULSE RESET", 0, 20);
delay(2000);
}
myFile.println("111111111");
delay(200);
myFile.close();// close the file:
myGLCD.clrScr();
myGLCD.print("RECIB.TXT ini", 0, 0);
delay(2000);
myGLCD.print("OK", 0, 10);
delay(2000);
}
}
//funcion para escribir el número leido de RECIB.TXT y grabarlo en
//el fichero de numeros bloqueados BLOQ.TXT
void bloquear()
{
if (!myFile.open("BLOQ.TXT", O_RDWR | O_CREAT)){
myGLCD.print("Error SD write", 0, 0);
sd.initErrorHalt();
delay(2000);
myGLCD.print("PULSE RESET", 0, 10);
pinMode(10, INPUT);
delay(1000);
}
myFile.println(charThree);
delay(200);
myFile.close();
myGLCD.clrScr();
myGLCD.print("Numero bloqueado", 0, 0);
myGLCD.print("*********", 0, 20); // Limpia espacio numero
myGLCD.print(charThree, 0, 20); // Muestra el numero bloqueado
myGLCD.print("**BLOQUEADO**", 0, 30);
delay(2000);
}
//Sistema de lectura del puerto serie
int readline(int readch, char *buffer, int len)
{
static int pos = 0;
int rpos;
if (readch > 0) {
switch (readch) {
case '\n': // Ignore new-lines
break;
case '\r': // Return on CR
rpos = pos;
pos = 0; // Reset position index ready for next time
return rpos;
default:
if (pos < len-1) {
buffer[pos++] = readch;
buffer[pos] = 0;
}
}
}
// No end of line has been found, so return -1.
return -1;
}
// fin programa lectura puerto serie
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the sensor
//Valores para botonadura simple de 3 resistencias de 3k Ohm en serie
if (adc_key_in > 1000) return btnNONE; // Ningun boton pulsado
if (adc_key_in < 95 && adc_key_in > 90) return btn3;
//if (adc_key_in < 250) return btnUP;
if (adc_key_in < 200 && adc_key_in > 100) return btn2;
//if (adc_key_in < 650) return btnLEFT;
if (adc_key_in > 200 && adc_key_in < 300) return btn1;
return btnNONE; // when all others fail, return this...
}
// FIN READ BUTTONS
// Reseteo modem
void modemreset()
{
myGLCD.clrScr();
myGLCD.print("Reset Modem....", 0, 0);
// Iniciamos los comandos Hayes para configurar el modem
Serial.print("ATZ\r\n");
delay(4000);
myGLCD.print("4.", 0, 20);
Serial.print("AT+VCID=1\r\n");//Conceptronics CID ON
//Serial.print("AT#CID=1\r\n");//USR Robotics CID ON
delay(2000);
myGLCD.print("3.", 10, 20);
Serial.print("ATS7=5\r\n");//USR Robotics Answer Wait 7 seg
delay(2000);
myGLCD.print("2.", 20, 20);
Serial.print("ATS0=0\r\n");//USR Robotics Auto Answer OFF
delay(2000);
myGLCD.print("1.", 30, 20);
Serial.print("AT+FAE=1\r\n");//USR Robotics Adaptative Answer/Silent Answer
delay(2000);
myGLCD.print("OK", 40, 20);
delay(2000);
}
// sonido del buzzer
void buzz(int targetPin, long frequency, long length) {
long delayValue = 1000000/frequency/2; // calculate the delay value between transitions
//// 1 second's worth of microseconds, divided by the frequency, then split in half since
//// there are two phases to each cycle
long numCycles = frequency * length/ 1000; // calculate the number of cycles for proper timing
//// multiply frequency, which is really cycles per second, by the number of seconds to
//// get the total number of cycles to produce
for (long i=0; i < numCycles; i++){ // for the calculated length of time...
digitalWrite(targetPin,HIGH); // write the buzzer pin high to push out the diaphram
delayMicroseconds(delayValue); // wait for the calculated delay value
digitalWrite(targetPin,LOW); // write the buzzer pin low to pull back the diaphram
delayMicroseconds(delayValue); // wait againf or the calculated delay value
}
}
El sistema ya montado tiene el siguiente aspecto:
El resultado final del sketch es el siguiente:
/* Proyecto de discriminador de llamadas telefonicas no deseadas, tras la llamada se identifica el
numero llamante y se compara con los que están anotados en un fichero almacenado en una tarjeta SD. Si
coincide con alguno, la llamada es bloqueada. Ademas graba automáticamente los números que han llamado
y que posteriormente pueden seleccionarse con la botonadura para ser bloqueados. Al necesitar dos RING para
poder leer el CALLERID lleva un buzzer incorporado que suena a partir del tercer RING, para evitar
que suenen los telefonos siempre un par de veces (hacer mute en los telefonos para evitar el ring).
El hardware necesario es un Arduino Uno, un modem con CallerID (en mi caso US Robotics 56k o un Conceptronics
C55E de 56k), un modulo SD YL-30, una tarjeta SD, un modulo Serie HC05, un modulo LCD de 16x2 y
una botonadura tipo Keypad DIY de resistencias (una botonadura simple con tres resistencias de 3K en serie
conectando GND a Pin A0, p.e.).
Se usa un modulo HC05 master bluetooth para comunicarse con un modem bluetooth hc06 conectado al modem serie, que
a su vez está conectado a la linea de telefono.
La cadena del Caller ID detectada por el modem es siempre del tipo siguiente:
DATE = 0422 //MMDD
TIME = 1945 //HHMM
NMBR = 659278358 //Numero llamante
Conexion modulo hc05 a Arduino es : RX-TX(Pin digital 1) y TX-RX(Pin digital 0)
Conexion pines modulo SD a Arduino:
modulo: GND 3.3v 5v. CS MOSI SCK MISO GND
Arduino:GND 3.3V 5V. 10 11 13 12 GND
La botonadura es del tipo resistencias en serie unidas a pin A0 y GND, y boton uniendo PIN RESET a GND.
El buzzer está conectado al Pin A1 - GND - 5v
*/
// LCD5110_NumberFonts
// Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
// web: http://www.RinkyDinkElectronics.com/
//
// This program is a demo of the included number-fonts,
// and how to use them.
//
// This program requires a Nokia 5110 LCD module.
//
// It is assumed that the LCD module is connected to
// the following pins using a levelshifter to get the
// correct voltage to the module.
// CLK/ SCK - Pin 7
// MOSI - Pin 6
// DC - Pin 5
// RST - Pin 3
// CE/CS - Pin 4
//
#include <LCD5110_Basic.h>
LCD5110 myGLCD(7,6,5,3,4);
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];
#include <SdFat.h>//CS en pin 10
SdFat sd;
SdFile myFile;
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btn3 0
#define btnUP 1
#define btn2 2
#define btnLEFT 3
#define btn1 4
#define btnNONE 5
/// Guardamos en que entrada de arduino esta conectado el pin CS del modulo.
const int chipSelect = 10;
char nmbrstring[ ] = "NMBR";
char ringstring[ ] = "RING";
char numerodete[10];
char numerotst[10];
char numllam[10];
char charBuf[10];
char charBuf2[10];
char charThree[10];
int numblock = 50;//cantidad de lineas de numeros del fichero
int i = 0;
int i2 = 0;
int llamadas = 0;// Contador de llamadas, debe ser 0. Otro valor es para pruebas.
int ringer = 2;// Contador de ring, los 2 primeros no se detectan
int pin = A1;//pin conexion buzzer
String stringThree;
byte Bin2;
unsigned long tAntes = 0;
unsigned long tAntes2 = 0;
unsigned long tAntes3 = 0;
unsigned long tAntes4 = 0;
unsigned long tAntes5 = 0;
unsigned long tAntes6 = 0;
long time_now = 0;
//Sonido del buzzer
void playNote(int noteInt, long length, long breath = 20) {
length = length - breath;
buzz(pin, 2000 , length); // Valor 2000 es agudo y fuerte, 50 es grave y flojo
if(breath > 0) { //take a short pause or 'breath' if specified
delay(breath);
}
}
void setup()
{
myGLCD.InitLCD();
//myGLCD.clrScr();
pinMode(A0, INPUT_PULLUP); // sets analog pin for input
//digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT); // set a pin for buzzer output
myGLCD.setFont(SmallFont);
myGLCD.print("LCD Activado", 0, 0); // print a simple messag
delay (2000);
// Configuramos el puerto serie (esta version NO usa Serie Virtual)
Serial.begin(38400);
while (!Serial) {
; // Espera para conexion puerto serie, solo necesario para leonardo
}
myGLCD.clrScr();
myGLCD.print("Setup is Ready", 0, 0);
delay(2000);
//Iniciamos la SD
//Serial.print("Iniciando SD...");
//Serial.print("\n");
myGLCD.clrScr();
myGLCD.print("Iniciando SD...", 0, 0);
// El pin CS por defecto de la placa arduino debe ser configurado como salida
// aunque no se use (10 en la mayoria de las placas, 53 en Arduino Mega).
pinMode(10, OUTPUT);
// Si ha habido error al leer la tarjeta informamos por el puerto serie.
if (!sd.begin(chipSelect, SPI_HALF_SPEED))
{
//Serial.println("Error inicializar SD!");
myGLCD.print("Error SD...", 0, 20);
sd.initErrorHalt();
delay(2000);
myGLCD.clrScr();
myGLCD.print("PULSE RESET", 0, 40);
pinMode(10, INPUT);
delay(1000);
return;
}
myGLCD.print("SD ini...OK", 0, 20);
delay(2000);
//REcreando fichero RECIB.TXT
if (!myFile.open("RECIB.TXT", O_RDWR)) {
myGLCD.print("Error SD write", 0, 20);
delay(2000);
}
myFile.println("111111111");
delay(200);
myFile.close();// close the file:
myGLCD.clrScr();
myGLCD.print("RECIB.TXT ini", 0, 10);
delay(2000);
myGLCD.print("OK", 0, 30);
delay(2000);
myGLCD.clrScr();
myGLCD.print("Start Modem....", 0, 0);
// Iniciamos los comandos Hayes para configurar el modem
Serial.print("ATZ\r\n");
delay(4000);
myGLCD.print("4.", 0, 20);
Serial.print("AT+VCID=1\r\n");//Conceptronics CID ON
//Serial.print("AT#CID=1\r\n");//USR Robotics CID ON
delay(2000);
myGLCD.print("3.", 10, 20);
Serial.print("ATS7=5\r\n");//USR Robotics Answer Wait 7 seg
delay(2000);
myGLCD.print("2.", 20, 20);
Serial.print("ATS0=0\r\n");//USR Robotics Auto Answer OFF
delay(2000);
myGLCD.print("1.", 30, 20);
Serial.print("AT+FAE=1\r\n");//USR Robotics Adaptative Answer/Silent Answer
delay(2000);
myGLCD.print("OK", 40, 20);
delay(2000);
digitalWrite(pin, HIGH);
playNote(1,100);
digitalWrite(pin, LOW);
}
void loop()
{
static char buffer[20];
buttonselect();// Selector botones
myGLCD.setFont(SmallFont);
if (readline(Serial.read(), buffer, 80) > 0)
{
//Deteccion del numero llamante leido por puerto serie
char* numero1 = strchr(buffer, 'NMBR =');
char* prefinmbr = strtok(buffer, " =");
char* numero2 = strchr(numero1, ' ');
if(strcmp(prefinmbr, nmbrstring) == 0)//Detectamos la cadena NMBR que contiene el numero llamante
{
//Lector de numero
char* numerodete = numero2;//detecta numero con 1 espacio al inicio
String stringOne = numerodete;//convierte numero char a string
stringOne.trim();//elimina el espacio del inicio del número
myGLCD.clrScr();
myGLCD.print("Num.llamante:", 0, 0);
myGLCD.print("*********", 0, 20);
//myGLCD.print(charBuf, 0, 20);
stringOne.toCharArray(charBuf, 10);//convierte el numero string a char para strcmp
//ringer = 2;//Pone a 0 el contador de rings
myGLCD.print(stringOne, 0, 20);//Presenta en numero detectado
//Inicio codigo escritura llamadas recibidas
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
// if the file opened okay, write to it:
if (!myFile.open("RECIB.TXT", O_RDWR | O_CREAT | O_AT_END)) {
myGLCD.print("Error SD write", 0, 30);
}
myFile.println(stringOne);
delay (200);
myFile.close();// close the file:
llamadas++;// acumulado de numero de llamadas
myGLCD.print("Llamadas.....", 0, 40);
myGLCD.printNumI(llamadas, 60, 40);
myGLCD.print("WCOK", 60, 20);//Presenta el OK de grabacion numero detectado
//Mantiene el tiempo a 0 mientras se pulsa boton lectura
long time_now = millis();
tAntes = time_now;
tAntes2 = time_now;
tAntes3 = time_now;
tAntes4 = time_now;
// fin codigo escritura llamadas recibidas
//Inicio seccion lectura fichero numeros bloqueados.
char Ruta[9] = {'B', 'L', 'O', 'Q', '.', 'T', 'X', 'T', '\0'};//establece nombre fichero tlfs bloqueados
for(int i = 0; i < numblock; i++)// secuencialmente se lee cada una de los numeros del fichero
{
//Leemos linea de archivo en la SD
String numerotst = ReadFile(i,Ruta);
String stringTwo = numerotst;
stringTwo.toCharArray(charBuf2, 10);// convertimos string to char para strcmp
if(strcmp(charBuf, charBuf2) == 0)// comparamos el numero detectado con el leido en el fichero
{
myGLCD.clrScr();
myGLCD.print("Numero detec.:", 0, 0);
myGLCD.print(stringTwo, 0, 20); // Muestra el numero bloqueado
myGLCD.print("**BLOQUEADO**", 0, 30);//Presenta señal numero bloqueado
ringer = 20;//Impide que suene el buzzer
/* //Codigo activacion del modem para contestar y colgar
Serial.print("ATA\r\n");//Coge el tlf
delay(2000);
Serial.print("ATH1\r\n");//Cuelga el tlf
*/
delay (4000);
}// Fin deteccion numero bloqueado
}//Fin bucle lectura numeros bloqueados SD
}//Fin deteccion de llamada NMBR
//Deteccion de los RING para activar el buzzer
if(strcmp(buffer, ringstring) == 0)//Detectamos la cadena RING
{
/* Test cadena detectada
lcd.clear();
lcd.setCursor(0,0);
lcd.print(buffer);
lcd.print(ringer);
*///Fin test
ringer++;
//myGLCD.printNumI(ringer, 0, 35);//Print num rings
if(ringer > 3 && ringer < 15)//detector de rings para hacer sonar el buzzer
{
digitalWrite(pin, HIGH);
playNote(1,100);
playNote(1,200);
playNote(1,100);
playNote(1,100);
playNote(1,200);
playNote(1,100);
playNote(1,100);
playNote(1,200);
playNote(1,100);
digitalWrite(pin, LOW);
}
}
//Fin deteccion RING
}//Fin lectura buffer serie
//Timer Reponedor a 0 de rings
long time_now = millis();
if ((long)(time_now - tAntes6) > 80000)//Temporizador 80 seg para poner rings a 0
{
tAntes6 = time_now;
ringer = 2;
}
/*Test rings status
lcd.setCursor(0,15);
lcd.print(ringer);
*///Fin test
}// Fin LOOP
// Codigo de lectura de los telefonos bloqueados en la SD
String ReadFile(int Linea,char Ruta[]){
int Lin=0;
String Resultado;
byte Bin;
if (!myFile.open(Ruta, O_RDWR)) {
myGLCD.print("SD Read Error", 0, 0);
delay (2000);
myFile.close();return Resultado;
}
while (myFile.available()){
Bin=myFile.read();
if (Bin==13){Lin++;myFile.read();}
else
{
if (Lin==Linea){Resultado=Resultado+(char(Bin));}
if (Lin>Linea){myFile.close();return Resultado;}
}
}
myFile.close();return Resultado;
}
/// AÑADIDO CONTROL BOTONADURA Y GRABADO NUMEROS BLOQUEADOS SD
void buttonselect()
{
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btn3:
{
myGLCD.clrScr();
//LcdCharacter(adc_key_in);
myGLCD.print("Numero Block", 0, 0);
bloquear();
delay(500);
break;
}
case btn2:
{
myGLCD.clrScr();
//gotoXY(0,1);
//LcdCharacter(adc_key_in);
myGLCD.print("Bloquear Numero?", 0, 0);
myGLCD.print("NO", 0, 40);
myGLCD.print("X", 30, 40);
myGLCD.print("SI", 60, 40);
delay(500);
break;
}
case btn1:
{
//gotoXY(7,0);
//myGLCD.print("Bloquear");
leer();
/*myGLCD.clrScr();
gotoXY(0,1);
LcdCharacter(adc_key_in);
myGLCD.print("SELECT");*/
break;
}
case btnNONE:
{
long time_now = millis();
if ((long)(time_now - tAntes) > 10000) // regulador de tiempo medida datos y presentacion lcd
{
myGLCD.clrScr();
myGLCD.print("Waiting call...", 0, 0);
myGLCD.print("Llamadas..", 0, 40);
myGLCD.printNumI(llamadas, 60, 40);
tAntes = time_now;
}
if ((long)(time_now - tAntes2) > 1000)//Blink de * para indicar funcionamiento normal
{
myGLCD.print("****************", 0, 10);
tAntes2 = time_now;
}
if ((long)(time_now - tAntes3) > 1500)
{
myGLCD.print("* * * * * * * * ", 0, 10);
tAntes3 = time_now;
}
//Reponedor a 0 de lectura llamadas si inactividad en botones
if ((long)(time_now - tAntes4) > 20000)
{
i2 = 0;
tAntes4 = time_now;
}
if ((long)(time_now - tAntes5) > 1800000) //RESETEO MODEM CADA 30 MINUTOS
{
modemreset();
tAntes5 = time_now;
ringer = 2;
}
break;
}
}
}
void leer()
{
char Ruta[10] = {'R', 'E', 'C', 'I', 'B', '.', 'T', 'X', 'T', '\0'};//establece nombre fichero tlfs bloqueados
String numllam = ReadFile(i2,Ruta);//Leemos linea de archivo como char en la SD
//Proceso conversion de string to char para poder grabar los datos leidos
String stringThree = numllam; //convertir char to string
stringThree.toCharArray(charThree, 10);// convertimos string to char
delay(500);
myGLCD.clrScr();
myGLCD.print("Numero Leido.....", 0, 0);
myGLCD.print(".................", 0, 10);
myGLCD.printNumI((llamadas + 5)- i2, 40, 10);
//gotoXY(0,1);
//myGLCD.print(" "); // Muestra el numero leido
myGLCD.print(charThree, 0, 30); // Muestra el numero leido
//myGLCD.print("..", 75, 0);
delay (500);
i2++;
//Mantiene el tiempo a 0 mientras se pulsa boton lectura
long time_now = millis();
tAntes = time_now;
tAntes2 = time_now;
tAntes3 = time_now;
tAntes4 = time_now;
if (i2 > (llamadas + 5))
{
i2 = 0;
llamadas = 0;
delay (1000);
myGLCD.clrScr();
myGLCD.print("Borrando las", 0, 0);
myGLCD.print("LLamadas...", 0, 10);
if (!myFile.open("RECIB.TXT", O_RDWR | O_CREAT)) {
myGLCD.clrScr();
myGLCD.print("Error SD write", 0, 10);
delay(2000);
myGLCD.print("PULSE RESET", 0, 20);
delay(2000);
}
//Borrando fichero RECIB.TXT
myFile.remove();//borra fichero
delay(2000);
myFile.close();
//REcreando fichero RECIB.TXT
if (!myFile.open("RECIB.TXT", O_RDWR | O_CREAT)) {
myGLCD.print("Error SD write", 0, 10);
delay(2000);
myGLCD.clrScr();
myGLCD.print("PULSE RESET", 0, 20);
delay(2000);
}
myFile.println("111111111");
delay(200);
myFile.close();// close the file:
myGLCD.clrScr();
myGLCD.print("RECIB.TXT ini", 0, 0);
delay(2000);
myGLCD.print("OK", 0, 10);
delay(2000);
}
}
//funcion para escribir el número leido de RECIB.TXT y grabarlo en
//el fichero de numeros bloqueados BLOQ.TXT
void bloquear()
{
if (!myFile.open("BLOQ.TXT", O_RDWR | O_CREAT)){
myGLCD.print("Error SD write", 0, 0);
sd.initErrorHalt();
delay(2000);
myGLCD.print("PULSE RESET", 0, 10);
pinMode(10, INPUT);
delay(1000);
}
myFile.println(charThree);
delay(200);
myFile.close();
myGLCD.clrScr();
myGLCD.print("Numero bloqueado", 0, 0);
myGLCD.print("*********", 0, 20); // Limpia espacio numero
myGLCD.print(charThree, 0, 20); // Muestra el numero bloqueado
myGLCD.print("**BLOQUEADO**", 0, 30);
delay(2000);
}
//Sistema de lectura del puerto serie
int readline(int readch, char *buffer, int len)
{
static int pos = 0;
int rpos;
if (readch > 0) {
switch (readch) {
case '\n': // Ignore new-lines
break;
case '\r': // Return on CR
rpos = pos;
pos = 0; // Reset position index ready for next time
return rpos;
default:
if (pos < len-1) {
buffer[pos++] = readch;
buffer[pos] = 0;
}
}
}
// No end of line has been found, so return -1.
return -1;
}
// fin programa lectura puerto serie
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the sensor
//Valores para botonadura simple de 3 resistencias de 3k Ohm en serie
if (adc_key_in > 1000) return btnNONE; // Ningun boton pulsado
if (adc_key_in < 95 && adc_key_in > 90) return btn3;
//if (adc_key_in < 250) return btnUP;
if (adc_key_in < 200 && adc_key_in > 100) return btn2;
//if (adc_key_in < 650) return btnLEFT;
if (adc_key_in > 200 && adc_key_in < 300) return btn1;
return btnNONE; // when all others fail, return this...
}
// FIN READ BUTTONS
// Reseteo modem
void modemreset()
{
myGLCD.clrScr();
myGLCD.print("Reset Modem....", 0, 0);
// Iniciamos los comandos Hayes para configurar el modem
Serial.print("ATZ\r\n");
delay(4000);
myGLCD.print("4.", 0, 20);
Serial.print("AT+VCID=1\r\n");//Conceptronics CID ON
//Serial.print("AT#CID=1\r\n");//USR Robotics CID ON
delay(2000);
myGLCD.print("3.", 10, 20);
Serial.print("ATS7=5\r\n");//USR Robotics Answer Wait 7 seg
delay(2000);
myGLCD.print("2.", 20, 20);
Serial.print("ATS0=0\r\n");//USR Robotics Auto Answer OFF
delay(2000);
myGLCD.print("1.", 30, 20);
Serial.print("AT+FAE=1\r\n");//USR Robotics Adaptative Answer/Silent Answer
delay(2000);
myGLCD.print("OK", 40, 20);
delay(2000);
}
// sonido del buzzer
void buzz(int targetPin, long frequency, long length) {
long delayValue = 1000000/frequency/2; // calculate the delay value between transitions
//// 1 second's worth of microseconds, divided by the frequency, then split in half since
//// there are two phases to each cycle
long numCycles = frequency * length/ 1000; // calculate the number of cycles for proper timing
//// multiply frequency, which is really cycles per second, by the number of seconds to
//// get the total number of cycles to produce
for (long i=0; i < numCycles; i++){ // for the calculated length of time...
digitalWrite(targetPin,HIGH); // write the buzzer pin high to push out the diaphram
delayMicroseconds(delayValue); // wait for the calculated delay value
digitalWrite(targetPin,LOW); // write the buzzer pin low to pull back the diaphram
delayMicroseconds(delayValue); // wait againf or the calculated delay value
}
}