domingo, 20 de abril de 2014

Interesantes Interruptores

Los interruptores son la manera más fácil de comunicarnos con Arduino. Podemos conectar un pulsador a cada una de las entradas digitales y asignar una acción a cada uno de ellos. La entrada digital lee HIGH/5V en un estado del interruptor y LOW/0V en el otro y podemos pedir a Arduino que realice una acción dependiendo del estado del interruptor.

Un interruptor en un circuito eléctrico controla un solo dispositivo, mientras que con Arduino podemos asociar al interruptor una secuencia de eventos tan complicada como queramos. Ejemplo: en el video de abajo el pulsador se usa para llevar voltaje a las vías mientras está activado, pero para esto no nos haría falta una Arduino y podríamos haber conectado el interruptor al transistor; en la segunda parte, cuando se activa el interruptor, Arduino lanza una secuencia de acciones: luz verde, espera un segundo, aceleración progresiva, velocidad constante, luz roja y frenada progresiva.



Encontrareis los esquemáticos y códigos para los ejemplos al final de la entrada

Cómo

En un montaje eléctrico colocábamos el interruptor en mitad del cable de alimentación y si estaba abierto, no circulaba corriente. En electrónica de señal tenemos dos puntos de dificultad extra:

  1. Arduino lee el voltaje a la salida del interruptor para saber si está activado, pero no nos interesa que pase intensidad que daría un consumo innecesario. Ya se encargarán los transistores de hacer pasar la intensidad hacia las vías u otros dispositivos.
  2. Una entrada digital debe ver siempre un valor de 5V o 0V, no podemos dejarla al aire porque tomará un valor cualquiera.

Así que no nos vale el primer montaje que se nos ocurre:

Así no: interruptor mal conectado y además el esquemático dibujado 
en la espalda de un sobre da sensación de poca profesionalidad

Porque
  1. esto llevaría a la entrada digital tanta intensidad como suministre la fuente de 5V y la puede quemar
  2.  cuando el interruptor está abierto, la entrada no está forzada a 0V ni a 5V, y puede tomar cualquier valor.

Todo esto se soluciona añadiendo una resistencia de pull-down de 10k que forzará un 0 en la entrada mientras el interruptor esté abierto y que limitará la corriente cuando esté cerrado:

Así sí: Esquemático en una vieja factura de una
tienda de electrónica, este tío es un pro

En una configuración pull-down con el interruptor abierto, la entrada recibe 0V a través de la resistencia. Como no circula corriente no hay pérdida de voltaje y ambos lados de la resistencia ven 0V/LOW. Cuando el interruptor se cierra, circula sólo una corriente de 0.5 mA y tenemos la entrada a 5V/HIGH.

Muy bien: Esquemáticos en bloc de notas de
hotel de lujo. MegaPro

Las entradas digitales de Arduino tienen una resistencia interna de pull-up que nos puede simplificar el conexionado (ejemplo aquí) y podemos prescindir de la resistencia, pero en nuestro programa habrá que tener en cuenta:

1.Se debe declarar el uso de internal pull-up en el setup para el pin que usamos de entrada

      void setup(){
          pinMode(pinStart, INPUT_PULLUP);
      }
      
2. Con un pull-up, la lógica del interruptor se invierte: cuando está abierto da HIGH y cuando está cerrado da LOW


Lectura de un Interruptor

Deberemos declarar en setup todos los interruptores que usemos como entradas. Luego, en loop podemos tomar varias estrategias:

