sábado, 8 de octubre de 2016

Diferenciar entre pulsación corta y pulsación larga

Siguiendo con el tema de pulsadores en una casa para encender o apagar luces, persianas o lo que deseemos hay una particularidad que se puede lograr con programación que aumenta las características de un pulsador. Por si solo, sólo tenemos 2 posiciones, encendido (Mientras se esta apretando el pulsador) y apagado (cuando se suelta). Pero gracias a la programación podemos medir el tiempo en que el pulsador esta apretado, dándole así nuevas funciones... como por ejemplo apretar menos de 2 segundos y encender o apagar la luz de la entrada y si apretamos mas de 2 segundos apagamos cualquier luz que hubiera encendida en la casa. (muy útil cuando te vas de casa y te olvidaste de apagar la luz de la habitación por ejemplo).

A modo de practica os dejo el esquema de conexión donde conectaremos 3 pulsadores a la placa Arduino y 2 luces. El funcionamiento sera el siguiente: los 2 primeros pulsadores encenderán o apagarán la primera luz, el tercer pulsador encenderá o apagara la segunda luz, pero con la particularidad que si éste se aprieta mas de 2 segundos apagara cualquier luz que este encendida.

ESQUEMA DE CONEXIÓN:


Recordemos que las resistencias de los pulsadores serán de un valor de 10 kilo-ohmios, y la de los leds de 220 ohmios. 

CÓDIGO DE PROGRAMACIÓN:

const int pulsadores[] = {2, 3, 4};
const int nPulsadores = 3;

const int Luz[] = {11, 12};
const int nLuces = 2;

int estadoLuz[] = {LOW, LOW};
int estadoBoton[] = {HIGH, HIGH, HIGH};
int estadoBotonAnterior[] = {HIGH, HIGH, HIGH};

long lastDebounceTime = 0;  
long debounceDelay = 50;

long tempPulsacionIni = 0;
long tempPulsacionFin = 0;
long intervalo = 0;

int apagarLuces = LOW;

void setup() {
  for(int i = 0; i < nPulsadores; i++){
      pinMode(pulsadores[i], INPUT);
    }
  for(int i = 0; i < nLuces; i++){
      pinMode(Luz[i], OUTPUT);
    }
  for(int i = 0; i < nLuces; i++){
      digitalWrite(Luz[i], LOW);
    }
}

void loop() {
  for(int i = 0; i < nPulsadores; i++){
      leerPulsador(i);
    }
}

void leerPulsador(int pulsador){
  int lecturaPulsador = digitalRead(pulsadores[pulsador]);
  if (lecturaPulsador != estadoBotonAnterior[pulsador]) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (lecturaPulsador != estadoBoton[pulsador]) {
      estadoBoton[pulsador] = lecturaPulsador;
      if(estadoBoton[0] == LOW || estadoBoton[1] == LOW){
          estadoLuz[0]= !estadoLuz[0];
        }
      if(estadoBoton[2] == LOW){
          tempPulsacionIni = millis();
        }
      if(estadoBoton[2] == HIGH && tempPulsacionIni > 50){
          tempPulsacionFin = millis();
          intervalo = tempPulsacionFin - tempPulsacionIni;
          if(intervalo > 50 && intervalo < 2000){
              estadoLuz[1] = !estadoLuz[1];
              tempPulsacionIni = 0;
            }else if(intervalo >= 2000){
                apagarLuces = HIGH;
                tempPulsacionIni = 0;
              }
        }
    }
  }
  if(apagarLuces == HIGH){
        estadoLuz[0] = LOW;
        estadoLuz[1] = LOW;
        apagarLuces = LOW;
    }
  for(int i = 0; i < nLuces; i++){
      digitalWrite(Luz[i], estadoLuz[i]);
    }
  estadoBotonAnterior[pulsador] = lecturaPulsador;  
}

