Felix Maocho

Para quien le interese lo que a nosotros nos interesa

5º Ejercicio de uso de pines digitales de entrada INPUT– Linterna multiuso – 1º Exposición de los problemas

linternaPor Félix Maocho
27/1/2017,

Conocimientos que se precisan

Para realizar este ejercicio tal como aquí se resuelve solo se necesitan los conocimientos que se han ido explicando hasta el capítulo dedicado al Uso de los pines digitales como entrada (IN PUT), que podemos resumir en los siguientes puntos:

Saber escribir, “subir” a la Tarjeta Arduino un sketch o programa
Conocer las funciones “int”, “pinMode”, “digitalWrite”, e “if”

Enunciado del problema

Queremos construir una linterna nultiuso que funcione de la siguiente forma:

– La primera pulsacion del botón, enciende un led blanco
– La segunda vez, se encienden a la vez dos leds blancos
– La tercera vez, se enciende tres leds blancos o
– La cuarta un led rojo se pone intermitente
– La quinta apaga todas las luces de la linterna

Material necesario

  • Tarjeta Arduino y cable de conexiones
  • Tarjeta de prototipado o “protoboard”
  • 12 Cables de conexiones macho/macho (preferiblemente 5 rojos , 6 azules 1 )
  • 4 Resistencias de 220 Ω
  • 4 Led ( preferiblemente 3 blancos y 1 rojo)
  • 1 pulsador o “Push button”

Objetivos

  • Ejercitarse en el uso de los pines digitales de OUPUT e INPUT
  • Practicar el montaje de pulsadores  
  • Detectar los problemas que puede dar la ·función “delay” y la forma de soslayarlos
  • Iniciarse en la resolución de multitareas simulando manualmente su funcionamiento
  • Introducir la nocion de usabilidad.
  • Introducion al concepto de Firmware

Especificaciones

La linterna tiene un botón que abre y cierra un circuito. Cada vez que se cierra el circuito, aumenta una unidad en un contador. En función del valor del contador la linterna hará lo indicado a su número de acuerdo con lo que se indica.

Inicialmente contador = 0,
Probar si se ha apretado el contador (PIN 2)
Si se ha apretado, sumar uno al valor del contador
Si contador = 0 – No hacer nada
Si contador = 1 – Encender un Led blanco (PIN 4)
Si contador = 2 – Encender un segundo Led blanco. (PIN 7)
Si contador = 3 – Encender un tercer Led blanco (PIN 8)
Si contador = 4 – Apagar los contadores y encender intermitentemente el Led rojo (PIN 12)
Si contador = 5 – Apegar el led rojo y poner nuevamente el contador = 0
Repetir el ciclo

Hardware

Habrá por tanto que abrir un pin a INPUT para controlar el pulsador dedicaremos el Pin 2 y cuatro pin a OUPUT para cada uno de los leds dedicaremos los pines 4, 7, 8 y 12 Elijo esos pines porque en Arduino Uno son los que tiene menos valor por no tener otra misión posible que ser pins de INPUT/OUPUT

El montaje del pulsador sera PULL DOWN que no precisa consumo de corriente cuando no se oprime el botón lo que ocurrirá casi todo el tiempo, aparte del mayor desgaste de la Tarjeta Arduino tenemos un consumo mayor de energía eléctrica. En este caso el interruptor ha de ser por fuerza un pulsador, una llave de la luz vale para dejar pasar o cortar la corriente, dos fases, pero en este caso el pulsador permite hacer varias cosas diferentes en conjunto tiene 5 posibilidades diferentes.

En función de lo indicado el esquema será tal como se indica en esta imagen.

linterna-multiuso

El esquema es el habitual, 5 circuitos diferentes, unos alimentado por el pin 4, 7, 8 y 12 que contiene un led blanco los tres primeros (4,7 y 8) y rojo el pin 12 con sus correspondientes resistencias de 220 Ω y otro circuito que contiene el push button, (pulsador), en este caso del tipo NO, (normalmente abierto), es decir que cuando no se pulsa corta el paso de la electricidad (0V) y cuando se pulsa cierra el circuito y el voltaje sube a 5V

Como es un montaje PULL DOWN el orden de los elementos es el siguiente:

  • Fuente de corriente eléctrica a 5V
  • Pulsador
  • Segmento de cable (color verde)que acaba en el Pin 2 que hará la lectura del voltaje
  • Resistencia del circuito (1000 Ω, porque no hay otras dispositivos que reduzcan el voltaje e impidan un cortocircuito)
  • Tierra

Software

