Montaje 9: Cerradura knock-knock

Requisitos:

  • Un LED, una resistencia de 220 ohmios.
  • Un pulsador.
  • Un zumbador piezoeléctrico.
  • Una resistencia de varios Mohmios.

Planteamiento: ¿Harto de que entren en tu habitación cuando no estás?. Instala una cerradura que reconozca el ritmo de tu canción favorita.

Del mismo modo que la cerradura digital de seguridad? compartía buena parte del código con replay?, este ejercicio se puede hacer sobre la base de la grabadora de ritmos?.

Volvemos a utilizar lo que aprendimos para guardar en cadenas y comparar series de valores, sólo que ahora en lugar de ser señales digitales de entrada, lo que guardamos son los tiempos entre una señal analógica que sobrepasa un umbral y la siguiente.

Para ello añadimos dos cadenas más: cadenacode[] , en la que guardamos los tiempos de la primera secuencia de golpes, y codecomp[] , donde guardamos los aciertos o fallos al comparar la primera secuencia con los intentos posteriores.

Usaremos los procedimientos del limpiaparabrisas? para mover el motor paso a paso que va a cerrar y abrir el pestillo.

Cada vez que se termina una secuencia hay que presionar el pulsador, entonces se reproduce con pitidos y el procedimiento sifinrepro( )comprueba:

  • si es la primera, lo que está indicado por el valor 0 de la variable c, y ejecuta el procedimiento guardacode( ), que copia los valores de cadenatiempos( ) en cadenacode() convirtiendo la primera secuencia de golpes en el código de seguridad y cierra moviendo el motor hasta topar con uno de los finales de carrera.
  • si no es la primera, porque c no es 0, se comparan los tiempos recién insertados con los del código uno a uno (con el margen de error que se ajuste) y se van sumando los aciertos( con el procedimiento compruebatiemp( ) ). Si resulta el mismo nº de aciertos que de golpes, abre (procedimiento compruebacode( ) ) y reinicia las variables para volver a empezar.