Caso 1: Un único interruptor lanza una función

      void loop(){
        
        while(digitalRead(pinEntrada)==0){
          delay(10);
        }
        ...
        
En este caso, Arduino arrancará y se quedará a la espera de que activemos el interruptor antes de seguir ejecutando el resto del contenido de loop. Al terminar, se vuelve al inicio y a la espera del interruptor.


Caso 2: Más de un interruptor

    void loop(){
      
      if (digitalRead(interruptor1)==HIGH){
       accion1();
      }else if (digitalRead(interruptor2)==HIGH){   
        accion2();
      }
      delay(10);  
    }

En este otro caso, loop sólo está vigilando cuál de los botones es presionado. Las acciones que se ejecutan para cada botón estarían definidas aparte en las subfuciones "accion1()" y "accion2()".

En los ejemplos anteriores tenemos dos limitaciones en nuestro programa:
-          mientras esperamos a leer el interruptor, Arduino no puede hacer nada más: todo lo que se está moviendo se sigue moviendo, todo lo parado sigue parado
-          cuando estamos realizando una secuencia de acciones, no se presta atención al interruptor. Esto puede ser peligroso si nuestro interruptor es por ejemplo un botón de parada de emergencia, al que tenemos que prestar atención sobre todo lo demás.

Para solventar estos dos problemas, los procesadores de Arduino pueden programarse para recibir interrupciones por algunas de sus entradas. Cuando se activa una interrupción se dejará de lado todo lo que se esté haciendo y se ejecutará la acción asignada a la interrupción. Más detalles aquí.


 Multitud de Interruptores

La maqueta necesitará más de un botón de control. Vale la pena construirse una placa con un pulsador para cada una de las acciones que queramos realizar. El montaje que os propongo es un ejemplo con tres pulsadores, pero se puede replicar el montaje hasta ocupar las 13 entradas digitales.


 A medida que la maqueta progresa, podemos ir  modificando las acciones de cada botón, dándoles funciones cada vez más complejas o bien asignarles funciones temporalmente para hacer pruebas.




Conexionado pull-down


Cada interruptor se conecta a 5V a tierra con una resistencia de 10k. Los pines se declaran como INPUT en setup.





Requiere la mitad de elementos, pero debemos tener presente hacer el setup de los pines como INPUT_PULLUP.


Código y Esquemáticos



   Ejemplo 1: Transistor y Pulsador (configuración pull-down)


/* TRANSISTOR INTERRUPTOR   

El tren se moverá mientras se acciona el pulsador

Aceleraciones progresivas con la función voltProgresivo  

CONEXIONES: 
  - Base del Transistor a pin Arduino 11
  - Colector del transistor a una via
  - Emisor del transistor a tierra GND
  - La otra via al positivo de la fuente de alimentación
  - Arduino conectada a la fuente de alimentación
    mediante Vin y GND, ojo a la polaridad
  
Carles F. Abril 2014  

*/
  

int base=11;  // pin para conectar la base del transistor
int interruptor=2;
int pasoVolt=10;  // paso del voltaje para aceleración progresiva
int maxVolt=120; //voltaje máximo = maxVolt *VoltajeFuente/255
int minVolt=40; //voltaje mínimo para que ruede la máquina
                //principio de la aceleración

void setup(){
    pinMode(interruptor,INPUT);
    pinMode(base, OUTPUT);//definimos el pin hacia el transistor como salida
    pinMode(13,OUTPUT);
    analogWrite(base,0);
    digitalWrite(13,LOW);
}

void loop(){
  
  if (digitalRead(interruptor)==HIGH){
    analogWrite(base,80);
    digitalWrite(13,HIGH);
    
  }else{
    analogWrite(base,0);
    digitalWrite(13,LOW);
  }
  delay(10);
  >
}



   Ejemplo 2: Secuencia de Órdenes (configuración con pull-up interno)


/* SECUENCIA DE ORDENES   

Cuando se pulsa el botón, el semáforo pasa a verde, el tren
acelera progresivamente, se mueve a velocidad constante durante
dos segundos, cambia el semáforo a rojo y frena progresivamente.

Aceleraciones progresivas con la función voltProgresivo  

CONEXIONES: 
  - Interruptor a GND por un lado y al pin 7 por otro
  - Led rojo con resistencia de 470 ohm en seria al pin 6 por un lado 
    y a GND por el otro
  - Led verde con resistencia de 470 ohm en seria al pin 5 por un lado 
    y a GND por el otro
  - Base del Transistor a pin Arduino 11
  - Colector del transistor a una via
  - Emisor del transistor a tierra GND
  - La otra via al positivo de la fuente de alimentación
  - Arduino conectada a la fuente de alimentación mediante Vin y GND, 
  ojo a la polaridad
  
Carles F., Abril 2014  


*/
  
int pinStart=7; // pin del interruptor
int ledRojo=6;  // pin para el led rojo
int ledVerde=5; // pin para el led verde

int base=11;  // pin para conectar la base del transistor
int pasoVolt=10;  // paso del voltaje para aceleración progresiva
int maxVolt=120; //voltaje máximo = maxVolt *VoltajeFuente/255
int minVolt=60; //voltaje mínimo para que ruede la máquina
                //principio de la aceleración

void setup(){
    pinMode(pinStart, INPUT_PULLUP);
    pinMode(ledRojo, OUTPUT);
    pinMode(ledVerde, OUTPUT);
    pinMode(base, OUTPUT);
    
    digitalWrite(ledVerde,LOW); //inicializa las salidas
    digitalWrite(ledRojo,HIGH);
    analogWrite(base,0);
        
}

void loop(){
  
  while(digitalRead(pinStart)==1){
    delay(10);
  }  // mientras no pulsamos el botón, 
     // damos vueltas dentro del while
  
  digitalWrite(ledVerde,HIGH); //luz verde
  digitalWrite(ledRojo,LOW);
  delay(1000);
  voltProgresivo(minVolt, maxVolt, base, 300, pasoVolt); //acelera
  delay(2000); //mantiene velocidad durante 2 segundos
  
  digitalWrite(ledVerde,LOW);  //luz roja
  digitalWrite(ledRojo,HIGH);  
  delay(600);
  voltProgresivo(maxVolt, minVolt, base, 300, pasoVolt); //frena
  analogWrite(base,0); //desactivamos el transistor
  delay(100);  //volvemos a esperar al botón  
               
}

void voltProgresivo(int startV, int endV, int digiHigh, int timeSpacing, int VSpacing){
  
  /* modifica el PWM progresivamente, en pasos de VSpacing
  (recomendado 10) cada timeSpacing (milisegundos).digiHigh is el puerto de salida
  de Arduino (4, 5, 6, 9, 10 u 11). 
  
  endV-startV debe ser divisible por VSpacing

  */
  
  /* ejemplo acelerando  voltProgresivo(80, 160, 7, 200, 10);
     example frendando  voltProgresivo(160, 80, 7, 200, 10);*/
  
  int steps = (endV - startV)/VSpacing;
  int direcc;
  
  if (steps > 0) {
    direcc = -1;
  }else{
    direcc=1;
  }
  
  for (int i=1; i < abs(steps+1); i++){  
    int salida=startV-VSpacing *i*direcc;
    if (salida > 200){
      salida = 200;
    } else if (salida < 0){
      salida=0;
    }
    
    analogWrite(digiHigh, salida);
    delay (timeSpacing);
  }
}

  
  
  




1 comentario:

  1. Estimado Carles, estaba trabajando exactamente en esto y sin lograr los resultados satisfactorios de su programa.
    Mis sinceras felicitaciones por lo fino del trabajo que hizo.
    Busqué en los comentarios algún mail para comentarle esto más directamente, pero no lo encontré.
    Espero reciba este comentario, desde el norte de Argentina.
    Un afectuoso saludo.

    Mario Lucio Pereyra
    marioluciopereyra@gmail.com

    ResponderEliminar