Este programa es un poco traicionero, pues como la tradicional película de chinos, tiene muchas mas trampas que no se ven a simple vista. En principio, parece que este ejercicio no presenta problemas muy diferentes de los que los que hemos solucionando hasta ahora, pero hay varios problemas ocultos: ¿Cómo saber diferenciar que han oprimido el botón una vez o varias? ¿Como contar las pulsaciones? y ¿Cómo evitar una y otra vez mandar lucir un led que ya esta luciendo?. ¿Como hacer enterarse Arduino que hemos apretado el pulsador el si estamos ·”entretenidos” encendiendo y apagando la luz roja intermitente?.

“Solución” a primera vista

Comenzaremos a hacer lo que aparentemente es suficiente, para que veamos donde están los errores, pues como he escrito varias veces, no hay mejor forma de aprender que caer en el error y aprender a salir de él.

En principio se diría que que una repetida colección de funciones if es suficiente. Probemos

/* Sketch E7.01 41 Linterna multiuso ( erroneamente programada)
* Inicialmente contador = 0,
* Probar si se ha apretado el el botón (PIN 2)
* Si se ha apretado, sumar uno al valor del contador
* Si contador = 0 – No hacer nada
* Si contador = 1 – Encender un Led blanco (PIN 4)
* Si contador = 2 – Encender un segundo Led blanco. (PIN 7)
* Si contador = 3 – Encender un tercer Led blanco (PIN 8)
* Si contador = 4 – Apagar los leds blancos
* Encender intermitentemente el Led rojo (PIN 12)
* Si contador = 5 – Apegar el led rojo
* Hacer contador = 0
* Repetir el ciclo
*/
// Área de definición de variables y parámetros
int pinled1 = 4; // pin en OUTPUT para el LED ! (blanco)
int pinled2 = 7; // pin en OUTPUT para el LED 2 (blanco)
int pinled3 = 9; // pin en OUTPUT para el LED 3 (blanco)
int pinledrojo = 12; // pin en OUTPUT para el LED ROJO
int pininp = 2; // pin que se abre en INPUT
int corriente = 0; // Si hay 5V toma el valor 1 , si hay 0V, 0
int j = 0; // Contador de 0 a 5 de las veces que se pulsa el botón
int tiempo = 2000; // tiempo para el delay de 2 segundos
int rebote = 100; // tiempo para evitar los posibles en la medición
// Función setup
void setup() {
pinMode( pinled1, OUTPUT); // enciende led 1
pinMode( pinled2, OUTPUT); // enciende led 2
pinMode( pinled3, OUTPUT); // enciende led 3
pinMode(pinledrojo, OUTPUT); // enciende led rojo
pinMode(pininp, INPUT); // Pin abierto como INPUT, lee el voltaje
}
// Función loop
void loop() {
// Probar si se ha apretado el el botón (PIN 2)
delay (rebote) ; // Retardo para evitar “rebote” de los interruptores
corriente = digitalRead(pininp); // 1º comprobar el voltaje
// Si se ha apretado, sumar uno al valor del contador
if (corriente == 1) { // han apretado el pulsador)
j = j + 1; // Se suma al contador j una unidad
}
// Si contador = 1 – Encender un Led blanco (PIN 4)
if (j == 1) {
digitalWrite(pinled1, HIGH);
} // Fin if (j == 1)
// Si contador = 2 – Encender un segundo Led blanco. (PIN 7)
if (j == 2) {
digitalWrite(pinled2, HIGH);
} // Fin if (j == 2)
// Si contador = 3 – Encender un tercer Led blanco (PIN 8)
if (j == 3) {
digitalWrite(pinled3, HIGH);
} // Fin if (j == 3)
// Si contador = 4
if (j == 4) {
// Apagar los Leds blancos
digitalWrite(pinled1, LOW);
digitalWrite(pinled2, LOW);
digitalWrite(pinled3, LOW);
// Encender intermitentemente el Led rojo (PIN 12)
digitalWrite(pinledrojo, HIGH); // Encender rojo
delay (tiempo); // parada durante un tiempo
digitalWrite(pinledrojo, LOW); // Apagar rojo
delay (tiempo); // parada durante un tiempo
} // Fin if (j == 4)
// Si contador = 5 – Apagar el led rojo y poner j a cero
if (j == 5) {
digitalWrite(pinledrojo, LOW); // Apagar rojo
j = 0;
} // Fin if (j == 5)
} // cierre de la función loop. Repetir el ciclo

Aparentemente no puede fallar pero falla

