Introducción a la Programación en C para Arduino: Hardware y Software

Enviado por Programa Chuletas y clasificado en Informática y Telecomunicaciones

Escrito el en español con un tamaño de 25,82 KB

Programación en C para Arduino

1. Introducción

Arduino es una plataforma de hardware libre, basada en una placa electrónica que tiene un microcontrolador (µC) y un entorno de desarrollo integrado (IDE), diseñada para ser utilizada en proyectos multidisciplinares. Su programación se basa en el lenguaje C/C++. A pesar de que no es un requisito, es conveniente que la persona que quiera programar una placa Arduino sepa lo básico de programación en los lenguajes mencionados.

Existen variados modelos de placas, las cuales se pueden revisar en el sitio web de Arduino. Además, en el mercado, hay diversas empresas que fabrican placas totalmente compatibles con Arduino. La Escuela de Ingeniería Civil Informática dispone de placas Sparkfun, que son compatibles con el modelo Arduino UNO. La ventaja de este es que se entrega en formato de kit de desarrollo, el que tiene todo lo necesario para realizar las tareas en las asignaturas que se ocupe, como por ejemplo, cables, motores, protoboard, luces LED, sensores, etc.

El objetivo de este material es que quien lo lea, esté capacitado para programar un sistema con Arduino y entender el funcionamiento básico de algunos sensores que dispone dicho microcontrolador.

2. Descripción del hardware

Las placas Sparkfun, que son las que la Escuela dispone, están basadas en el chip ATmega328, que es el mismo µC que utiliza el modelo Arduino UNO. Tiene 14 pines de entrada/salida (E/S) digitales, de los cuales 6 pueden simular salidas análogas mediante la técnica PWM y 6 entradas análogas. Funciona a una velocidad de 16 [MHZ] y tiene 32 [KB] de memoria flash y 2 [KB] de SRAM. La Figura 1 muestra un diagrama de la placa.

- Alimentación

La placa se puede energizar a través del conector USB o con una fuente externa entre 7 [V] y 15 [V]. Normalmente, se puede utilizar una batería de 9 [V]. El conector externo, en el último caso, debe ser de 2,1 [mm], con centro positivo.

- Entradas y salidas

Cada uno de los 14 pines digitales (numerados del 0 al 13) pueden utilizarse como entradas o como salidas usando las funciones pinMode(), digitalWrite() y digitalRead(). Las E/S operan a 5 [V]. Cada pin puede proporcionar o recibir una corriente máxima de 40 [mA].

Los pines 3, 5, 6, 9, 10, y 11 proporcionan una salida PWM (modulación por ancho de pulsos) de 8 bits de resolución (valores de 0 a 255) mediante la función analogWrite().

El pin digital 13 lleva conectado un LED integrado en la propia placa. Se encenderá cuando dicho pin se configure como salida y adopte un valor HIGH; con valor LOW se apaga.

La placa tiene 6 entradas analógicas, y cada una de ellas proporciona una resolución de 10 bits (1024 valores).

- Comunicaciones

La placa proporciona comunicación serial a través de los pines digitales 0 y 1, utilizados para la recepción (RX) y transmisión (TX) de datos. Un chip integrado en la placa analiza esta comunicación serie, además, a través del puerto USB. El software de Arduino incluye un monitor de puerto serie, que permite enviar y recibir información textual hacia y desde la placa Arduino. Los LEDs RX y TX de la placa parpadearán cuando se detecte comunicación transmitida a través de la conexión USB.

3. Preparando el escenario de trabajo

- Entorno de Desarrollo de Software

El entorno de desarrollo integrado (IDE) se puede bajar desde la página de Arduino y en la Figura 3 se pueden distinguir las partes que lo constituyen.

El área de edición de código es donde se escribirá el código del software que se requiere. Es sencillo visualmente y tiene ciertas características que usted debe descubrir mediante su uso. Normalmente, en la jerga de Arduino, aquí se crea el “sketch” (código fuente).

