Problema sensor en entrada digital

Hola! Estoy haciendo una alarma antirrobo con Arduino UNO.
Me quedé sin pines digitales suficientes y opté por poner los pines analógicos como digitales, con lo cual todos quedarían como digitales, y el sensor se conecta a una digital también. La señal procedente del sensor PIR (que cuando detecta una persona sube de 0V a 5V, con pequeños rizados), la conecté al pin 2, y usé la interrupción:

attachInterrupt(0, GestionarSensor, RISING);

De esta forma, una vez me detectara el cambio a 5V (al ser digital, de 0 lógico a 1 lógico), me saltaría la interrupción y sonaría la alarma.

El problema es que me salta siempre. Creo que es porque el mínimo cambio en ese pin ya se toma como un RISING (por ejemplo de ruido), y la única forma de que no salte es poniendo el pin 2 a masa. Si conecto un cable suelto a dicho pin, también salta la interrupción.

Quería saber si hay alguna manera de mantener la señal del sensor en un pin digital (me es imposible ponerla en uno analógico), pero que el ruido ese (que creo que es lo que detecta) no me lo tomase en cuenta, es decir, que me tomase en cuenta señales mayores a unos pocos mV.

Muchas gracias de antemano! :slight_smile:

Primero para que usas una interrupción? Seguramente la tienes sin ninguna resistencia pull-down o up.

No hace falta para algo tan lento como un PIR.
con dos variables una con el dato actual y otra con el dato anterior lo haces

define

bool actual, anterior = false; // en globables o en el loop

en el setup define como entrada pinPIR

pinMode(pinPIR, INPUT);   // usa una R de 10k a GND.

en el loop

  actual = digitalRead(pinPIR); // pinPIR elque corresponda
  if (actual && !anterior) {
     GestionarSensor();
   }
   anterior = actual;

mira que fácil y sin interrupciones.

Hola! Muchas gracias!
Yo uso una interrupción para detectar un cambio en la entrada del sensor (que seria de 0 a 5V). La utilizo porque mientras estoy esperando datos del sensor, estoy en un bucle chequeando un teclado matricial, que me permite elegir opciones de un menú:

  1. Activar la alarma
  2. Desactivarla
  3. Cambio de contraseña
  4. Cerrar sesión

Si por ejemplo quiero desactivar la alarma cuando llego a casa (es decir, que aunque le lleguen datos del sensor, no haga sonar la alarma), ese bucle de chequeo me lo permite, además de saltar las interrupciones en el momento en que haya el cambio en el sensor.
De la forma que me describes no podría estar mirando el teclado y el sensor a la vez, verdad?

Si el código lo haces sin delay, algo TAN LENTO como el PIR lo vas a detectar de todos modos.
Si tu codigo ABUSA (y ves que lo pongo en mayúsculas) de los delays, estas cosas van a requerir de un elementos como el que sugieres (interrupción).
Sería bueno que postearas (usando la etiqueta de códigos </> ) tu código para poder analizar la situación.

Aquí está el código. En la interrupción no uso ningún delay, durante el resto del código muy pocas veces.

#include <TimerOne.h>


#include <Keypad.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(14, 15, 16, 17, 18, 19); //Pines para la pantalla LCD

const int sensor = 2 ;  //pin para el sensor, asociado a la interrupcion, no se puede cambiar el pin
const int led = 5 ;    //pin para el led 
const int zumbador = 11;  //pin para el zumbador 

char lectura; //Recibe lo escrito por teclado
const byte Filas = 4;          //Teclado de 4 filas
const byte Cols = 4;           //y 4 columnas
byte Pins_Filas[] = {10, 9, 8, 7};      // Pines asignados a las filas
byte Pins_Cols[] = {6, 5, 4, 3};     // Pines asignados a las columnas
char Teclas [ Filas ][ Cols ] =
          {
              {'1','2','3', 'A'},          // teclado
              {'4','5','6', 'B'},
              {'7','8','9', 'C'},
              {'*','0','#', 'D'}
          };