Aparentemente no puede fallar. Lo hemos hecho un montón de veces y no ha fallado. Hemos colocado antes de efectuar la lectura del voltaje del pulsador “delay (rebote) ; “. Como indicamos al estudiar los pulsadores, el corte repentino de corriente provoca unos flujos parasitarios de corriente, semejantes a unas olas que producen un efecto ariete en una cañería, que puede hacer que alcance cualquier voltaje voltaje el cable que teóricamente unas veces sólo puede tener 0 y otras que solopuede tener 5 voltios. La forma más sencilla de evitar falsas lecturas, es dar un tiempo a que se calme “el oleaje voltaico”, ese tiempo es sobradamente 100 milisegundos. es decir una décima de segundo, algo inapreciable.

Otra cosa es que puede asombrar, es que hayamos utilizado para el contador el nombre “j” esto viene de una “vieja” tradición de los programadores, que en los comienzos de la informática ahorraban espacio utilizando variables de un solo carácter en el caso de variables locales, (las que se usan solo dentro de un programa, en nuestro caso todas) y solo tres caracteres para las variable generales (que se usaban en varios programas), por ejemplo “cli” por código de cliente, “dom” por domicilio etc.

Generalmente las variables locales se nombraban consecutivamente “a” “b” “c” “d”. Lo podríamos seguir haciendo nada impide poner “a” en vez de “pinled1” o “d” en vez de “pinledrojo” pero la lectura y comprensión del programa se obscurece y ahora que tenemos memoria abundante, este ahorro no tiene sentido.

Entonces las variables que se utilizaban para contador se utilizaban las letras “j”, “k” ,”l”, … porque no suelen ser ningún concepto, sólo un valor que aumenta poco a poco, en nuestro caso solo el número de índice de un menú de tareas diferentes, y con esta costumbre se ha quedado hasta nuestros tiempos, podríamos perfectamente llamarlo “contadorpulsaciones” pero prefiero llamarlo “j” para que cuando vean una cosa así en otro programa, la entiendan.

Bien, pueden copiar y pegar este programa en el editor de IDE compilarlo y cargarlo, pero observarán que el programa funciona imprevisiblemente, igual se enciende una luz, como varias o el intermitente rojo ¿Porque pasa esto?

Localizar los errores

Veamos lo que pasa en el simulador. En dos  lecciónes annteriores les mostraba, eun una primera  el simulador UnoArduSim y en otra posterior la forma de usarlo, algo que nos va a ser en este caso de mucha utilidad.

Comencemos por definir primero los dispositivos de entrada/salida (I/O Devices) que vamos a utilizar. En nuestro caso, es un pulsador, (pushbutton), y cuatro leds. (tres blancos y uno rojo). En el simulador no hay leds blancos, por lo que utilizare tres amarillos (Y), que es lo mas parecido que hay.

i-o-devices

Una vez escrito y dado OK la pantalla del programa aparece con los dispositivos en la parte derecha. Ha continuación hay que configurarlos según los utiliza el programa. El pushbutton por el pin 2 y con montaje PULL DOWN, los leds amarillos (Yelow =Y) en los pines 4, 7 y 9 y el rojo (Red=R) en el pin 12

´
primerprograma-preparado-2

Eligiendo la opción de menú File (fichero) y Edit/View (Editar/Ver), aparece una pantalla que nos permite mediante copy/paste trasladar el texto del programa a la simulación. Lo compilamos, si hemos hecho la copia completa, no dará errores, porque yo lo he depurado antes de ponerla en el post y así por fin conseguiremos una pantalla que tiene el siguiente aspecto

primerprograma-preparado

A la derecha la simulación gráfica, tal como hemos explicado y configurado u a la izquierda el programa y debajo los valores que en este momento tienen las distintas variables, en te caso los calores iniciales.

Para que se vea claro como funciona el programa, en la opción de menú “Execute” he marcado la opción “Animate”, que hace ver una banda azul que indica en cada momento la linea de programa que está ejecutando, Tiene el inconveniente que retardar muchísimo la ejecución, pues el programa además de hacer lo que corresponda tiene que situar la linea azul donde corresponda en la imagen de la pantalla con el programa que se ejecuta , lo que hace que en la realidad todo ocurra unas 100 veces mas lento que en la realidad. Así y todo vean lo que ocurre cuando en esta misma opción de menú se lanza el programa oprimiendo RUN. Pueden lanzarlo y pararlo tantas veces como quieran escribiendo RESET y muevamente RUN Nosotros lo hemos hecho un par de veces.

Observa lo rápido que va y posiblemente su velocidad real sea de 10 a 100 veces mas rápido por lo que la frena el representar la barra azul. A esa velocidad no hay posibilidad de apretar un botón y levantar el dedo, antes que el programa haya leído el voltaje varias veces, por tanto la máquina va a “pensar”, que la has apretado seguidamente varias veces y te va a situar, en cualquiera de los menús, posiblemente en el cuarto, pues cuando esté en el cuarto va a tener que hacer una intermitencia roja y ahí si que estará bastante tiempo.