Una sección importante es el área de mensajes, en donde el compilador le informa posibles errores en el código. Además, en esta área, la placa Arduino puede enviar información acerca de su estado, según como se haya programado.

- Conexión de la placa al computador

Cada kit Sparkfun dispone de un cable USB para poder conectar la placa a un computador, tal como se muestra en la Figura 5.

Cuando conecte ambos elementos, el sistema operativo del computador le puede solicitar los drivers para poder acceder a la placa. Si el menú Herramientas à Puerto Serial no está habilitado (ver ejemplo en la Figura 4), debe seguir las instrucciones de la página https://learn.sparkfun.com/tutorials/how-to-install- ftdi-drivers.

- Protoboard

Una placa de pruebas (o protoboard) es una placa de uso genérico, que se utiliza para construir prototipos de circuitos electrónicos sin utilizar herramientas para soldar. En el caso de las placas Sparkfun, estas vienen con una, similar a la mostrada en la Figura 6. El diagrama de conexiones eléctricas se visualiza en la Figura 7.

4. Forma de programar Arduino

El código que se debe escribir en el IDE de Arduino debe tener cierta estructura, la que se indica en la Figura 8.

En la primera sección (Declaraciones Globales), se deben poner las bibliotecas específicas que se utilizarán (ninguna en el código de ejemplo) y las variables globales que se utilizarán (pinLed en este caso). Este bloque se ejecuta una sola vez y bajo cualquier de los siguientes eventos:

  • Encendido de la placa.
  • Después de un reset.
  • Después de cargar un programa desde el computador.

La función setup() se ejecuta después de la sección anterior y por una sola vez. Se utiliza para configurar el hardware que se utilizará. En el ejemplo, se inicializa el pin 10 como salida.

La función loop(), por otro lado, se ejecuta después de la función anterior, de forma “perpetua”, a una tasa de repetición muy cercana a la velocidad de trabajo de la placa, dependiendo de la cantidad de instrucciones que tenga.

5. Modalidad de trabajo

Arduino se creó para facilitar el prototipaje de ideas que mezclan software con componentes electrónicos, con el fin de crear soluciones que interactúen con el medio ambiente y con otros sistemas. En la Figura 10 se muestra un esquema que representa el trabajo que usted debe realizar para implementar sus ideas.

6. Primer prototipo con Arduino

- La idea inicial

A modo de ejemplo, supongamos que usted quiere realizar un sistema, basado con Arduino, que prenda y apague un LED cada 1 segundo.

- Diseño del hardware

En la sección 2.2 se menciona que Arduino dispone de cierta cantidad de salidas digitales, las que pueden estar en un nivel alto de voltaje (5 [V]) y un nivel bajo de voltaje (cero), según cómo estén programadas.

Luego, el LED debería estar conectado a una de dichas salidas.

El diagrama eléctrico podría ser el de la Figura 11. Bajo condiciones normales, el voltaje del LED es de 2 [V] y para que tenga una luminosidad aceptable, su corriente debe ser por lo menos 5 [mA]. Cuando el pin 10 está a 5 [V], el voltaje de la resistencia es de 3 [V]. Luego, su corriente es, según la Ley de Ohm, aproximadamente 9 [mA], corriente que es suficiente para que el LED se vea encendido.

En la Figura 12 y Figura 13 se muestra la equivalencia para el LED y la resistencia utilizada.

Luego que se tiene configurado el hardware que se va a utilizar, hay que diseñar la lógica de la solución. Hay diversas formas, pero como recomendación, siempre se debe determinar esta fase con un diagrama donde indique cómo va a funcionar el software. Típicamente, esto es un diagrama de flujo.

Tal como se ve en el diagrama de flujo, la solución se basa en un ciclo infinito de funcionamiento, el que se acomoda perfectamente con el modo de funcionamiento de la función loop().

Para escribir un dato digital (Nivel alto o bajo, un Verdadero o Falso), se ocupa la función digitalWrite() y para que el sistema espere durante cierta cantidad de tiempo, se ocupa la función delay(). El código de la función loop() se muestra en la Tabla 3.

7. Programación a nivel de registros