CODIGO FUENTE

 Copyright (C) 2006  Juan Carlos Alonso de Mena
 This program is free software; you can redistribute it and/or modify it under the terms
 of the GNU General Public License as published by the Free Software Foundation;
 See the GNU General Public License for more details?

 int ledPin = 13;
 int piezosensor = 0; 
 int puls =7;              
 int medida = 0;
 int nivel = 80;
 int zumb = 10;
 int numgolpes = 0;
 int tiempo = 0;
 int n=0;
 int c=0;                                         //variable cuyo valor diferencia si se stá introduciendo 
                                                  //el código o intentando repetirlo
 int num=0;
 int s=0;
 int cadenatiempos[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,};
 int cadenagolpes[] ={2,3,4,5,6,7,8,9,10,11,12,13,14,15};
 int cadenacode[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//cadena en la que guardamos los tiempos de la primera 
                                                  //secuencia de golpes
 int codecomp[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  //donde guardamos los aciertos o fallos al comparar la primera secuencia con los intentos posteriores.
 int vel =10;
 int unoa = 3;
 int unob = 4;
 int dosa = 5;
 int dosb = 6;
 int fincarrera1=11;
 int fincarrera2=12;
 void setup() {
   pinMode(ledPin, OUTPUT); 
   pinMode(zumb, OUTPUT);
   pinMode(12,OUTPUT); 
   beginSerial(9600);
   pinMode(unoa,OUTPUT);
   pinMode(unob,OUTPUT);
   pinMode(dosa,OUTPUT);
   pinMode(dosb,OUTPUT);
   pinMode(fincarrera1, INPUT);
   pinMode(fincarrera2, INPUT);
 }
 void avanza(){
   digitalWrite(unoa,HIGH);
   digitalWrite(unob,LOW);
   digitalWrite(dosa,LOW);
   digitalWrite(dosb,LOW);
   delay(vel);
   digitalWrite(unoa,LOW);
   digitalWrite(dosa,HIGH);
   delay(vel);
   digitalWrite(unob,HIGH); 
   digitalWrite(dosa,LOW);
   delay(vel);
   digitalWrite(unob,LOW);  
   digitalWrite(dosb,HIGH);
   delay(vel);
 }       
 void retrocede(){
   digitalWrite(unoa,LOW);
   digitalWrite(unob,HIGH);
   digitalWrite(dosa,HIGH);
   digitalWrite(dosb,HIGH);
   delay(vel);
   digitalWrite(unoa,HIGH);
   digitalWrite(dosa,LOW);
   delay(vel);
   digitalWrite(unob,LOW); 
   digitalWrite(dosa,HIGH);
   delay(vel);
   digitalWrite(unob,HIGH);  
   digitalWrite(dosb,LOW);
   delay(vel);
 }      
 void guardatiempos(){                        
   for (n=0 ;n<14 ;n++){
     if (numgolpes ==cadenagolpes[n]){
       cadenatiempos[n] =tiempo;
     }
   }
 }      
 void guardacode(){                               //copia los tiempos de la secuencia de golpes
   for(n=0;n<(numgolpes-1);n++){
     cadenacode[n]=cadenatiempos[n];
   }
   num=numgolpes;     
 }       
 void compruebatiemp(){                           //consideramos un tiempo como bueno si entra en un margen de error 
   for (n=0; n<(numgolpes-1);n++){
     if (cadenacode[n]>=(cadenatiempos[n]/2)){
       if(cadenacode[n]<=(cadenatiempos[n]*3/2)){ 
         codecomp[n]=1;                           //apunta un acierto
       }
       else{
         codecomp[n]=0;                           //apunta un fallo
       }
     }
     else{
       codecomp[n]=0;
     }
   }
 }                 
 void compruebacode(){                            //procedimiento que suma el nº de   aciertos
   if(numgolpes==num){
     for (n=0;n<(num-1);n++){
       if(codecomp[n]==1){
         s=s+1;
       }
     }
     if(s==(num-1)){                              //y si coincide con el total
       digitalWrite(12,HIGH);                      
       delay(2000);
       digitalWrite(12,LOW);
       while(digitalRead(fincarrera2)==LOW){      //abre
         retrocede();
       }
     }
   }
 }
 void sifinrepro(){
   if(digitalRead(puls) == HIGH){                 //si se presiona el pulsador para indicar que ha terminado la secuencia:
     delay(2000);                                 //se reproduce la secuencia de golpes como pitidos 
     digitalWrite(zumb, HIGH);                          
     delay(50);
     digitalWrite(zumb, LOW);
     for(n=0 ;n<(numgolpes-1); n++){
       delay(cadenatiempos[n]*90);  
       digitalWrite(zumb, HIGH);
       delay(50);
       digitalWrite(zumb, LOW);
     } 
     if (c==0){                                   //si es la primra vez:
       guardacode();                              //convertimos la secuencia de golpes en el código de seguridad
       while(digitalRead(fincarrera1)==LOW){      //y cerramos
         avanza();
       }
     }
     else{                                        //si ya hemos introducido el código:
       compruebatiemp();                          //comparamos los tiempos y decidimos si los damos por buenos
       compruebacode();                           //y si todos son buenos abre y si no, pues no.
     }
     numgolpes=0;                                 //se pone a cero el nº de golpes
     c=c+1;                                       //indicamos que empezamos otro intento
     s=0;                                         //se pone a cero el nº de aciertos
     //printByte(10);    
   }
 }
 void loop() {
   medida = analogRead(piezosensor);     
   if (medida >= nivel) {                         //si se detcta un golpe:
     digitalWrite(ledPin,HIGH);                   //se enciende el LED
     printString("Knock!   ");                    //se envía una palabra al monitor del puerto serie
     // printByte(10);
     printByte(13);
     numgolpes = numgolpes +1;                    //se actualiza el contador de golpes
     guardatiempos();                             //se guarda el tiempo desde el golpe anterior
     sifinrepro();                                //se comprueba si hemos intentado la serie completa y si está bien
     tiempo = 0;                                  //se empieza a contar el siguiente tiempo
     delay(100);                                  //para evitar que un golpe fuerte cuente como varios  
   } 
   delay(100);                                    // para evitar que se sature el puerto serie
   tiempo = tiempo +1;                            //si no hay una señal suficiente del sensor, el tiempo corre
   digitalWrite(ledPin,LOW);                      //se apaga el LED
 }

Volver?

  Copyright (c) 2006  Juan Carlos Alonso de Mena

  Permission is granted to copy, distribute and/or modify this document under the terms of 
 the GNU Free Documentation License, Version 1.2 or any later version published by the
 Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no
 Back-Cover Texts.  A copy of the license is included in the section entitled 
 GNU Free Documentation License?.