Para verlo con detalle vamos a hacerlo a cámara lenta. El programa UnoArduSim tiene una opción en que los programas pasan a cámara lenta. Está en la opción de menú “Execute“ es la última línea “Slow Motion” (Amara lenta). Eligiendo esta opción todo ocurre mas lento y así podremos hacer encender un led dos y tres y luego el rojo. Para ello basta tener el botón apretado cuando la linea azul pasa po54r la parte alta del programa que es donde hemos situado el control del “pushbutton”..  Veamos el vídeo.

Observarán que cuando se enciende el led rojo la barra se queda parada aquí, es porque ha entrado en la “anestesia” que le producen los “delay” de hacer la intermitencia de la luz roja, Mientras esté haciendo esta intermitencia, como el programa no consulta el voltaje del pulsador no se “entera” de que le estamos mandando apagar todo, es mas cuando entremos en la parte de la intermitencia apagada pensaremos que hemos conseguido apagar la linterna, pero veremos que no responde a la hora de pedir que la encienda de4 nuevo y que acabada la intermitencia , rápidamente pasa por ahí otra ves y entra en otra intermitencia, La forma mas practica de apagar la linterna es haciendo nuevamente RESET

Y no han acabado ahí los problemas. Hay otra cosa que me irrita bastante aunque en si mismo no es un problema. Mientras el valor de “j” no varíe y sea por ejemplo 2, en cada “loop” la máquina va a intentar encender el segundo led, La cosa no tiene la menor importancia porque como el led ya esta encendido no va a hacer mas que encenderle de nuevo y ni se va a notar, pero hacer cosas que no valen para nada es un poco tonto.

Para que lo noten voy a dejar el aparato con dos led encendidos, en la parte de las variables abajo verán que la “j” adquiere el valor 2 pero en cada vuelta verán que entra en el “if (j ==2) y intenta encender el led. Para que lo vean en el video con más facilidad he puesto un pequeño “delay” inmediatamente debajo de encender el segundo led, verán así claramente que si “j” es 2 , el programa entra en ese “if” e intenta encender el segundo led aunque ya este encendido. Veanlo en este tercer vídeo.

Comienzo poniendo la barra azul sobre el “delay” que he puesto después de encender el segundo led. Este “delay” es absolutamente innecesario pero ayudar a ver cuando el programa se mete en ese “if”

Luego hago un RESET y a continuación un RUN para iniciar el programa. El programa trabaja como antes, porque como ”j” no vale 2 y no entra en el “delay” que he puesto,

Con el ratón aprieto el pulsador y se enciende el primer led. No pasa nada especial porque “j “ ha adquirido el valor 1 se enciende el primer led y punto. Cuando enciendo el segundo led verán que a continuación hace el pequeño “delay” que he puesto y que a partir de entonces y mientras “j” valga 2 va a hacer ese “delay”,  señal que el programa pasa por ahí en todos los “loop” y que por lo tanto va a intentar encender el led, aunque el led ya esta encendido.

Nuevamente pulso el botón, “j” adquiere el valor 3 se enciende el tercer led pero el programa como es lógico ya no pasa por el “if(j==2)” y nuevamente no vuelve a parar en el “delay”, 

Como hemos hecho con el valor 2 de “j” pasaria con el valor 1, 3, 4 y 5 en cada caso intentaria entrar repetidamente en “if” que lo que hacen es encender y apagar leds.

Problemas detectados

Así pues hemos detectado tres problemas, uno menor, más bien una manía mía, “un programa no debe dar pasos innecesarios”. Tal como está hecho este programa, los led son encendidos o apagados como corresponda en función del Menú, en cada “loop”.

Habría que buscar una forma de que esto no pasara.

El segundo problema es mas grave, al hacer la intermitencia, el programa entra en un estado “catatónico” y no se entra si aprietas el botón o no.

Hay que buscar una solución a este problema de la intermitencia.

El tercer problema también es delicado, La máquina tiene mucha dificultad para diferenciar si las pulsaciones son diferentes o es la misma pero no hemos levantado el dedo del botón, ¿Cómo lo resolvemos?

Hay que saner identificar el número de pulsaciones realizadas.

Hay muchas formas de solucionar estos problemas, En el próximo programa dedicado a Arduino daré una solución, que no es única ni posiblemente sea la mejor, hasta entonces tienes tiempo para tratarde resolver el problema.

Félix Maocho

 

indice

 

 

Anuncios

27 enero 2017 - Posted by | Curso de Arduino, General | , , ,

Aún no hay comentarios.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: