Documentos de Académico
Documentos de Profesional
Documentos de Cultura
pulsador para peatones para solicitar el cruce de la vía. El Arduino reaccionará cuando se presione
el botón cambiando el estado de las luces para hacer que los autos se detengan y permitan que el
peatón cruce de manera segura.
Por primera vez podemos interactuar con el Arduino y hacer que haga algo cuando cambiamos el
estado de un botón que el Arduino está observando (es decir, presionarlo para cambiar el estado
de abierto a cerrado). En este proyecto también aprenderemos a crear nuestras propias funciones.
De ahora en adelante, cuando conectemos los componentes, ya no incluiremos la placa ni los
cables de puente. Tómelo como si estuviera claro que siempre necesitará ambos.
Que necesitarás
Conecte los LED y el interruptor como en el diagrama de la página anterior. Deberá pasar los cables
desde los pines 8, 9 y 10 en el proyecto anterior hasta los pines 10, 11 y 12 para permitirle
conectar las luces para peatones a los pines 8 y 9.
Ingrese el código
Ingrese el código en la página siguiente, verifíquelo y cárguelo. Cuando ejecutes el programa verás
que el semáforo de automóviles comienza en verde para permitir el paso de los automóviles y el
semáforo de peatones está en rojo. Al pulsar el botón, el programa comprueba que hayan
transcurrido al menos 5 segundos desde la última vez que se cambiaron las luces (para permitir
que el tráfico se mueva), y si es así pasa la ejecución de código a la función que hemos creado
llamada changeLights() . En esta función, las luces del automóvil pasan de verde a ámbar, luego a
rojo y luego las luces de peatones se vuelven verdes. Después de un período de tiempo establecido
en la variable crossTime (tiempo suficiente para permitir que los peatones crucen), la luz verde
para peatones se encenderá y apagará intermitentemente como advertencia a los peatones para
que se apresuren ya que las luces están a punto de volver a cambiar a roja. . Luego, el semáforo
para peatones vuelve a cambiar a rojo y las luces del vehículo pasan de rojo a ámbar y luego a
verde y el tráfico puede reanudarse. El código de este proyecto es similar al del proyecto anterior.
Sin embargo, se han introducido algunas declaraciones y conceptos nuevos, así que echémosles un
vistazo.
void loop() {
int state = digitalRead(button);
/* check if button is pressed and it is
over 5 seconds since last button press */
if (state == HIGH && (millis() - changeTime) > 5000) {
// Call the function to change the lights
changeLights();
}
}
void changeLights() {
digitalWrite(carGreen, LOW); // green off
digitalWrite(carYellow, HIGH); // yellow on
delay(2000); // wait 2 seconds
digitalWrite(carYellow, LOW); // yellow off
digitalWrite(carRed, HIGH); // red on
delay(1000); // wait 1 second till its safe
digitalWrite(pedRed, LOW); // ped red off
digitalWrite(pedGreen, HIGH); // ped green on
delay(crossTime); // wait for preset time period
// flash the ped green
for (int x=0; x<10; x++) {
digitalWrite(pedGreen, HIGH);
delay(250);
digitalWrite(pedGreen, LOW);
delay(250);
}
La mayor parte del código de este proyecto lo comprenderá y reconocerá de proyectos anteriores.
Sin embargo, echemos un vistazo a algunas palabras clave y conceptos nuevos que se han
introducido en este boceto.
Aquí tenemos un nuevo tipo de datos para una variable. Anteriormente hemos creado tipos de
datos enteros, que pueden almacenar un número entre -32,768 y 32,767. Esta vez hemos creado
un tipo de datos largo, que puede almacenar un número desde -2.147.483.648 hasta
2.147.483.647. Sin embargo, hemos especificado un largo sin signo, lo que significa que la variable
no puede almacenar números negativos, lo que nos da un rango de 0 a 4.294.967.295. Si usáramos
un número entero para almacenar el tiempo transcurrido desde el último cambio de luces, solo
obtendríamos un tiempo máximo de 32 segundos antes de que la variable entera alcanzara un
número superior al que podía almacenar.
Como es poco probable que se use un paso de peatones cada 32 segundos, no queremos que
nuestro programa falle debido a que nuestra variable se "desborde" cuando intenta almacenar un
número demasiado alto para el tipo de datos de la variable. Es por eso que utilizamos un tipo de
datos largos sin firmar, ya que ahora tenemos una gran cantidad de tiempo entre las pulsaciones
de botones.
Como es bastante inevitable que se presione el botón de un paso de peatones al menos una vez
cada 49 días, no deberíamos tener problemas con este tipo de datos. Quizás se pregunte por qué
no tenemos un solo tipo de datos que pueda almacenar cantidades enormes todo el tiempo y
terminar con ello. Bueno, la razón por la que no hacemos eso es porque las variables ocupan
espacio en la memoria y cuanto mayor es el número, más memoria se utiliza para almacenar
variables. En el PC o portátil de tu casa no tendrás que preocuparte mucho por eso, pero en un
microcontrolador pequeño como el Atmega328 que usa Arduino es esencial que usemos solo el
tipo de datos variable más pequeño necesario para nuestro propósito.
Hay varios tipos de datos que podemos usar como nuestros bocetos y estos son:
Data type RAM Number Range
Void keyword N/A N/A
Boolean 1 byte 0 to 1 (True or False)
Byte 1 byte 0 to 255
Char 1 byte -128 to 127
Unsigned char 1byte 0 to 255
Int 2 byte -32,768 to 32,767
Unsigned int 2 byte 0 to 65,535
Word 2 byte 0 to 65,535
Long 4 byte -2,147,483,648 to
2,147,483,647
Unigned long 4 byte 0 to 4,294,967,295
Float 4 byte -3.4028235E+38 to
3.4028235E+38
Double 4 byte -3.4028235E+38 to
3.4028235E+38
String 1 byte + x Arrays of chars
Array 1 byte + x Collection of variables
Cada tipo de datos utiliza una cierta cantidad de memoria en Arduino, como puede ver en el
cuadro anterior. Algunas variables usan sólo 1 byte de memoria y otras usan 4 o más (no te
preocupes por lo que es un byte por ahora, ya que discutiremos esto más adelante). No puede
copiar datos de un tipo de datos a otro, p. Si x fuera un int e y fuera una cadena, entonces x = y no
funcionaría ya que los dos tipos de datos son diferentes.
El Atmega168 tiene 1Kb (1000 bytes) y el Atmega328 tiene 2Kb (2000 bytes) de SRAM. Esto no es
mucho y en programas grandes con muchas variables, fácilmente podría quedarse sin memoria si
no optimiza el uso de los tipos de datos correctos. En la lista anterior podemos ver claramente que
nuestro uso del tipo de datos int es un desperdicio ya que utiliza 2 bytes y puede almacenar un
número de hasta 32,767. Como hemos utilizado int para almacenar el número de nuestro pin
digital, que sólo llegará hasta 13 en nuestro Arduino (y hasta 54 en el Arduino Mega), hemos
consumido más memoria de la necesaria. Podríamos haber ahorrado memoria usando el tipo de
datos byte, que puede almacenar un número entre 0 y 255, que es más que suficiente para
almacenar el número de un pin de E/S.
A continuación tenemos
pinMode(button, INPUT);
Esto le dice al Arduino que queremos usar el Pin Digital 2 (botón = 2) como en INPUT. Usaremos el
pin 2 para escuchar las pulsaciones de botones, por lo que su modo debe configurarse en entrada.
En el bucle principal del programa comprobamos el estado del pin digital 2 con esta declaración:
Esto inicializa un número entero (sí, es un desperdicio y deberíamos usar un booleano) llamado
"estado" y luego establece el valor del estado para que sea el valor del pin digital 2. La declaración
digitalRead lee el estado del pin digital dentro del paréntesis y lo devuelve. al número entero al
que se lo hemos asignado. Luego podemos verificar el valor en el estado para ver si el botón se ha
presionado o no.
if (state == HIGH && (millis() - changeTime) > 5000) { // Call the function to change the lights
changeLights(); }
Cuando leemos un pin digital usando el comando digitalRead, el estado del pin será ALTO o BAJO.
Entonces el comando if en nuestro boceto se ve así
Lo que estamos haciendo aquí es comprobar que se han cumplido dos condiciones. La primera es
que la variable llamada estado es alta. Si se ha presionado el botón, el estado será alto, ya que ya
lo hemos configurado para que sea el valor leído desde el pin digital 2. También estamos
verificando que el valor de millis()-changeTime sea mayor que 5000 (usando el comando lógico
AND &&). La función millis() está integrada en el lenguaje Arduino y devuelve el número de
milisegundos desde que Arduino comenzó a ejecutar el programa actual. Nuestra variable
changeTime inicialmente no tendrá ningún valor, pero después de que se haya ejecutado la
función changeLights), la configuramos al final de esa función con el valor actual de millis().By
subtracting the value in the changeTime variable from the current millis() value we can check if 5
seconds have passed since changeTime was last set. The calculation of millis()-changeTime is put
inside itʼs own set of parenthesis to ensure that we compare the value of state and the result of
this calculation and not the value of millis() on its own.
state == HIGH
y el cálculo es un ejemplo de operador booleano. En este caso significa Y. Para ver qué queremos
decir con esto, echemos un vistazo a todos los operadores booleanos.
Estas son declaraciones lógicas y se pueden usar para probar varias condiciones en declaraciones
if. && significa verdadero si ambos operandos son verdaderos, p. :
if (!x) {....... Will run if x is false, i.e. equals zero. You can also ʻnestʼ conditions with parenthesis, for
example if (x==5 && (y==10 || z==25)) {.......
En este caso, las condiciones entre paréntesis se procesan por separado y se tratan como una
condición única y luego se comparan con la segunda condición. Entonces, si dibujamos una tabla
de verdad simple para esta afirmación, podemos ver cómo funciona.
Cuando changeLights(); se llama, la ejecución del código salta de la línea actual a la función,
ejecuta el código dentro de esa función y luego regresa al punto en el código después de donde se
llamó la función.
Entonces, en este caso, si se cumplen las condiciones en la declaración if, entonces el programa
ejecuta el código dentro de la función y luego regresa a la siguiente línea después de
changeLights(); en la declaración if. El código dentro de la función simplemente cambia las luces
del vehículo a rojo, pasando a ámbar, y luego enciende la luz verde para peatones. Después de un
período de tiempo establecido por la variable crossTime la luz parpadea unas cuantas veces para
advertir al peatón que su tiempo está por terminar, luego el semáforo para peatones se pone rojo
y la luz del vehículo pasa de rojo a verde, pasando por ámbar y vuelve a es estado normal.
El bucle del programa principal simplemente verifica continuamente si el botón de peatón ha sido
presionado o no y si es así, y (&&) el tiempo desde la última vez que se cambiaron las luces es
mayor a 5 segundos, llama nuevamente a la función changeLights().
En este programa no hubo ningún beneficio al poner el código en su propia función aparte de
hacer que el código pareciera más limpio. Sólo cuando a una función se le pasan parámetros y/o
devuelve datos, sus verdaderos beneficios salen a la luz y lo veremos más adelante. A
continuación, vamos a utilizar muchos más LED para crear un efecto de persecución de LED estilo
"Knight Rider".