La placa Arduino, tiene tres puertos (B, C y D) según se resume en la Tabla 5.

Puerto

Pines

B

Digitales 8 al 13

C

Entradas Análogas

D

Digitales 0 al 7

Además, cada puerto es controlado por tres registros, los que están definidos como variables a nivel de programa (ver Tabla 6). Cada uno de estos registros es de 8 [bits]. En los puertos que tienen menos de 8 pines, como es el caso del puerto B, los bits más significativos, que no están asociados a pines físicos, no se toman en cuenta.

Registro

Descripción

DDR

Determina qué pines son entradas o salidas (valor 1 para salida, 0 para entrada)

PORT

Determina qué pines están en un nivel alto o bajo.

PIN

Entrega el estado de los pines del puerto (si es entrada o salida)

8. Especificación del lenguaje de programación

Arduino se programa en C, pero por tratarse de un µC, la cantidad de instrucciones es menor a las que se pueden utilizar en un computador de escritorio o portátil. Además, se tiene otras funciones que no existen en C estándar. En esta sección, se describen las funciones que son propias del lenguaje C de Arduino y que serán utilizadas por usted en el taller o asignatura que está cursando. El resto de las funciones clásicas de C, como por ejemplo, for(), while(), if(), etc., las puede estudiar en el sitio web de Arduino.

Las palabras reservadas del lenguaje se escriben, en este documento, con una fuente Courier New, en negrita. Por ejemplo, delay() es una palabra reservada. Si una palabra no está en negrita, pero con la fuente mencionada, se refiere a una variable o función que se utiliza en el código. Por ejemplo, pinLed se refiere a una variable utilizada en un código.

8.1 Constantes

8.1.1 Niveles Lógicos

false: se define como 0 (cero).

true: es cualquier número distinto que 0. Por comodidad, se asocia un valor 1 a este nivel.

8.1.2 Niveles de Voltaje

HIGH: Representa un voltaje de 5 [V] en una salida y un voltaje mayor que 3 [V] en una entrada.

LOW: Representa un voltaje de 0 [V] en una salida y un voltaje menor que 2 [V] en una entrada.

8.2 Tipos de datos

Tipo

Descripción

Ejemplo

void

Sólo en las declaraciones de funciones. Indica que no retorna un valor.

void setup() {


}

boolean

Variable que puede tener dos valores: true o false. También HIGH o LOW.

boolean ledON = false;

boolean OFF = LOW;

char

Almacena números enteros entre [-128,127]. Ocupa 1 [Byte] de memoria y almacena un valor de carácter.

char dato = 'A';

char dato = 65; // Es lo mismo

unsigned

char

Lo mismo que char, pero almacena números enteros de 8 bits. Rango entre [0,255].

unsigned char dato = 240;

byte

Lo mismo que unsigned char. Es preferible desde el punto de vista de la coherencia del código.

byte b = B10010;

int

Permite almacenar un número entero en el rango [-32768,32767]. Ocupa 2 [Bytes] de memoria.

int valorInt = 23456;

unsigned

int

Permite almacenar un número entero en el rango [0,65535]. Ocupa 2 [Bytes] de memoria.

unsigned int valor = 65432;

unsigned int valor = -1; // valor // es 65535

word

Lo mismo que unsigned int.

word valor = 65432;

word valor = -1; // valores 65535

long

Permite almacenar un número entero en el rango [-2147483648,2147483647]. Ocupa 4 [Bytes] de memoria.

long valor = 2345678L;

unsigned

long

Permite almacenar un número entero en el rango [0,4294967295]. Ocupa 4 [Bytes] de memoria.

unsigned long valor = 4294967295UL;

float

Permite almacenar un número en punto flotante (fraccionario) en el rango [-3.4•10^38,3.4•10^38]. Ocupa 4 [Bytes] de memoria.

float valorSensor = 4.7657;

double valorSensor = 4.7657; // precisión doble no existe // en Arduino. Queda como float

arrays

Los arreglos son una colección de variables a las que se accede a través de un número índice, que comienza en cero.

