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?.