Si bien el programa funciona, me di cuenta de que a la hora de apagar todas las luces se apagan de golpe, con lo que por ejemplo si es de noche y tienes el pulsador al fondo del pasillo te obliga a ir a oscuras hasta la puerta de la calle. No creéis que seria mejor darle un tiempo prudencial, que una vez apretado el pulsador para que nos apague todas las luces las mantenga encendidas 5 segundos y nos de tiempo a salir de casa? Luego se apagan solas. Como siempre para conseguir eso hay que modificar el código de programación. A continuación os dejo el código modificado por si alguien quiere ver la diferencia entre los dos programas. Hasta pronto!! 

const int pulsadores[] = {2, 3, 4};
const int nPulsadores = 3;

const int Luz[] = {11, 12};
const int nLuces = 2;

int estadoLuz[] = {LOW, LOW};
int estadoBoton[] = {HIGH, HIGH, HIGH};
int estadoBotonAnterior[] = {HIGH, HIGH, HIGH};

long lastDebounceTime = 0;  
long debounceDelay = 50;

long tempPulsacionIni = 0;
long tempPulsacionFin = 0;
long intervalo = 0;

int apagarLuces = LOW;
long previousMillis = 0;
long crono = 5000;

void setup() {
  for(int i = 0; i < nPulsadores; i++){
      pinMode(pulsadores[i], INPUT);
    }
  for(int i = 0; i < nLuces; i++){
      pinMode(Luz[i], OUTPUT);
    }
  for(int i = 0; i < nLuces; i++){
      digitalWrite(Luz[i], LOW);
    }
}

void loop() {
  for(int i = 0; i < nPulsadores; i++){
      leerPulsador(i);
    }
}

void leerPulsador(int pulsador){
  int lecturaPulsador = digitalRead(pulsadores[pulsador]);
  if (lecturaPulsador != estadoBotonAnterior[pulsador]) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (lecturaPulsador != estadoBoton[pulsador]) {
      estadoBoton[pulsador] = lecturaPulsador;
      if(estadoBoton[0] == LOW || estadoBoton[1] == LOW){
          estadoLuz[0]= !estadoLuz[0];
        }
      if(estadoBoton[2] == LOW){
          tempPulsacionIni = millis();
        }
      if(estadoBoton[2] == HIGH && tempPulsacionIni > 50){
          tempPulsacionFin = millis();
          intervalo = tempPulsacionFin - tempPulsacionIni;
          if(intervalo > 50 && intervalo < 2000){
              estadoLuz[1] = !estadoLuz[1];
              tempPulsacionIni = 0;
            }else if(intervalo >= 2000){
                previousMillis = millis();
                apagarLuces = HIGH;
                tempPulsacionIni = 0;
              }
        }
    }
  }
  if(apagarLuces == HIGH){
      long currentMillis = millis();
      if(currentMillis - previousMillis > crono){
          previousMillis = currentMillis;
          estadoLuz[0] = LOW;
          estadoLuz[1] = LOW;
          apagarLuces = LOW;
        }
    }
  for(int i = 0; i < nLuces; i++){
      digitalWrite(Luz[i], estadoLuz[i]);
    }
  estadoBotonAnterior[pulsador] = lecturaPulsador;  
}
  

viernes, 7 de octubre de 2016

Realizar conmutadas con pulsadores.

Hola de nuevo visitantes del blog, en la entrada anterior vimos como encender y apagar algo a través de un pulsador. Sin embargo en una instalación real, cuando entras en tu cuarto por ejemplo, puedes encender la luz desde varios sitios, no solo de uno.

En esta entrada lo que vamos a hacer es convertir nuestros pulsadores en conmutadores o conmutadores de cruce gracias a la programación. La manera en que conectaremos los pulsadores es la siguiente. 


No recuerdo si lo dije en la otra entrada pero las resistencias de los pulsadores deben ser de un valor de 10 kilo-ohmios y la del diodo led de 220 ohmios. 

A continuación os pondré el código de programación para que funcione. Lo que hace es encender o apagar la luz desde cualquiera de los 3 pulsadores de manera que ya podríamos encender la luz desde la puerta de la habitación y desde cada lado de la cama por ejemplo. Comentar que en este código entran en juego funciones, bucles "for" y arrays.. Como esta enfocado a todo el mundo sin que tenga ni remota idea de programar después del código os diré como modificarlo por si queréis cambiarlo a vuestro gusto. 

CÓDIGO DE PROGRAMACIÓN: 

const int pulsadores[] = {2, 3, 4};
const int nPulsadores = 3;

const int Luz = 12;

int estadoLuz = LOW;
int estadoBoton[] = {HIGH, HIGH, HIGH};
int estadoBotonAnterior[] = {HIGH, HIGH, HIGH};

long lastDebounceTime = 0;  
long debounceDelay = 50;    

void setup() {
  for(int i = 0; i < nPulsadores; i++){
      pinMode(pulsadores[i], INPUT);
    }
  pinMode(Luz, OUTPUT);
  digitalWrite(Luz, LOW);
}

void loop() {
  for(int i = 0; i < nPulsadores; i++){
      leerPulsador(i);
    }
}

void leerPulsador(int pulsador){
  int lecturaPulsador = digitalRead(pulsadores[pulsador]);
  if (lecturaPulsador != estadoBotonAnterior[pulsador]) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (lecturaPulsador != estadoBoton[pulsador]) {
      estadoBoton[pulsador] = lecturaPulsador;
      if(estadoBoton[0] == LOW || estadoBoton[1] == LOW || estadoBoton[2] == LOW){
          estadoLuz= !estadoLuz;
        }
    }
  }
  digitalWrite(Luz, estadoLuz);
  estadoBotonAnterior[pulsador] = lecturaPulsador;  
}

Como agregar otro pulsador para que tambien se encienda y apague desde este:

Aveces como electricista es imposible predecir desde cuantos sitios quiere que se encienda la luz, por lo que os enseñare como añadir otro pulsador y siguiendo este sistema podremos añadir los que queramos... 

En el montaje tan solo tendríamos que añadir otro pulsador y resistencia y conectarla igual que los otros conectando el pulsador al pin 5 de Arduino por ejemplo. Luego en la parte de código tendríamos que seguir estos pasos:

  1.  En la linea de código const int pulsadores[] = {2, 3, 4}; añadir el nuevo pulsador, quedando así: const int pulsadores[] = {2, 3, 4, 5};
  2.  En la linea de código const int nPulsadores = 3; cambiaríamos el valor 3 por un 4, ya que ahora tenemos 4 pulsadores.
  3. En las lineas int estadoBoton[] = {HIGH, HIGH, HIGH};int estadoBotonAnterior[] = {HIGH, HIGH, HIGH}; añadiremos también el estado del cuarto pulsador quedando de esta manera: int estadoBoton[] = {HIGH, HIGH, HIGH, HIGH};int estadoBotonAnterior[] = {HIGH, HIGH, HIGH, HIGH};
  4. Y por ultimo en la linea de código  if(estadoBoton[0] == LOW || estadoBoton[1] == LOW || estadoBoton[2] == LOW) añadiremos también el cuarto pulsador quedando así: if(estadoBoton[0] == LOW || estadoBoton[1] == LOW || estadoBoton[2] == LOW || estadoBoton[3] == LOW)
Como vemos es muy fácil encender o apagar una luz desde cualquier sitio, tan solo tenemos que modificar el código de programación y decirle a cada pulsador lo que queremos que encienda o apague. En cambio en una instalación normal, si quisieras encenderlo desde otro lugar tendrías que ir desmontando cajas de empalme y añadiendo cableado nuevo pasándolo por los tubos que hay dentro de la pared hasta llegar al conmutador deseado.. un follón vamos.