char PIN[4] = {'0','0','0','0'}; // Aqui va el pin de la alarma
char prueba [4] = {'0','0','0','0'}; //Inicializamos array prueba

Keypad Teclado = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Filas, Cols); //Inicializamos teclado

int estadoAlarma=0;  //alarma empieza desactivada
                     //estadoAlarma=0 desactivada 
                     //estadoAlarma=1 activada en silencio
                     //estadoAlarma=2 activada sonando

int sesion=0; // Sesion iniciada o no

int aux=0; //para que la alarma parpadee en sonido

int contadorv = 0;
int contadorv2 = 0;

int escribio = 0;
int escribio2 = 0;
int escribio3 = 0;



void setup() {
  
  pinMode(led,OUTPUT);     // LED, salida
  pinMode(zumbador,OUTPUT);    // Zumbador, salida
  
  //Analogicas como digitales

  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
  pinMode(17, OUTPUT);
  pinMode(18, OUTPUT);
  pinMode(19, OUTPUT);
 
  attachInterrupt(0, GestionarSensor, RISING); //Interrupcion 0 (pin 2, sensor) 
  lcd.begin(16, 4);           // Fijamos el numero de caracteres y filas
  lcd.setCursor(0,0);


  Timer1.initialize(500000);         // Dispara cada 500 ms
  Timer1.attachInterrupt(GestionarAlarma);
}


void loop() {

if (sesion==0){
  lcd.setCursor(0,0);
  lcd.print("Introduzca PIN");  // Aqui va el mensaje inicial
  
  
  while (contadorv < 4){
    while (escribio == 0){
      

      lectura = Teclado.getKey() ; // leemos tecla pulsada
      if (lectura !=0){
//        lcd.setCursor(0,1);
//        lcd.print (lectura);
      
        escribio = 1;
        
      }
    }
    escribio = 0;
    lcd.setCursor(contadorv,1);
    lcd.print (lectura);
    prueba [contadorv] = lectura;
    //lcd.setCursor(8,1);
    //lcd.print (contadorv);
    contadorv++;
    
  }
  lectura = 0;
  contadorv = 0;
  if ((prueba[0] == PIN[0]) & (prueba[1] == PIN[1]) & (prueba [2] == PIN[2]) & (prueba[3] == PIN[3])){
    lcd.clear();
    lcd.setCursor(0,0);
    //lcd.print(PIN);
    //lcd.print(prueba);
    //delay(500);
    lcd.print ("PIN CORRECTO");
    delay(500); 
    sesion = 1;
  }
  else {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print ("PIN INCORRECTO");
    delay(500);
    lcd.clear();   
  }


}


//Si ya iniciamos sesion
if (sesion == 1){
  lcd.setCursor(0,0);
  lcd.print("1Activ 2Desactiv");
  lcd.setCursor(0,1);
  lcd.print("3Cambio 4Cerrar");

  
  while (escribio2 == 0){
      
      lectura = Teclado.getKey() ; // leemos tecla pulsada
      if (lectura !=0){
        escribio2 = 1;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Has elegido");
        lcd.setCursor(0,1);
        lcd.print(lectura);
        delay (700);
        lcd.clear(); ////////////OJO ESTE!!!
        
      }
    }
    escribio2 = 0;

  ///LO ELEGIDO EN MENU///
  if (lectura == '1'){
    if (estadoAlarma == 0){
     estadoAlarma = 1;
     lcd.print("Activada");
     delay(500);
    }
    sesion = 0;
    lcd.clear();
  }  
  if (lectura == '2'){
   if (estadoAlarma!=0){
     estadoAlarma = 0;
     
   }
   lcd.clear();
   lcd.print("DESACTIVADA");
   delay(500);
   sesion=0;
   lcd.clear(); 
  }
  
  if (lectura == '3'){
    lcd.setCursor(0,0);
    lcd.print("Nuevo PIN");  // Aqui va el mensaje inicia
    while (contadorv2 < 4){
      while (escribio3 == 0){
      

        lectura = Teclado.getKey() ; // leemos tecla pulsada
        if (lectura !=0){
//        lcd.setCursor(0,1);
//        lcd.print (lectura);  
          escribio3 = 1;
          
      }
    }
    escribio3 = 0;
    lcd.setCursor(contadorv2,1);
    lcd.print (lectura);
    PIN [contadorv2] = lectura;
    lcd.setCursor(8,1);
    lcd.print (contadorv2);
    contadorv2++;
    
  } 
    contadorv2 = 0;
    //escribio2 = 0;
    lectura = 0;
  }

  if (lectura == '4'){
      sesion = 0;
      lcd.clear();
      lectura = 0;
  }
}
           
}