int pinPWM[] = {3, 5, 6, 9, 10, 11};

char mensaje[] = "El dato llegó";

8.8 Funciones de tiempo más utilizadas

8.8.1 Función millis()

Devuelve la cantidad de milisegundos transcurridos desde que la placa Arduino empezó a ejecutar el programa actual. Este número se desbordará (volverá a cero), después de aproximadamente 50 días. El dato devuelto es de tipo unsigned long (rango [0,2^32–1]).

Observación: Debido a que el dato que retorna millis() es de tipo unsigned long, por lo que se pueden generar errores si se intenta hacer operaciones matemáticas con otros tipos de datos.

8.8.2 Función delay(mtiempo)

Pausa el programa durante el tiempo (en milisegundos) especificado en el parámetro mtiempo. El dato dado como parámetro es de tipo unsigned long.

Observación: esta función detiene las lecturas de sensores, no se pueden manipular los pines, entre otras cosas.

8.9 Interrupciones

Una interrupción permite que el flujo normal de un programa se detenga y se ejecute una función específica. Una vez que esta función termina, el control retorna al programa. En el caso de Arduino UNO, tiene dos interrupciones, INT0 e INT1 asociadas a los pines 2 y 3, respectivamente. Una interrupción sucederá en cualquier momento de la ejecución del programa.

11. Anexos

11.1 Ley de Ohm

Esta ley dice que el Voltaje en un conductor eléctrico es directamente proporcional a la corriente que circula a través de ella. La constante de proporcionalidad se llama Resistencia y se mide en [Ω] (ohm).

Por ejemplo, si la resistencia R=10 [KΩ] y el voltaje v=3 [V], entonces i=0.3 [mA]

11.2 Divisor de voltaje

Un divisor de voltaje consiste en dos resistencias, dispuestas en una configuración como la mostrada en la Figura 34. El voltaje Vout se determina por la siguiente ecuación:

El factor G es menor que 1. Por lo tanto, se tiene que Vout

11.3 Medición de sensores resistivos

Los sensores que se utilizan con Arduino, en general, son resistivos. Esto quiere decir que son resistencias que varían su valor según alguna interacción con el medio ambiente. Por ejemplo, el sensor de luz (fotoresistencia) que tiene el kit Sparkfun es una resistencia, cuyo valor depende de la temperatura ambiente.

Ahora bien, la placa Arduino no puede medir resistencia, pero sí puede medir voltajes, a través de sus entradas análogas. Luego, integrando los conocimientos acerca del divisor de voltaje, es posible disponer de un voltaje que depende del medio ambiente. Para esto, se debe utilizar una de las configuraciones de la Figura 35. Para efectos prácticos, R fija = 10 [KΩ] y Vin = 5 [V].

Ahora, se debe tener claro que, según la configuración utilizada, se obtendrán distintos valores de entrada para la placa, bajo las mismas condiciones ambientales. Esto se ejemplifica a continuación.Ejemplo de rango de valores entregados por el sensor. Se desea utilizar la fotoresistencia para medir la luz ambiente. En ausencia de luz, tiene una resistencia de 1 [MΩ] y con luz ambiente (aprox 10 [lux]), 50 [KΩ]. Encontrar el rango de valores que serán leídos por la placa.Configuración A)

Para la configuración A, el valor mínimo es 0.05 [V], que Arduino lo interpretará como el número entero 10. El más alto, será 0.9 [V], que corresponde a un valor 184 (recordar que si se lee 5 [V], Arduino interpretará dicho voltaje como el número entero 1023).

Para la configuración B, el valor mínimo es 4.2 [V], que corresponde al número entero 859. El más alto, es 5 [V], que equivale al número 1023.

Resumiendo, según la configuración utilizada, se tendrán los siguientes rangos de voltajes y de valores de interpretados por Arduino cambiarán. Luego, la lógica del software cambia en la toma de decisiones. Por ejemplo, si se quiere tomar una decisión en torno a si hay luminosidad o no, el código en ambas

Entradas relacionadas: