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:
- 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.
- 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
- esto llevaría a la entrada digital tanta intensidad como suministre la fuente de 5V y la puede quemar
- 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
Caso 1: Un único interruptor lanza una función
Caso 2: Más de un interruptor
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í.
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.
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.
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); } }