void GestionarSensor (){//solo nos interesa el estado 1
  if (estadoAlarma ==0){
    digitalWrite(zumbador, LOW);
  }
  if (estadoAlarma == 1){
    estadoAlarma = 2;
    aux=0;
    suenaAlarma();
  }
}
void GestionarAlarma (){
  if (estadoAlarma==2){
    if (aux & 0x01){
      silenciaAlarma();
      aux++;
    }
    else{
      suenaAlarma();
      aux++;
    }
  }
}
void suenaAlarma() {
      digitalWrite(led, HIGH);
      digitalWrite(zumbador, HIGH);
   
}
void silenciaAlarma() {
      digitalWrite(led, LOW);
      digitalWrite(zumbador, LOW);
   
}

Bueno muchos delays.
Veamos si se puede resolver a tu manera.
Como es la conexión del Pin2 donde esa la interrupción?

attachInterrupt(0, GestionarSensor, RISING); //Interrupcion 0 (pin 2, sensor)

El PIR directo al Pin 2?
Que PIR es?

Agrega una R de 10k a GND. Y si aun persisten los disparos agrega un capacitor electrolitico de 10uF y tensión mayor a 5V por supuesto.

La conexión al pin 2 viene de un circuito analógico que realicé yo. Es un circuito que primero amplifica la señal del sensor (que es de unos pocos mV), y luego hace una etapa de comparación (con dos operacionales), de forma que finalmente, la señal de salida de dicha etapa son 5V cuando se detecta presencia. Ese circuito es análogo al que vi en la hoja de características del sensor que utilizo, que es el IRA E-700, de Murata.
(En la imagen, es lo marcado con amarillo lo que me entra al pin 2).

Captura.PNG

Ese circuito termina en colector abierto.. que pusiste como carga pull-up?

Monitoreaste que se comporte bien, que no oscile?

Puse una resistencia de 100k llevada a +5V.
Y comprobé con el osciloscopio que oscila bastante, debe de ser que el sensor tampoco es muy bueno. Pero bueno, mantiene los 5V (que son 4,7V normalmente por el rizado) en tramos largos.

El sensor no tiene la culpa.
100k me parece alto.
Mira como lo cargan en este ejemplo pagina 10

Observá con el osciloscopio hacia atras a ver si detectás donde oscila.
La carga del transitor debe ser mayor, una R de 4k7 o 3k3 estaría mejor que 100k.

Mira antes del 555.

El enlace que me pasaste es el mismo que uso yo para realizar el circuito, y la resistencia de pull-up es de 100k, no?

¿A que te refieres con que mire donde oscila? Me hace cambios a la salida porque el comparador me saca 5V cuando la señal está entre 1,7 y 3,2 V (por el divisor de tensión), que cuando yo paso la mano por el sensor son los valores entre los que está la señal de la que sube a 5V (claro, cuando sube del todo 5V o baja de 1,7V es donde la salida se me pone en 0V). Raramente se queda un rato en 5V, siempre suele estar entre esos dos valores cuando hay presencia y movimiento.

Yo hablaba del transistor, no del 555.
El 555 no necesita pull-up.
Entonces el problema esta antes.

Porque tuviste que armar el PIR?

Para un trabajo de clase, y en principio ese circuito del pir me dijo el profesor que estaba bien, por eso quería buscar si con la programación con Arduino podía arreglar el problema.

El 555 no lo uso, es donde yo tendría el Arduino

Creo que el 555 esta ahi para actuar como monoestable de modo que el primer disparo genera un pulso habitualmente largo.
En el esquema no se ven ni el valor de C ni el valor de R que dan dicho pulso. Pero generalmente dura 20 o mas segundos.
De modo que tal vez lo que este mal sea el enfoque.
Solo haz que un disparo sea suficiente para accionar la salida y bloquea la interrupción por ese tiempo hasta que se cumpla tu tiempo. Luego del cual vuelves a habilitar la interrupción.

Para ello verifica que el sistema esta estable cuando no hay objetos delante del PIR.

Lo estoy probando y sin tener nada conectado al pin también detecta un flanco. La única forma en la que no detecta nada es poniendo ese pin a masa.
Si pusiera una temporización tras detectar algo tal y como me dices, yo creo que me seguiría sonando, puesto que ya me detectó un flanco, e independientemente de que luego haya más o no, ya ha sido suficiente para que suene. ¿O te referías a otra cosa?

Entonces esta mal tu circuito... intenta ir para atras o sea acercate con el Osciloscopio a la primera etapa amplificadora y observa si ocurre lo mismo.
O mejor aún: una punta en la salida que ahora tienes y otra comienza desde la mayor sensibilidad del osciloscopio a ver si puedes seguir desde el sensor en adelante y compruebas que alguna etapa se esta comportando mal.

Mira los puntos que te he marcado.

Comienza con la primer punta desde 4 a 1. Ajustando sensibilidad si corresponde.

El punto 3 es la salida de un comparador.
Si miras su entrada (2) tiene un divisor de 330k en la otra entrada, que establece una tensión de comparacion de 2.5V asi que ese punto a la entrada tmb es intersante para ver que ocurre... claro que ahi es posible que tengas la señal mas sucia.

NOTA: tuve que editar varias veces porque me expliqué viendo el 555 y luego recordé que no lo usas.
Que usas en lugar del NJM 2903

Perdona, puede que me explicase yo mal.
El circuito de amplificación y comparación del pir lo he comprobado y funciona correctamente.

A lo que me refería con que detectaba siempre un flanco es en el pin 2, pero del Arduino. Es decir, sin llegar a conectar el circuito del pir siquiera al Arduino, me detecta señales en el pin 2, que es donde está la interrupción. Me refiero a que dejando ese pin sin conectar nada, me salta la interrupción, y solo he conseguido que no salte poniendo un cable a masa. Conectando cualquier señal, conectando un cable suelto, o dejando sin conectar nada al pin de la interrupción, me detecta "algo" que produce un flanco de subida y me la activa.

Perdón si no lo había dejado claro. Respecto al circuito todo está en orden!

Me refiero a que dejando ese pin sin conectar nada, me salta la interrupción, y solo he conseguido que no salte poniendo un cable a masa.

Eso no puedes hacerlo con el pin suelto. Coloca una R (que ya te dije antes) de 10k a masa y veras que eso no ocurre.

surbyte:
Agrega una R de 10k a GND. Y si aun persisten los disparos agrega un capacitor electrolitico de 10uF y tensión mayor a 5V por supuesto.

Efectivamente con la resistencia eso no ocurre, aunque el funcionamiento no es el esperado.
La situación que tengo ahora es la siguiente:
El circuito del sensor que funciona correctamente, dándome la señal de 0 a casi 5V cuando detecta presencia.
El pin 2 del arduino detectando interrupciones con flanco de subida conectado a ese circuito, y con una R de 10k a masa.

Si en vez de la salida del circuito, conecto al pin 2 directamente una alimentación de 5V, la alarma suena cuando, una vez activada, meto los 5V manualmente. Es decir, la activo y para que haga un flanco de subida, conecto yo el pin a los 5V de alimentación. Ahí funciona correctamente.
Pero en el caso de tener conectado al pin 2 el circuito del sensor, los cambios, que son flancos de subida de 0 a 5 V, sigue sin detectarmelos.