Pulsador de acceso universal

Hola buenos días, soy nuevo en esto de la programación en Arduino.
Quería hacer un proyecto que tiene que consistir en utilizar un pulsador ya existente, por ejemplo el timbre de una puerta y mediante un código ejecutado mediante el pulsador ejecutar una acción, abrir la puerta.
Si alguien puede encaminarme un poco estaré muy agradecido.
Requisitos del proyecto:
Todo le sistema tiene que funcionar con un solo pulsador exterior, ja existente que lo adaptaría a la entrada 2 bot1 mediante un opto.
Ubicado en placa otro pulsador para poder realizar un reset de fabrica de los códigos de acceso en caso de olvido o mala grabación.
Led1 conectado en la salida 13 para ver las pulsaciones del pulsador exterior entrada 2 bot1.
Led2 conectado en la salida 12 para mostrar que le dispositivo esta leyendo código del pulsador bot1 (después de la primera pulsación de bot1l1 activa la lectura del código de 6 bits durante un tiempo de 6 segundos, transcurrido dicho tiempo sin un código correcto desactiva el modo de lectura de código)
Si el código es correcto activa salida 8 out1 durante 0.5 segundos.
El problema básicamente lo tengo a la hora de leer la duración de los pulsos y almacenarlos en una variable de 6 bits (pulso corto de 100 a 200 milisegundos = 0, pulso largo > de 200 milisegundos = 1)
Muchas gracias.

Utiliza un algoritmo tipo:

para detectar el cambio de estado del pulsador y utiliza la función millis() para controlar el tiempo entre los cambios de estado del pulsador.

Muchas gracias gracias Josemanu, pero el enlace no me funciona.
El proyecto ya lo tengo bastante avanzado, ahora el problema lo tengo en almacenar en una variable 6 pulsaciones.
Me parece que tengo que hacer un bucle pero de momento no me salgo.

const int led1=13;
const int led2=12;
const int out1=8;
const int out2=7;
const int bot1=2;
const int bot2=4;
int botoEstat1=0;
int botoEstat2=0;


boolean estadoActual  = 0;   //Estado actual pulsador
boolean estadoUltimo  = 0;   //Estado ultimo pulsador
boolean contadorONOFF = 0;   //Contador de pulsaciones

unsigned long Tinicio;         //Momento en que se pulsa el pulsador
unsigned long Tfin;            //Momento en que se libera el pulsador
unsigned long Tpulsacion;      //Diferencia Tfin-Tinicio
unsigned long Tinput;  //Tiempo maximo de lectura
unsigned long codic1;//codic out1
unsigned long codic2;//codic out2
unsigned long cod;

void setup()
{
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(out1,OUTPUT);
  pinMode(out2,OUTPUT);
  pinMode(bot1,INPUT);
  pinMode(bot2,INPUT);
  Serial.begin(9600);
}
void loop()
{
  estadoActual = digitalRead(bot1);        //Para leer el estado del pulsador
  if(estadoActual != estadoUltimo)   //Si el nuevo estado es distinto al ultimo..   
  {         
    if(estadoActual == HIGH)    //Si el estado es alto(cuando se aprita el boton) 
    {               
      Tinicio = millis();  //Guarda el momento de la pulsacion
      digitalWrite(led2,LOW);
      digitalWrite(led1,LOW);
    }                  
    if(estadoActual == LOW)  //Si el estado es bajo(cuando se libera el boton)
    {                
      Tfin = millis();
    }                     //Guarda el momento de la liberacion
    Tpulsacion = (Tfin-Tinicio);            //Calculo de la duracion de la pulsacion
  }
  estadoUltimo = estadoActual;              //Guarda el ultimo estado del boton

  if ((Tpulsacion <=200)&&(Tpulsacion >=10))//pulso corto
  {           
    digitalWrite(led1,HIGH);
    cod=0;
    Serial.println(cod);
  }
  if ((Tpulsacion >=200)&&(Tpulsacion<2000))//pulso largo
  {
    digitalWrite(led2,HIGH);
    cod=1;
    Serial.println(cod);
  }
  Tpulsacion=0;

  botoEstat2=digitalRead(bot2);//apaga leds
  if (botoEstat2==HIGH)
  {
    digitalWrite(led1,LOW);
    digitalWrite(led2,LOW);
  }
  Tinput=millis();
  if (Tinput >= Tinicio+2000)//apaga leds despuesde de 2 segundos
  {
    codic1=0;
    codic2=1;
    Serial.println(codic1);
    digitalWrite(led1,LOW);
    digitalWrite(led2,LOW);
    Tinicio=0;
    if (codic1==cod)//codic de la sortida 1 correcte obre 1
    {
      digitalWrite(out1,HIGH);
      delay (500);
      digitalWrite(out1,LOW);
    }
    if (codic2==cod)//codic de la sortida 2 correcte obre 2
    {
      digitalWrite(out2,HIGH);
      delay (500);
      digitalWrite(out2,LOW);
    }
  }
}

