Arduino-Básico Asensor 2021
Arduino-Básico Asensor 2021
Descripción de Arduino
Arduino es una placa de circuitos electrónicos que incorpora dos elementos interesantes:
La utilidad de arduino es realizar montajes con circuitos simples que realicen funciones de
automatización y robótica de una forma fácil y rápida. Para ello, el usuario escribe un
programa, código, o conjunto de instrucciones que se guarda en la memoria de arduino y
que se ejecuta en el microprocesador
Una característica flexible de arduino es que las conexiones de la parte superior (etiquetadas
con la palabra "DIGITAL"), son entradas o salidas a elección del usuario que realiza el
montaje y la programación. Si necesitas una salida o una entrada, puedes elegir un pin
cualquiera y configurarlo como desees -entrada o salida-. El problema es que no hay
muchos pines disponibles, pero la mayoría los que hay son entradas o salidas a elegir.
Un aspecto cómodo de arduino es que incorpora una conexión USB con la que se
puede conectar a un ordenador normal. Así, resulta sencillo programarlo y verificar su
funcionamiento.
Simulador de arduino.
En vez de utilizar un robot real, vamos a realizar ejercicios y ejemplos con un simulador
online que se ejecuta en un navegador.
www.tinkercad.com
En este simulador, se puede colocar componentes en un tablero virtual y además realizar la
programación en un editor que incorpora la propia página. La compilación, descarga y
ejecución del código es realizado por la misma página del simulador.
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, HIGH);
delay(1000); // Wait for 1000 millisecond(s)
digitalWrite(13, LOW);
delay(1000 ); // Wait for 1000 millisecond(s)
}
Lo primero que hay que observar es que aparecen dos funciones llamadas "setup" y "loop".
Cada una de ellas encierra entre llaves { } unas instrucciones que son el programa que
ejecutará arduino. El siguiente diagrama te ayudará a identificar las funciones y sus partes
En el ejemplo, estas instrucciones aparecen porque las ha puesto el simulador por su
cuenta, pero la misión del programador es escribir aquí las instrucciones de lo que se desee
ejecutar. Tú tendrás que escribir las instrucciones adecuadas para solucionar el problema
que se te plantee en el futuro.
setup()
La función setup() es una función que se ejecuta en el momento en el que se
enciende o inicia el arduino. Las instrucciones o código que escribas allí, se ejecutarán sólo
una vez, y lo harán al principio. Esta función sirve para preparar lo necesario en el momento
inicial, para establecer unas condiciones de funcionamiento concretas en el primer
momento.
Por ejemplo, supón que arduino está controlando un sensor infrarrojo que detecta
personas que pasan por un pasillo y contándolas. Al principio deberemos establecer en 0 las
personas que han pasado, y después durante el funcionamiento normal, cada persona
detectada incrementará esa cuenta.
loop()
La función loop es la función principal. Allí se escribe el programa que deberá
ejecutar arduino. Esta función se ejecuta una y otra vez indefinidamente. Cuando termina su
ejecución, vuelve a iniciarse otra vez, y así hasta que se desconecte arduino. Si el programa
va a controlar algo durante mucho tiempo (por ejemplo una puerta automática que se abre
cuando detecta la presencia de un objeto) no hace falta hacer un bucle infinito, ya que la
función loop se ejecuta una y otra vez
Funciones utilizadas
Ahora analizaremos las líneas de código escritas, explicando qué ocurre en ellas.
delay();
setup y loop, son dos funciones que debes hacer tú. Sin embargo, delay() es una
función que está completamente hecha y que se "invoca", "llama" o "ejecuta" en tu
programa. Puedes usarla escribiéndola como en el ejemplo anterior. Tan sólo has de elegir
un número y ponerlo entre paréntesis. Cuando el programa se ejecute, y llegue a la línea
donde está escrita esta función, arduino se parará por un tiempo. Todo se quedará tal como
esté en ese momento y nada cambiará ni se ejecutará la siguiente instrucción hasta que
transcurra el tiempo especificado. Después de ese tiempo, el programa seguirá
ejecutándose en la siguiente instrucción al delay. Entre paréntesis escribes el tiempo (en
milisegundos) que el programa ha de estar parado.
delay(1000);
pinMode()
pinMode() es una función que también es llamada por el programa y que el
programador escribe cuando la necesita. Su tarea es configurar un pin para indicar que es
de entrada o de salida. Hay que pasarle dos datos a la función: el número de pin y una
indicación de si es una entrada o una salida. En nuestro caso:
pinMode(13, OUTPUT);
Estamos configurando el pin 3 como salida "OUTPUT". Normalmente esto debe hacerse
durante setup() y dejar el pin configurado para el resto del funcionamiento normal.
digitalWrite()
Esta función también es utilizada por el programador para especificar una acción a
realizar. La tarea de ella es cambiar el estado de una salida, de ahí, que se llame "Write". Y
la palabra "digital" indica que se trata de una salida digital, que puede tomar un valor de 0 o
1, verdadero o falso, si o no, alto o bajo, 0 voltios o 5 voltios…. como quieras entenderlo.
Esta función debe saber el número de pin que se va a cambiar y el valor a establecer,
Los pines son números y los valores posibles: "HIGH" o "LOW".
Ejercicio
Vamos a modificar el ejemplo anterior, haciendo que el parpadeo sea cada vez más lento.
Solución:
Algunas cosas deben cambiarse:
● No se puede hacer un delay fijo, de otra forma nada cambiará y todo seguirá igual
○ Por ello, h
ay que poner una variable y usarla en el delay
○ La variable hay que inicializarla obligatoriamente antes de usarla
● Hay que incrementar la variable cada vez
○ No hay que hacer un while… El "loop" ya es un while
○ En este momento tenemos lo siguiente:
void loop()
{
int retraso;
retraso = 10;
digitalWrite(13, HIGH);
delay(100+ retraso);
digitalWrite(13, LOW);
delay(100 + retraso );
}
La líneas
1 int retraso;
2 retraso = 10;
son :
1. la declaración de una variable llamada "retraso" que es de tipo "número entero" (se
indica con "int")
2. a asignación de un valor concreto a la variable (en este caso 100)
En la línea
delay(100+ retraso);
Se indica a arduino que debe dejar todo quieto durante un tiempo. Ese tiempo está
especificado entre paréntesis, y en esa instrucción aparece una suma. Por tanto el tiempo a
a esperar puede no ser siempre el mismo, cuanto más valga la variable "retraso" , más
tiempo estará todo detenido…. En principio pinta bien
Lo que se consigue es aumentar en 10 el valor de la variable retraso, y como esa variable se
usa para establecer el retraso, ocurrirá que cada vez habrá más retraso
Depuración. Serial.println()
En el desarrollo anterior el programa funciona mal. El Led parpadea siempre con la misma
frecuencia. Tenemos una variable que usamos para indicar el retardo pero parece no
funcionar. Necesitamos saber mejor qué está pasando en el programa, m ientras el programa
está en marcha.
void setup()
{
pinMode(13, OUTPUT);
Serial.begin(9600);
}
void loop()
{
int retraso;
retraso = 10;
digitalWrite(13, HIGH);
delay(100+ retraso); // Wait for 1000 millisecond(s)
digitalWrite(13, LOW);
delay(100 + retraso ); // Wait for 1000 millisecond(s)
Para realizar la simulación y ver el resultado, hay que activar el botón de "Serial Monitor" en
la parte inferior de la ventana de código.
int retraso;
void setup()
{
pinMode(13, OUTPUT);
Serial.begin(9600);
retraso = 10;
void loop()
{
digitalWrite(13, HIGH);
delay(100+ retraso); // Wait for 1000 millisecond(s)
digitalWrite(13, LOW);
delay(100 + retraso ); // Wait for 1000 millisecond(s)
Serial.println(retraso,DEC);
}
En Arduino el botón debe estar conectado a un pin de entrada que va a leer 0 o 5 voltios
dependiendo de si está pulsado el botón. Hemos de hacer un pequeño montaje y circuito
para alcanzar este objetivo. Observa el montaje a realizar:
Observa que el botón está conectado por una línea roja a la alimentación de 5 Voltios y por
una línea negra a masa (ground). Si quitásemos la resistencia que aparece en la línea negra,
al pulsar el botón ocurriría un cortocircuito. Esa resistencia limita la corriente cuando el
botón se pulsa.
Por otra parte, cuando el botón está pulsado, la línea verde -de entrada- está
conectado a la línea roja que está a 5 voltios. Por lo que en el pin 7 de entrada se lee un
HIGH, 1 o 5 Voltios. Sin embargo, cuando el botón está sin pulsar, la línea negra está a
0Voltios y ello se transmite a la línea verde por lo que en el pin 7 se leen 0 Voltios o LOW
void setup()
{
pinMode(13, OUTPUT);
pinMode(7, INPUT);
Serial.begin(9600);
retraso = 0;
}
La lectura de datos se realiza mediante una función llamada "digitalRead". Ésta debe saber
el pin del que se desea leer, por ello se le indica -como argumento- el número del pin. La
función al ejecutarse obtiene un valor que puede ser 1 o 0, HIGH o LOW. El valor debe
almacenarse en algún lugar, para lo cual necesitamos otra variable
void loop()
{
...
int botonPulsado;
botonPulsado = digitalRead(13);
...
}
El dato leído ya puede ser analizado en el programa para determinar si hay que reinicializar
el valor del retardo.
void loop()
{
int botonPulsado;
botonPulsado = digitalRead(13);
Los ascensores disponen de unos sensores que se activan cuando el cajón del
ascensor llega a una planta. En nuestro montaje estos sensores serán también botones.
Pulsar un botón de estos, equivaldrá a indicar que el ascensor ya ha llegado a una planta
La misión de la programación del arduino es decidir si el motor gira para levantar el
ascensor o para hacerlo descender. En vez de poner un motor y rotarlo en una y otra
dirección, vamos a colocar dos leds para indicar el sentido de giro del motor y facilitarnos la
visualización del prototipo. El circuito es el siguiente
Y hago la inicialización!
void setup()
{
pinMode(pinBoton1,INPUT);
pinMode(pinBoton2,INPUT);
pinMode(pinBoton3,INPUT);
pinMode(pinSensor1,INPUT);
pinMode(pinSensor2,INPUT);
pinMode(pinSensor3,INPUT);
pinMode(pinLedSubiendo,OUTPUT);
pinMode(pinLedBajando,OUTPUT);
Serial.begin(9600);
}
Cuando se pulse el botón de la planta dos, el ascensor deberá empezar a subir. El botón de
llamar al ascensor, no estará pulsado todo el tiempo mientras el ascensor se mueve. Por eso
se llama "llamar al ascensor", el botón se pulsa una vez mediante una pulsación corta y el
ascensor se mueve durante un tiempo hasta llegar a la planta.
Los ascensores reales tienen unos sensores que indican que el cajón del ascensor ha
llegado a la planta. Cuando así ocurre y el sensor se activa, el control del ascensor detiene
inmediatamente el motor. En nuestro programa, nosotros hemos de reproducir esta
situación.
En este problema, el movimiento del ascensor no depende de los datos leídos de las
entradas, sino del estado en el que se encuentra el ascensor. Es decir, si el ascensor está
subiendo, da igual que los botones estén pulsados o no, el motor debe seguir tirando el
ascensor hacia arriba. Esa idea de que "el ascensor está subiendo" hay que programarla.
Podemos pensar que "el ascensor -mientras intenta alcanzar el piso2 estará subiendo hasta
que se active el sensor de llegada al piso 2".
Para entender esto inicialmente, vamos a mantenernos en el escenario del ejemplo, en el
cual, podemos ver tres situaciones o estados:
Estas tres situaciones posibles reflejan tres estados que podemos dibujar de la siguiente
manera
Las flechas indican las transiciones o cambios de estado y marcan las posibilidades
existentes. Así, es posible pasar de estar en reposo en el piso 1 a estar subiendo. Pero no es
posible pasar de estar en el piso 1 a estar en el piso 2.
(normalmente hay que añadir un estado intermedio para controlar el tiempo en el
que el boton1 está pulsado, pero en este ejercicio podemos seguir sin prestarle
atención a este hecho y la solución es casi igualmente válida)
Implementación de estados
En la programación, necesitamos primero que nada indicar qué estados posibles existen.
Hay varias formas de hacer esto (por ejemplo asignar un número o código numérico a cada
estado "1": en piso1, "2": subiendo a piso 2, "3": en piso 2, etc). Nosotros vamos a utilizar
una característica del lenguaje C que simplificará muchísimo la comprensión posterior del
programa. Utilizaremos "enum" para declarar tipos de datos que pueden contener ciertos
valores indicados libremente. Observa la declaración del enum siguiente
La línea anterior define un tipo de dato llamado "estado" que puede tener sólo los valores
"enPiso1", "subiendoA2" y "enPiso2". Ahora, es posible declarar variables con ese tipo de
datos. A continuación se declara una variable llamada "estadoActual" cuyo contenido sólo
pueden ser los valores anteriores
estado estadoActual;
Por ejemplo, podemos inicializar la variable "estado" en la función setup() para indicar que
inicialmente se está en el piso 1 de la siguiente manera:
Modificamos la función setup con esta instrucción para inicializar el Ascensor (suponemos
por comodidad que está en la planta 1 al principio)
void setup()
{
...
...
}
Vamos a preparar el terreno para poder ver qué hace el ascensor en cada momento. En la
función loop añadimos la comunicación serie con el simulador que nos permitirá ver el
estado del ascensor. Aquí volvemos a ver las ventajas de utilizar enum como forma de
codificar los estados del ascensor. Observa cómo se utiliza un switch para comparar el valor
de la variable "estadoActual" con los posibles valores asignables:
void loop()
{
Serial.println("");
delay(100);
}
Cambios de estado
La programación por estados consiste básicamente en determinar dos cosas:
Estos cambios se programan estado por estado de forma independiente. Y siempre se
realiza en dos fases.
1. Leemos los datos de entrada que son relevantes para un estado concreto (por
ejemplo, si estamos en el estado "subiendoA2" sólo nos interesa saber si el sensor
de llegada al piso 2 está activo o no. Porque ese estado sólo se cambia cuando se
llega a ese piso, no importa si se pulsa mientras otro botón.
2. Verificamos que se está en cierto estado y que los datos de entrada indican que
debemos cambiar
Para empezar, Vamos a controlar la subida del primer piso, -que es donde nos encontramos
al principio- al segundo piso
Ya está. Hemos implementado el cambio de estado para el estado "enPiso1". Seguimos con
el resto de estados
Esta parte se programa al final, después de todos los cambios de estado. La programación
suele ser muy sencilla:
Para seguir, reproducimos lo razonado para estos dos pisos en el otro piso y en los sentidos
de bajada:
El código:
digitalWrite(pinLedSubiendo,0);
digitalWrite(pinLedBajando,0);