¿QUÉ ES ARDUINO? Arduino es en realidad realidad tres cosas:
Una placa hardware libre que incorpora un microcontrolador reprogramable y una serie de pines-hembra que permiten conectar allí de forma muy sencilla diferentes sensores y actuadores.
Un software (entorno de desarrollo) gratis, libre y multiplataforma, que nos permite escribir, verificar ve rificar y guardar (“cargar”) en la memoria del microcontrolador el conjunto de instrucciones que deseamos que este empiece a ejecutar.
Un lenguaje de programación libre. Por “lenguaje de programación” se entiende cualquier idioma artificial diseñado para expresar instrucciones (siguiendo unas determinadas reglas sintácticas) que pueden ser llevadas a cabo por máquinas.
CARACTERÍSTICAS DEL MICRO DE LA PLACA ARDUINO UNO
El encapsulado físico del microcontrolador incorporado: puede ser en formato DIP (“Dual InIn line Package”) y en formato SMD (“Surface Mount Device”).
1
El modelo del microcontrolador. El microcontrolador que lleva la placa Arduino UNO es el modelo ATmega328P de la marca Atmel. La “P” del final significa “Picopower”, la cual permite un consumo eléctrico sensiblemente menor comparándolo con un modelo equivalente. El ATmega328P tiene una arquitectura de tipo AVR. La figura siguiente muestra esta disposición en el encapsulado de tipo DIP.
LAS MEMORIAS DEL MICROCONTROLADOR En el caso del ATmega328P tenemos: -
Memoria Flash Memoria permanente donde se almacena el programa que ejecuta el microcontrolador (hasta una nueva reescritura si se da el caso). En el caso del ATmega328P tiene una capacidad de 32KB. En los microcontroladores de la placa Arduino no se usa toda la capacidad de la memoria Flash porque existen 512 bytes ( “bootloader block”) ocupados por un código preprogramado de fábrica (el llamado “bootloader” o “gestor de arranque”), el cual nos permite usar la placa Arduino de una forma sencilla y cómoda.
-
Memoria SRAM Memoria volátil donde se alojan los datos que en ese instante el programa necesita crear o manipular para su correcto funcionamiento. Independientemente del tipo de dato, su valor siempre será eliminado cuando se deje de alimentar eléctricamente al microcontrolador. En el caso del ATmega328P esta memoria tiene una capacidad de 2KB.
2
-
Memoria EEPROM Memoria permanente donde se almacenan datos que se desea que permanezcan grabados una vez apagado el microcontrolador para poderlos usar posteriormente en siguientes reinicios. En el caso del ATmega328P esta memoria tiene una capacidad de 1 KB.
LOS REGISTROS DEL MICROCONTROLADOR. Los registros son espacios de memoria existentes dentro de la propia CPU de un microcontrolador. Sirven para albergar los datos (cargados previamente desde la memoria SRAM o EEPROM) necesarios para la ejecución de las instrucciones; sirven también para almacenar temporalmente los resultados de las instrucciones recientemente ejecutadas y sirven además para alojar las propias instrucciones que en ese mismo momento estén ejecutándose. El chip ATmega328P es de 8 bits.
LOS PROTOCOLOS DE COMUNICACIÓN I2C/TWI Y SPI. Como ya vimos, la transmisión de un conjunto de datos desde un componente electrónico a otro, puede ser:
Comunicación “serie”; en este tipo de comunicación la información es transmitida bit a bit (uno tras otro) por un único canal, enviando por tanto un solo bit en cada momento. Comunicación “paralela”, en la cual se envían varios bits simultáneamente, cada uno por un canal separado y sincronizado con el resto.
El microcontrolador, a través de algunos de sus pines de E/S, utiliza el sistema de comunicación serie para transmitir y recibir órdenes y datos hacia/desde otros componentes electrónicos. Los estándares más importantes, para este tipo de comunicación son:
I2C (Inter-Integrated Circuit, o - TWI “Two-WIre”, “dos cables”). Su principal característica es que utiliza dos líneas para transmitir la información: una sirve para transferir los datos (SDA) y otra que sirve para enviar la señal de reloj ( SCL). También se necesitan dos líneas más: la de alimentación y la de tierra. Señal de reloj (CLK): señal binaria de una frecuencia periódica que sirve para coordinar y sincronizar los elementos integrantes de una comunicación (emisores y receptores) de forma que todos sepan cuándo empieza, cuánto dura y cuándo acaba la transferencia de información. Cada dispositivo conectado al bus I²C tiene una dirección única que lo identifica uno del otro, y puede estar configurado como “maestro o esclavo”. Un dispositivo maestro es el que inicia la transmisión de datos y genera la señal de reloj (no necesariamente es así).
3
Para funcionar correctamente “SDA” y “SCL” necesitan estar conectad as mediante una resistencia “pull-up” a la fuente de alimentación común. SPI (Serial Peripheral Interface): Permite controlar (a cortas distancias) casi cualquier dispositivo electrónico digital que acepte un flujo de bits serie sincronizado (regulado por un reloj). Un dispositivo conectado al bus SPI puede ser “maestro” o “esclavo”, donde el primero es el que inicia la transmisión de datos y genera la señal de reloj (no siempre es así) y el segundo se limita a responder. Requiere de cuatro líneas. Una línea envía a todos los dispositivos la señal de reloj generada por el maestro ( SCLK); otra es la utilizada por el maestro para elegir con qué dispositivo esclavo se quiere comunicar; ya que solo puede transferir datos con un solo esclavo a la vez ( SS); otra es la línea utilizada para enviar los datos (0s y 1s) desde el maestro hacia el esclavo elegido ( MOSI); y la otra es la utilizada para enviar la respuesta del esclavo al maestro ( MISO). La transmisión de información es “full duplex”, es decir, que la información puede ser transportada en ambos sentidos a la vez.
4
Para el caso de la existencia de varios esclavos es necesario utilizar una línea “SS” diferente por cada uno de ellos, ya que esta línea es la que sirve para activar el esclavo concreto que en cada momento el maestro desee utilizar (el esclavo que reciba por su línea SS un valor de voltaje BAJO será el que esté seleccionado en ese momento por el maestro, y los que reciban el valor ALTO no lo estarán).
LA ALIMENTACION. El voltaje de funcionamiento de la placa Arduino es de 5 V y podemos obtener esta alimentación de varias maneras: a) Conectando la placa Arduino a una fuente externa: Para el primer caso, la placa dispone de un zócalo donde se puede enchufar una clavija de 2.1 mm de tipo “jack”. Para el segundo, los cables salientes de los bornes de la pila se pueden conectar a los pines-hembra marcados como “Vin” y “Gnd”. En ambos casos, la placa está preparada en teoría para recibir una alimentación de 6 a 12 V. b) Conectando la placa Arduino a nuestro computador mediante un cable USB. La alimentación recibida de esta manera es de 5 V y ofrece un máximo de hasta 500 mA. ZONA ETIQUETADA “POWER”.
”GND”: pines-hembra conectados a tierra. ”Vin”: este pin-hembra se puede utilizar para dos cosas diferentes: 1. Si la placa está conectada mediante el jack, podemos conectar a este pin-hembra cualquier componente electrónico para alimentarlo directamente con el nivel de voltaje que esté aportando la fuente en ese momento. Si la placa está alimentada mediante USB, entonces ese pin-hembra aportará 5 V. 2. También podemos usar este pin para alimentar la propia placa directamente desde alguna fuente de alimentación externa sin utilizar el jack o el cable USB. Esto se hace conectándole el borne positivo de la fuente y conectando el borne negativo al pin de tierra. Si se usa este montaje, el regulador de tensión que incorpora la placa reducirá el voltaje recibido al voltaje de trabajo de la placa (5 V).
5
”5 V”: Si la placa está alimentada mediante el cable USB o si está alimentada por una fuente externa, podemos conectar a este pin cualquier componente que pueda recibir 5 V, con una corriente máxima de 40 mA. Pero también podemos usar este pin para alimentar la propia placa desde una fuente de alimentación externa previamente regulada a 5 V. ”3,3 V”: Este pin ofrece un voltaje de 3.3 V. El cual se obtiene a través del cable USB o del jack por un circuito específico incorporado en la placa: el LP2985. Con una corriente máxima de 50 mA. Al igual que con los pines anteriores, podremos usar este pin para alimentar componentes.
SEÑALES DIGITALES. Una señal digital es aquella que solo tiene un número finito de valores posibles ( “valores discretos”). Un ejemplo es la señal binaria, donde el número de valores posibles solo es 2. El valor 0 o BAJO indica la ausencia de voltaje; el valor 1 o ALTO El valor de voltaje concreto que se corresponda con el estado ALTO o 1 será diferente según los dispositivos electrónicos utilizados en cada momento. Además de los niveles ALTO y BAJO, en una señal binaria existen las transiciones entre estos niveles (de ALTO a BAJO y de BAJO a ALTO), denominadas flanco de bajada y de subida, respectivamente.
ENTRADAS DIGITALES. El Arduino UNO dispone de 14 pines de entradas o salidas digitales, numeradas desde la 0 hasta la 13. Todos estos pines funcionan a 5 V, pueden proveer o recibir un máximo de 40m A, disponen de una resistencia “pull-up” interna de entre 20 K Ω y 50 K Ω que inicialmente está desconectada.
6
LAS RESISTENCIAS “PULL -UP” Y “PULL-DOWN”.
Son resistencias normales, que sirven para asumir un valor definido de la señal recibida en la entrada del circuito, cuando por ella no está conectada. En las resistencias “pull -up” el valor que se asume en la entrada es ALTO y en las “pulldown” es el valor BAJO. La diferencia entre unas y otras está en su ubicación dentro del circuito: las resistencias “pull -up” se conectan directamente a la fuente de señal externa y las “pull-down” directamente a tierra.
pull-down
pull-up
ENTRADAS ANALÓGICAS. Arduino UNO dispone de 6 entradas analógicas (desde “A0” hasta “A5”) que pueden recibir voltajes dentro de un rango de valores continuos de entre 0 y 5 V. Cada entrada cuenta con un convertidor análogo-digital, y cada uno de ellos disponen de 10 bits (bits de resolución) para guardar el valor del voltaje convertido digitalmente. La cantidad de bits de resolución, determina el grado de precisión. Por ejemplo, en el caso del convertidor incorporado en la placa Arduino, si contamos el número de combinaciones de 0s y 1s que se pueden obtener con 10 posiciones, vemos que hay un máximo de 2 10= 1024 valores diferentes posibles. Por ejemplo si tenemos un rango de 5V y lo dividimos entre 1024 valores disponibles, tendremos que cada valor digital corresponde aproximadamente 5mV.
SALIDAS ANALÓGICAS (PWM). Arduino no dispone de pines de salida analógica propiamente dichos, sino que utiliza algunos pines digitales para “simular” un comportamiento analógico. Los pines digitales que son capaces trabajar en este modo son los marcados con la etiqueta “PWM”. Para el modelo Arduino UNO son los pines número: 3, 5, 6, 9, 10 y 11.
7
Las siglas PWM vienen de “Pulse Width Modulation” (Modulación de Ancho de Pulso). Lo que hace este tipo de señal es emitir una señal cuadrada formada por pulsos de frecuencia constante (490 Hz aprox.). La gracia está en que al variar la duración de estos pulsos, estaremos variando proporcionalmente el voltaje promedio resultante. Es decir: cuanto más cortos sean los pulsos y más distantes entre sí en el tiempo, menor será el voltaje promedio de salida, y cuanto más anchos sean los pulsos y por lo tanto más juntos en el tiempo estén, mayor será dicho voltaje.
Cada pin PWM tiene una resolución de 8 bits. Esto quiere decir que se pueden obtener un máximo de 2 8 = 256 valores diferentes posibles. La diferencia de voltaje analógico existente entre dos valores promedio contiguos (por ejemplo el valor número 123 y el 124) se puede calcular mediante la división: rango_voltaje_salida/número_valores_promedio . En nuestro caso, sería (5 V – 0 V)/256 ≈19,5
mV. Es decir, cada valor promedio está distanciado 19,5 mV.
8
OTROS USOS DE LOS PINES. Pin 0 (RX) y 1 (TX): posibilitan la comunicación sin intermediarios de dispositivos externos con el receptor / transmisor serie que incorpora el microcontrolador.
Pines 2 y 3: se pueden usar, con la ayuda de programación software, para gestionar interrupciones.
Pines 10 (SS), 11 (MOSI), 12 (MISO) y 13 (SCK): se pueden usar para conectar algún dispositivo con el que se quiera llevar a cabo comunicaciones mediante el protocolo SPI.
Pin 13: este pin está conectado directamente a un LED incrustado en la placa. Pines A4 (SDA) y A5 (SCL): se pueden usar para conectar algún dispositivo con el que se quiera llevar a cabo comunicaciones mediante el protocolo I 2C/TWI.
Pin AREF: ofrece un voltaje de referencia externo para poder aumentar la precisión de las entradas analógicas.
Pin RESET: si el voltaje de este pin se establece a valor BAJO (LOW), el microcontrolador se reiniciará y se pondrá en marcha el bootloader.
Pin IOREF: es una duplicación regulada del pin “Vin”. Su función es indicar a las placas supletorias, el voltaje al que trabajan los pines de entrada/salida de la placa arduino, y que éstas se adapten a ese voltaje de trabajo.
SOFTWARE ARDUINO
¿QUÉ ES UN IDE? Un programa (“sketch” en el mundo de Arduino) es un conjunto concreto de instrucciones, ordenadas y agrupadas de forma adecuada y sin ambigüedades que pretende obtener un resultado determinado. Las siglas IDE vienen de Integrated Development Environment, lo que traducido significa Entorno de Desarrollo Integrado. Arduino utiliza el lenguaje de programación C, aunque eliminando parte de su complejidad. C es un lenguaje fácil de aprender, que se compila en un eficiente "código máquina" y que requiere poco espacio en la memoria. El entorno de desarrollo Arduino, utiliza algo llamado un compilador, el cual convierte la secuencia de comandos en código máquina, que será el que se ejecutará en el microcontrolador.
9
Estructura Básica de los Programas Escritos en Arduino.
Descripción del programa: 1. Líneas de Comentarios. Inician con /*, y terminan con */. Se usan para dar una explicación general del programa. 2. Comentarios en una sola línea. Si se coloca // en cualquier línea, el compilador ignora el texto después de estos símbolos en la misma línea. 3. Declaración de Variables. Una Variable es un lugar en la memoria del Arduino, que guarda información.
10
4. Función void setup() {….}. Una Función es una parte del código que hace una tarea específica. El código dentro de las llaves de la función setup(), es ejecutado una vez al iniciar el programa, por ejemplo: direccionar puertos, establecer las interfaces de comunicación, etc. 5. Los pines digitales de Arduino pueden funcionar como entradas o salidas. Para configurarlos usamos el comando pinMode(). Este comando tiene 2 argumentos. El 1er argumento de pinMode, determina sobre cual pin se va a direccionar. El 2do argumento establece la dirección del pin como INPUT o OUTPUT. Un Argumento da información de las instrucciones sobre cómo éstas deben operar. 6. Función void loop() {….}. Esta función se repite continuamente siempre que el Arduino este encendido. 7. (9) digitalWrite().Es usada para establecer el estado de una salida. El 1er argumento de esta instrucción es el pin que se quiere controlar. El 2do argumento es el valor a establecer sobre el pin, HIGH (5v) o LOW (0v). 8. (10) Función delay(). Retardo de tiempo en milisgundos. Con esta instrucción Arduino se detiene de hacer cualquier proceso según el tiempo especificado
Declaración e inicialización de una variable. La sintaxis general de una declaración es siempre una línea escrita así: tipoVariable nombreVariable;. También es posible declarar todas en una misma línea genéricamente, así: tipoVariable nombreVariable1, nombreVariable2; . A la vez que se declara la variable, se le puede establecer un valor inicial: a esto se le llama “inicializar una variable”. La sintaxis general de una inicialización es siempre una línea escrita así: tipoVariable nombreVariable = valorInicialVariable; .
Ámbito de una Variable. Una variable global, es aquella que puede ser utilizada y manipulada desde cualquier punto del sketch. Se declaran al principio de nuestro sketch; es decir, antes de las secciones “void setup()” y “void loop()”. Una variable local, es aquella que solo puede ser utilizada y manipulada por las instrucciones escritas dentro de la misma sección donde se ha declarado. Se declara en el interior de alguna de las secciones de nuestro sketch (dentro de “void setup()” o de “void loop()” o de otras que puedan existir).
11
Tipos de Variables. Tipo boolean char
Memoria (byte) 1 1
Rango TRUE o FALSE (1 o 0) -128 a +128
Notas
Se utiliza para representar un código de carácter ASCII ( “ A” se representa como 65). Normalmente, sus números negativos no se utilizan.
byte int unsigned int
1 2 2
0 a 255 -32,768 a + 32,768 0 a 65,536
long
4
-2,147,483,648 a +2,147,483,647
unsigned long float
4 4
doublé
4
0 a 4,294,967,295 -3.4028235E+38 a + 3.4028235E+38 igual que float
Se pueden utilizar para disponer de precisión extra, cuando no se necesitan números negativos. Deben utilizarse con cuidado ya que las operaciones aritméticas con ints pueden producir resultados inesperados. Sólo se necesitan para representar números muy grandes. Ver “unsigned int”.
Normalmente, esto serían 8 bytes y mayor precisión que los valores “float”, con un rango superior. Sin embargo, en Arduino son iguales a “float”.
12
BLOQUES CONDICIONALES. Los bloques “if” y “if/else”. Un bloque “if” sirve para comprobar si una condición determinada es cierta (”true”,1) o falsa (”false”,0). Si la condición es cierta, se ejecutarán las instrucciones escritas en su interior (dentro de las llaves de apertura y cierre). Si no se cumple, puede no pasar nada, o bien, si existe tras el bloque “if” un bloque “else” (opcional), se ejecutarán las instrucciones escritas en el interior de ese bloque “else”.
La sintaxis del bloque “if/else” es: if (condición) { // Instrucciones –una o más – que se ejecutan si la condición es cierta –”true”,1– } else { // Instrucciones –una o más – que se ejecutan si la condición es falsa –”false”,0– }
El bloque “else” es opcional. Si no lo escribimos, el “if” quedaría así: if (condición) { //Instrucciones –una o más – que se ejecutan si la condición es cierta –”true”,1– }
También existe la posibilidad de incluir una o varias secciones “else if”, siendo en este caso también opcional el bloque “else” final. Esta construcción tendría la siguiente sintaxis (puede haber todos los “else if” que se deseen): if (condición) { // Instrucciones –una o más – que se ejecutan si la condición es cierta } else if (otra_condición) { /* Instrucciones –una o más – que se ejecutan si la condición del anterior “if” es falsa pero la actual es cierta */ } else if (otra_condición) { /*Instrucciones –una o más – que se ejecutan si la condición del anterior “if” es falsa pero la actual es cierta */ } else { //Instrucción(es) que se ejecutan si todas las condiciones anteriores eran falsas }
13
Para escribir correctamente las condiciones, necesitamos utilizar los operadores de comparación: ==
Comparación de igualdad
!=
Comparación de diferencia
>
Comparación de mayor que
>=
Comparación de mayor o igual que
<
Comparación de menor que
<=
Comparación de menor o igual que
Además de los operadores de comparación, también se pueden utilizar los operadores booleanos (también llamados lógicos), usados para encadenar dos o más comprobaciones dentro de una condición. o o o
&& || !
Comprueba que las dos condiciones sean ciertas (Operador AND) Comprueba que, al menos, una de dos condiciones sea cierta (Operador OR) Comprueba que no se cumpla la condición a la que precede (Operador NOT)
El lenguaje Arduino también dispone de operadores aritméticos, que son: o o o o o
+ * / %
Operador suma Operador resta Operador multiplicación Operador división Operador módulo
BLOQUES REPETITIVOS (BUCLES) El bloque “while”
Es un bloque que i repite la ejecución de las instrucciones que están dentro de sus llaves de apertura y cierre. ¿Cuántas veces? No hay un número fijo: se repetirán mientras la condición especificada entre sus paréntesis sea cierta (“true”,1). Su sintaxis es muy sencilla: while (condición) { //Instrucciones que se repetirán mientras la condición sea cierta –”true”,1– }
14
El bloque “do”
El bloque “do” tiene la siguiente sintaxis: do { //Instrucciones que se repetirán mientras la condición sea cierta –”true”,1– } while (condición)
El bucle “do” funciona igual que el bucle “while”, con la excepción de que la condición es evaluada después de ejecutar las instrucciones escritas dentro de las llaves. El bloque “for”
La diferencia entre un bucle “while” (o “do”) y un bucle “for” está en que en el primero el número de iteraciones realizadas depende del estado de la condición definida, pero en un bucle “for” el número de iteraciones se puede fijar a un valor exacto. Por tanto, se usará esta instrucción para ejecutar un conjunto de instrucciones un número concreto de veces. La sintaxis general del bucle “for” es la siguiente: for (valor_inicial_contador;condicion_final;incremento){ //Instrucciones que se repetirán un número determinado de veces }
Tal como se observa, entre paréntesis se deben escribir tres partes diferentes, separadas por puntos y coma. Estas tres partes son opcionales (pueden omitirse cualquiera de ellas) y son las siguientes: -
-
-
Valor inicial del contador: Se asigna el valor inicial de una variable entera que se utilizará como contador en las iteraciones del bucle. Por ejemplo, si allí escribimos x=0 , se fijará la variable “x” a cero al inicio del bucle. A partir de entonces, a cada repetición del bucle, esta variable “x” irá aumentando (o disminuyendo) progresivamente de valor. Condición final del bucle: Se especifica una condición. Antes de cada iteración se comprueba que sea cierta para pasar a ejecutar el grupo de sentencias internas. Si la condición se evalúa como falsa, se finaliza el bucle “for”, continuando el programa tras su llave de cierre. Por ejemplo, si allí escribimos x<10 , el grupo interior de sentencias se ejecutará únicamente cuando la variable “x” valga menos de 10. Incremento del contador : Se indica el cambio de valor que sufrirá al inicio de cada iteración del bucle la variable usada como contador. Por ejemplo, la sentencia x=x+1, es un contador que aumenta de uno en uno a cada repetición. Este cambio se efectúa antes de comprobar la condición de final del bucle.
15
Para facilitar la escritura del código, de una manera compacta y rápida se hace uso de operadores compuestos: x++
Equivale a x=x+1 (Al operador “++” se le llama operador “incremento”)
x- -
Equivale a x=x-1 (Al operador “--“ se le llama operador “decremento”)
x+=3
Equivale a x=x+3
x-=3
Equivale a x=x-3
x*=3
Equivale a x=x*3
x/=3
Equivale a x=x/3
LA COMUNICACIÓN SERIE CON LA PLACA ARDUINO En el lenguaje de Arduino para que la placa pueda comunicarse con otros dispositivos, para así poder transferir datos entre ambos, se hace uso de l a instrucción “Serial”, la cual a través de nuestro sketch hacemos uso de un conjunto de instrucciones disponibles para manipular la comunicación serial. La sintaxis de la función “Serial”: -
-
-
Serial.begin(): abre el canal serie para que pueda empezar la comunicación por él. Se suele escribir dentro de la sección “void setup()”. Además, mediante su único parámetro se especifica la velocidad en bits/s a la que se producirá la transferencia serie de los datos. Serial.print(): envía a través del canal serie un dato (de cualquier tipo) desde el microcontrolador hacia el exterior. Los caracteres se han de escribir entre comillas simples y las cadenas entre comillas dobles. Serial.println(): hace exactamente lo mismo que Serial.print(), pero al final de la ejecución de Serial.println() se efectúa un salto de línea. Serial.available(): devuelve el número de bytes –caracteres – disponibles para ser leídos que provienen del exterior a través del canal serie (vía USB o vía pines TX/RX). Serial.parseInt(): lee del buffer de entrada (eliminándolos de allí) todos los datos hasta que se encuentre con un número entero.
El “Serial monitor” es una ventana del IDE que nos permite desde nuestra computadora enviar y recibir datos textuales a la placa Arduino usando el cable USB.
16
Ejemplo 1:
Ejemplo2:
Ejemplo 3:
17
Ejemplo 4:
Ejemplo 5:
Ejemplo 7:
18