Morse5.ino (2.52 KB)

Corregido el enlace.

No entiendo lo de almacenar 6 pulsaciones en una variable, explicate mejor.

Necesito un código de dígitos generado mediante el pulsador, parecido a un código Morse, pulsaciones cortas y largas.
Introduces el código mediante pulsaciones seguidas, esto es lo que no consigo.
Por ejemplo:
pulsación corta = "."
pulsación larga = "-"
introducción del codigo ...--- = a una variable 000111.
Muchas gracias

Hola,

Tienes que comprobar antes que nada que la señal que proviene del pulsador la lee correctamente el arduino. Puedes comprobar que cada vez que pulsas/sueltas, sea cual sea la duración de la pulsación, el arduino cambia de "1" (i.e. led 13 ON) a "0" (OFF) y viceversa. No me extrañaría que tengas un problema de "bounce" (rebote), de tal forma que cada vez que pulsas haya varios cambios de 0 a 1 y viceversa.

Una vez hecho esto, tendrás que depurar un poco más la especificación. Si no me equivoco, la interpretación del morse la hace una persona que distingue con bastante rapidez un "corto" de un "largo"; habrá que "decirle" al arduino cómo establecer el tiempo que diferencia uno de otro y cosas así.

Suerte

La lectura del pulsador ya lo tengo solucionado, si es 0 pulsación corta o 1 pulsación larga.
El problema lo tengo en como almacenar en una variables 6 pulsaciones seguidas.
Tengo que hacer un bucle que lea cada vez que pulso, 6 veces, esto es lo que no me sale.

Muchas gracias

Prueba con una variable de tipo char en la que metes los ceros y los unos por medio de concatenaciones, luego la puedes tratar como quieras (seguir como una variable de texto o convertirla en byte).

Hola.
Tiempo ha, realicé un código en C que hacía exactamente eso: enviar o recibir morse. Suponiendo que ya tienes optimizado el código para distinguir las pulsaciones de punto o raya, y evitar problemas de rebote, te cuento, así de memoria, en pseudocódigo, cómo lo realicé yo para almacenar los valores en variables tipo byte.

