17 dic. 2014

Cómo hacer que las luces se enciendan/apaguen con dos palmadas: fácil y barato con Arduino

La caja ya preparada con el micro en el centro

Hace poco vimos cómo tener diferentes modos de intensidad en una lámpara con leds no regulables utilizando Arduino, en esta ocasión construiremos un interruptor accionable por dos palmadas seguidas, muy útil para apagar luces, televisores, etc.

En nuestra habitación el interruptor nos quedó a desmano de la cama, así que se me ocurrió que sería posible, con un micro, construir un relé que activaríamos como habíamos visto tantas veces en la tele, con dos palmadas.
También le puede venir muy bien a personas con movilidad reducida, aunque en ese caso sería mejor un mando a distancia.
Cuando al fin me puse con ello, se me ocurrió que seguro que lo había echo alguien antes, y ¡bingo! un alemán comentaba cómo lo había desarrollado en su página, lo que me ahorró horas de pruebas con el micro.
Un micro con una salida activable a cierto volumen simplifica mucho las cosas, por lo que la teoría es que el programa del Arduino sólo tiene que estar escuchando, y se producen dos (sólo dos) golpes altos en menos de 0,4 segundos, es muy probable que sean dos palmadas.
3 componentes, unos pocos cables dupont y el conector USB es todo lo que necesitamos para probarlo


Puede darse el caso que se produzcan dos sonidos fuertes seguidos (una puerta, unos tacones, etc), a pesar del breve tiempo de detección y de regular la sensibilidad del micro, para esos casos en que las lámparas puedan encenderse sin estar nadie, añadiré unas líneas de código de forma que se apague el relé después de 6 horas.
También había pensado en añadir un sensor por ultrasonidos para encender la lámpara por movimiento durante un minuto, pero en una habitación eso es poco práctico, además de que era complicarlo sin necesidad. Tal vez lo haga, pero hoy en día los sensores de movimiento por infrarrojos están tan baratos (unos 10€) que no merece la pena. Otra opción es "samplear" el sonido, de forma que sea el Arduino el que decida si ha habido un "plas plas" o no, podría ser más fiable, como se explica en esta entrada.
No sé lo que costará un aparato que haga lo mismo, pero no creo que me cueste menos que el siguiente material necesario:
  1. Un Arduino "Nano" con Atmel 328p de 32KB Rom (2 Ks ocupados por el cargador de arranque).
  2. Un relé "Keyes", al que le basta con la salida del pin de 5V del Arduino para activarse.
  3. Y un micrófono especial para palmadas, (este no; el potenciómetro es inestable, aunque podemos servirnos de su salida digital), o este otro, pues detecta niveles de sonido por encima de un valor regulable, con una de las salidas digital (D0) que se activa a un volumen configurado por resistencia, y otra salida analógica (A0) para el nivel de sonido detectado (entre 50 y 1024 según el volumen del ruído). Bien calibrado, nos puede valer para registrar el número de veces que el sonido supera un cierto límite al día, por ejemplo en un puesto de trabajo.
  4. Y un transformador entre 7 y 12V DC para alimentar el Arduino.
Un transformador sin un triste condensador a la salida... ¡con lo poco que cuestan!
No voy a entrar en detalles de la programación, ni en cómo se introduce el programa, etc, para eso existe abundante información en otras páginas de internet.

Este sería el sencillo programa:


/*
 * PROGRAMA activación de relé por palmadas
 * (C) Creative Commons
 * Modificado a partir de http://en.code-bude.net/2014/12/08/how-to-build-a-clap-switch-using-arduino/ 
 * con guardado de horas de funcionamiento en EEPROM
 */
 
#include <EEPROM.h>
int soundSensor = 7;
int relay = 4;
int claps = 0;
int pos =0;
int value =0;
long horas=0;
long detectionSpanInitial = 0;
long detectionSpan = 0;
long millisPrevious=0;
long millisNow=0;
boolean relayState = true; //comenzamos con él activado
 
void setup() {
  pinMode(soundSensor, INPUT);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, HIGH); //encendemos al encender la luz
}
 
void loop() {
 
  //for (int pos = 0; pos <256; pos++) { //sólo lo ejecuto una vez para borrar toda la eeprom
  //   EEPROM.write(pos, 0);
  //}
  
  int sensorState = digitalRead(soundSensor);
 
  if (sensorState == 0)
  {
    if (claps == 0)
    {
      detectionSpanInitial = detectionSpan = millis(); //guardamos el contador de milisegundos inicial
      claps++;
    }
    else if (claps > 0 && millis()-detectionSpan >= 50)
    {
      detectionSpan = millis();
      claps++;
    }
  }
  
  //apagamos sin han pasado 6 horas (en caso de falsa activación)
  if (horas>5){ //cambiar este valor por el deseado
    horas=0;
    relayState = false;
    digitalWrite(relay, LOW);
  }     
 
  if (millis()-detectionSpanInitial >= 350)
  {
    if (claps == 2)
    {
      if (!relayState)
        {
          relayState = true;
          digitalWrite(relay, HIGH);
          horas=0; //empieza a contar
        }
        else if (relayState)
        {
          relayState = false;
          digitalWrite(relay, LOW);
        }
    }
    claps = 0;
  }
  //while(1) {delay(500);} //bucle infinito
  //Si ha pasado una hora, lo guardamos en la eeprom aumentando el primer valor en 1, y si es=255, aumentamos el siguiente
  //lo que nos da poder llegar a guardar 260.000 horas
  millisNow=millis();
  
  if (millisNow-millisPrevious >= 3600000)
  {
    horas++; //incrementar
    millisPrevious=millisNow;
    pos=0;
    while (EEPROM.read(pos)==255) {
      pos++;
      if (pos==1024) {break;} //el Atmel328p tiene 1K de EEPROM; modificar por 512 en versiones menores
    }
    value=EEPROM.read(pos);
    EEPROM.write(pos,value++);
  }
  else
  {
      millisNow=millis();
  }
  
}

He añadido líneas de código para guardar en la EEPROM el número de horas que esté encendido; es muy probable que la fuente de alimentación o el relé duren menos que la propia placa, así que podré comprobar cuánto ha funcionado antes de estropearse.
Y si os preguntáis cuánto puede durar una placa Arduino funcionando, la conclusión es que con una fuente de alimentación de calidad, mínimo 50.000 horas; entre 5 y 10 años. Aquí una interesante discusión sobre su fiabilidad.

Su consumo es mínimo; calculo que 1W con esta fuente de 7V; 50mA del Nano, 20mA del relé (sin activar, activado gasta más pero estará poco tiempo) y 15mA del micro y 60mA la fuente (mínimo), pero si queréis bajar más su consumo, lo mejor es poner una fuente conmutada de 5V (típico cargador de móviles), y se puede quedar en 0,5W cuando no se usa.
De todas formas, como está después del interruptor de la luz (el programa hace que cuando se enciende el arduino, se conecte el relé; tarda 1 seg. en encenderla), sólo consume cuando lo hemos apagado con palmadas y dejamos el interruptor de la luz conectado.

El ajuste del potenciómetro que trae el micrófono se puede hacer con él en marcha; yo lo he aflojado (sentido contrario a las agujas del reloj) hasta que se activaba permanentemente el led indicador del sonido, y luego lo he apretado con un par de vueltas. Si no, su sensibilidad era muy pequeña, y prácticamente había que hacerse daño en las manos para que nos detectara.

Tras probarlo concienzudamente, he colocado todo (un poco mal organizado, todo hay que decirlo) en una caja empotrable al lado de la alimentación en el techo, aunque también podemos ponerlo al lado del interruptor, haciendo un hueco en la pared, éso ya es a gusto del consumidor.
En la foto siguiente se ven las conexiones; el Arduino abajo a la izda. con un agujero practicado para poder conectarlo al ordenador en caso de querer ajustar alguna cosa, y todo pegado con un poco de termoencoladora (no va a coger mucha temperatura en mi caso, pero mejor usad silicona).
Para el micrófono, lo he soldado por el otro lado para poder pasarlo por un pequeño agujero de la tapa, y que pueda escuchar bien las palmadas.
Las conexiones de alimentación: Como son sólo dos elementos de poco consumo, lo mejor es alimentar al Arduino en su Vin (patilla 30) con entre 7 y 12V, y con su salida de 5V (patilla 22 creo), alimentamos el relé y micrófono.
En caso de usar un relé de más voltaje, tendríamos que alimentarlo directamente con la fuente para que se pueda activar.

Al transformador (bobina roja y amarilla) le he puesto un condensador bien gordo, pues no traía
Y finalmente así queda en el techo junto a la lámpara, con los tres cables. El blanco/rojo es el neutro, conectado a la lámpara directamente y al Arduino (transformador), y el marrón va al Arduino, y la salida (rojo) va a la lámpara (desde el relé).

Ponemos la tapa... y a disfrutarlo!
La verdad es que es un poco "pijada", pero ¡lo bien que viene en las noches de invierno para no tener que salir de la cama! XD Un par de palmadas... y luz apagada. Otro par... y luz encendida. Otro par... ¡esto es adictivo oye! jeje.

De nuevo, os recomiendo leer la página de Raffi, no tiene desperdicio, explica todo el proceso de análisis del problema y la solución técnica que le da.

Este otro ejemplo usando la salida de nivel de audio A0 (con este sensor):


 /*
Código para activar un led con sonido.
Tienes que establecer el mínimo de forma que sea suficientemente sensible.
Este tipo de sensores sólo funcionan bien con sonidos altos.
Conectas un LED al PIN13 y el sensor de sonido al pin analógico A0
*/
#define DEBUG 1
#define ANALOG_PIN A0
#define LED_PIN 13

int threshold = 50; // Configura esto
int volume;

void setup() { 
pinMode(LED_PIN, OUTPUT); 
#if DEBUG
Serial.begin(9600); // Para depuración
#endif
}

void loop() {

volume = analogRead(ANALOG_PIN); // Lee el valor del pin analógico.
#if DEBUG
Serial.println("Volumen " + String(volume));
delay(100);
#endif

if (volume > threshold){
digitalWrite(LED_PIN, HIGH); //Turn ON Led

else{
digitalWrite(LED_PIN, LOW); // Turn OFF Led
}
}

Y como siempre, ¡si te ha gustado o tienes alguna duda, a qué esperas para dejar un comentario! :)

Actualización: Se le cambiaba la sensibilidad, el potenciómetro no es muy fiable, al final he usado este otro:



La única pega que tiene es que también se acciona con los tosidos... ¡no os pongáis malos! XD

Referencias:
How to build a clap switch using Arduino
Sensor de golpe de sonido usando un altavoz piezoeléctrico y una resistencia con Arduino
Controlador activado por sonido

2 comentarios:

  1. Hola David, no me contestas al google forms en el email.
    Verás , enhorabuena por el proyecto , te quedó muy guapo.
    Hay una o unas correcciones que quisiera decir-
    Yo soy quien tiene la autoría . YO Gabriel Martín .
    Publicado en un "foro de coches" de España en el 2013 , y
    aún conservo la cuenta pública de google code en la que estaba
    el proyecto .
    Las horas ésas que te ahorrastes con lo del micrófono,
    tranquilo que las gasté yo aquí antes del verano 2013 , dando vueltas
    por el parque cuando
    me atascaba ; )
    Ni alemán ni *'s , el autor es español.

    Autor:Gabriel Martín

    ResponderEliminar
    Respuestas
    1. Hola Gabriel, gracias por comentarlo; al César lo que es del César. No te contesté porque sólo me decías que contactara contigo, hay que ser más concreto.

      En cuanto al código, si es tuyo, indícame enlace donde lo tuvieras y lo analizaré, y si es así cambiaré la entrada dándote el reconocimiento que mereces.

      De todas formas, como comprenderás otros pueden haber llegado a la misma solución sin haber visto siquiera tu idea, es algo que ocurre continuamente en software (por eso las patentes de software son una aberración, es como patentar los colores del arcoiris).

      Eliminar

Puede dejar su comentario. Los comentarios descalificativos o sin relación ninguna con el tema tratado serán eliminados sin previo aviso. Antes de plantear una duda, asegúrate de que la respuesta no está en otra entrada del tema visitando la etiqueta que hay al final del artículo para verlos todos; muchas veces lo que planteas puede haber sido corregido o comentado en otra entrada posterior.