-Si llevamos más de x tiempo sin recibir pulsación, guardamos el byte_recibido y reiniciamos su a 1. Esto es así, porque como los códigos no son de la misma longitud, el primer bit a 1 que recibamos no va a significar punto o raya, sino sencillamente que a continuación empieza el código. Por ejemplo, la A
. _ se almacenaría como
000001/01. Osea, el primer 1 de la izquierda nos indica que a continación comienza el código, que sería un cero (punto) y un uno (raya). Asimismo, la L (._..) se representaría como 0001/0100. Espero haberme explicado.

  • Si recibimos un punto o una raya, lo que haremos será desplazar hacia la izquierda el byte que estamos recibiendo, y poner en el bit 0 un 1 en caso de raya (en el caso de punto lo dejamos a cero, que es como queda por defecto tras el desplazamiento.
    if (pulsacion) {
    byte_recibido<<=1;
    if (pulsacion_larga) byte_recibido|=1;
    }

El proceso para "crear" una P (.__.) haría que byte_recibido pasara por estos estados:
00000001=>valor inicial
00000010=> .
00000101=>_
00001011=>_
00010110=>.

Espero haberme explicado. Si tienes alguna duda, no dudes en preguntar.
Saludos.

Muchas gracias a todos.
Pero el problema que tengo es con crear y definir la variable que quiero utilizar.
por ejemplo una pulsación corta = 0
dos pulsaciones cortas = 00
Dos pulsaciones cortas y una larga = 001
Y así hasta seis pulsaciones
Para almacenar seis pulsaciones seguidas se que tengo que crear un bucle y para ir sumando las pulsaciones dentro de la variables no lo consigo.
Como tengo que declara la variable???

Muchas gracias

El propio loop, como su nombre indica, es un bucle. Lo único que tienes que hacer es llevar la cuenta de pulsaciones. Prueba a ver si esto hace algo. He utilizado un contador para que te resulte más claro, teniendo en cuenta que la longitud de todos los códigos es 6. En el caso de morse, como te expliqué, hay longitud variable de códigos, con lo que habría que almacenar el valor de una forma un poco distinta.

const int bot1=2; // Pulsador en PIN2
boolean estadoUltimo  = 0;   //Estado ultimo pulsador

unsigned long Tinicio;         //Momento en que se pulsa el pulsador

byte cod=0;      // valor del byte que se está recibiendo
byte recibidos=0; // bits recibidos hasta el momento

void setup()
{
  pinMode(bot1,INPUT);
  Serial.begin(9600);
}
void loop()
{
      boolean estadoActual=digitalRead(bot1);
      if(estadoActual!=estadoUltimo){
            estadoUltimo=estadoActual;
            if (estadoActual==HIGH){      
                  Tinicio=millis(); 
            } else {
                  unsigned long Tpulsacion = millis() - Tinicio;
                  if (Tpulsacion>20){      // detectada pulsación no considerada rebote
                        cod <<= 1;      // desplazamos un bit a la izquierda el valor que tenemos hasta ahora
                        recibidos++;
                        if (Tpulsacion > 200){
                              cod|=B00000001;      // si la duración>200 convertimos el bit recibido en 1
                        }
                        if (recibidos>=6) {      // si el bit 6 está a 1 es que ha habido 6 desplazamientos
                              Serial.print("RECIBIDO CODIGO ");
                              Serial.print(cod, HEX);
                              recibidos = 0;
                              cod = 0; // reiniciamos valor.
                        }
                  }
            }
      }
}

Saludos.

Muchas gracias Noter.
Yo solo imposible de crear este codigo!!!
Funciona perfectamente, ahora lo estoy implementando en mi aplicación.
E añadido una instrucción para que si estas 2 segundos sin pulsar reinicie el contador.
Ahora el problema lo tengo al verificar si el código introducido mediante el pulsador coincide con el codigo correcto para dar salida al out1 o out2

const int bot1=2; // Pulsador en PIN2
const int led1=13;// Led 1
const int led2=12;// Led 2
const int out1=8;// Salida 1
const int out2=7;// Salida 2
const int bot2=4;//Pulsador reset

boolean estadoUltimo  = 0;   //Estado ultimo pulsador

unsigned long Tinicio;  //Momento en que se pulsa el pulsador
unsigned long Tinput;  //Retardo reinicio

byte cod=0;      // valor del byte que se está recibiendo
byte recibidos=0; // bits recibidos hasta el momento
byte codic1=0;
byte codic2=111000;

void setup()
{
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(out1,OUTPUT);
  pinMode(out2,OUTPUT);
  pinMode(bot1,INPUT);
  pinMode(bot2,INPUT);
  Serial.begin(9600);
}
void loop()
{
      boolean estadoActual=digitalRead(bot1);
      if(estadoActual!=estadoUltimo){
            estadoUltimo=estadoActual;
            if (estadoActual==HIGH){      
                  Tinicio=millis(); 
            } else {
                  unsigned long Tpulsacion = millis() - Tinicio;
                  if (Tpulsacion>20){      // detectada pulsación no considerada rebote
                        cod <<= 1;      // desplazamos un bit a la izquierda el valor que tenemos hasta ahora
                        recibidos++;
                        Serial.println(cod,BIN);
                          if (Tpulsacion > 200){
                              cod|=B00000001;
                              Serial.println(cod,BIN);      // si la duración>200 convertimos el bit recibido en 1
                               }
                                  if (recibidos>=6) {      // si el bit 6 está a 1 es que ha habido 6 desplazamientos
                                  Serial.print("RECIBIDO CODIGO ");
                                  Serial.println(cod, BIN);
                                      if (cod == codic1) {
                                        digitalWrite(out1,HIGH);
                                        delay(500);
                                        digitalWrite(out1,LOW);
                                        }
                                          if (cod == codic2) {
                                              digitalWrite(out2,HIGH);
                                              delay(500);
                                              digitalWrite(out2,LOW);
                                              }
                                  recibidos = 0;
                                  cod = 0; // reiniciamos valor.
                        }
                  }
            }
      }
       Tinput=millis();
       if (Tinput == Tinicio+2000){   //reinicia despuesde de 2 segundos de espera
             Serial.println("ANULAT");
             recibidos = 0;
             cod = 0;
             delay(200);
             }
}

Saludos

Hola,
Ya esta conseguido que mediante la introducción de un código de 6 dígitos accione la salida 1 o la 2, ahora estoy intentando poder variar el código desde el mismo pulsador. La intención es que introduciendo el código correcto para la salida 1 y seguidamente pulsando el pulsador 2 de reset entre en modo grabación de un nuevo código para salida 1, en este punto me gustaría volver a llamar a la subrrutina inputcode para entrar el nuevo código pero aquí me lío.

const int bot1=2; // Pulsador en PIN2
const int led1=13;// Led 1
const int led2=12;// Led 2
const int out1=8;// Salida 1
const int out2=7;// Salida 2
const int bot2=4;//Pulsador reset

boolean estadoUltimo  = 0;   //Estado ultimo pulsador

unsigned long Tinicio;  //Momento en que se pulsa el pulsador
unsigned long Tinput;  //Retardo reinicio

byte cod=0;      // valor del byte que se esta recibiendo
byte codic=0;  //valor del codic rebut
byte recibidos=0; // bits recibidos hasta el momento
byte codic1=1;
byte codic2=2;

void setup()
{
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(out1,OUTPUT);
  pinMode(out2,OUTPUT);
  pinMode(bot1,INPUT);
  pinMode(bot2,INPUT);
  Serial.begin(9600);
}
void loop(){
     inputcode();
     if (codic == codic1){ //Abre salida 1 si codigo correcto
         codic=0;
         digitalWrite(out1,HIGH);
         delay(1500);
         digitalWrite(out1,LOW);
         boolean estatboto2=digitalRead(bot2);
             if (estatboto2==HIGH){
                   Serial.println("Grabacio codic 1");
                   digitalWrite(led2,HIGH);
                   inputcode();
                   delay(1500);
                   digitalWrite(led2,LOW);
             }                              
         }
     if (codic == codic2) {  //Abre salisa 2 si codigo correcto
          codic=0;
          digitalWrite(out2,HIGH);
          delay(1500);
          digitalWrite(out2,LOW);
          boolean estatboto2=digitalRead(bot2);
             if (estatboto2==HIGH){
                   Serial.println("Grabacio codic 2");
                   digitalWrite(led2,HIGH);
                   inputcode();
                   delay(1500);
                   digitalWrite(led2,LOW);
        }
    }
}
      
void inputcode(){
   boolean estadoActual=digitalRead(bot1);
      if(estadoActual!=estadoUltimo){
            estadoUltimo=estadoActual;
            if (estadoActual==HIGH){      
                  Tinicio=millis();
            } 
            else {
                  unsigned long Tpulsacion = millis() - Tinicio;
                  if (Tpulsacion>20){      // detectada pulsacion no considerada rebote
                        cod <<= 1;      // desplazamos un bit a la izquierda el valor que tenemos hasta ahora
                        recibidos++;
                        Serial.print("Pul=");
                        Serial.print(recibidos);
                        Serial.print("Bit=");
                        Serial.println(cod,BIN);
                          if (Tpulsacion > 200){
                              cod|=B00000001;
                              Serial.print("Pul=");
                              Serial.print(recibidos);
                              Serial.print("Bit=");
                              Serial.println(cod,BIN);      // si la duracion>200 convertimos el bit recibido en 1
                               }
                                  if (recibidos>=6) {      // si el bit 6 esta a 1 es que ha habido 6 desplazamientos
                                  codic=cod;
                                  Serial.print("Codic Rebut ");
                                  Serial.println(codic, BIN);
                                  recibidos = 0;  //reiniciamos contador
                                  cod = 0; // reiniciamos valor.
                                  }
                  }
            }
      }
   Tinput=millis();
       if (Tinput == Tinicio+2000){   //reinicia despuesde de 2 segundos de espera
             Serial.println("Reset");
             Serial.print("Codic1=");
             Serial.println(codic1,BIN);
             Serial.print("Codic2=");
             Serial.println(codic2,BIN);
             recibidos = 0; //reiniciamos contador.
             cod = 0; // reiniciamos valor. 
             digitalWrite(led1,HIGH);
             delay(200);
             digitalWrite(led1,LOW);
             }
      }

Muchas gracias