¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Arduino
  3. Un primer programa
Extrait - Arduino Hágalo jugar a los trenes
Extractos del libro
Arduino Hágalo jugar a los trenes Volver a la página de compra del libro

Un primer programa

La interrupción necesaria

1. Una librería

Los datos DCC se envían a las vías mediante la modulación de señales eléctricas cada 58 µs. Un bit 1 corresponde a una señal positiva de 58 µs, seguida de una señal negativa de la misma duración. Un bit 0 es una señal positiva de 116 µs, esto es, dos señales de 58 µs, seguidas de una señal negativa de la misma duración. Así, todo es un múltiplo de 58 µs. Basta con una interrupción ajustada a esta duración para que la señal DCC se genere con la precisión necesaria.

En el mundo Arduino, programar interrupciones no es complicado. Existen varias bibliotecas para gestionarlas. La biblioteca msTimer, que se propone como predefinida, utiliza una base de tiempo de 1 ms, que no es lo suficientemente precisa para generar una señal DCC. Por lo tanto, se utiliza la biblioteca FlexiTimer2, ya que ofrece una resolución de 1 µs.

Esta biblioteca no está disponible en el gestor de Arduino, por lo que es necesario descargar el archivo por separado para luego utilizar la opción Añadir biblioteca ZIP. El archivo está disponible en la dirección: https://playground.arduino.cc/Main/FlexiTimer2/

Esta biblioteca da acceso a tres funciones: set, start y stop, que permiten respectivamente...

La creación de la señal DCC

1. La teoría

Entre el botón que se gira para ajustar la velocidad del tren y la señal que se envía a las vías, se necesitan varias transformaciones. Esto comienza con el formateo de los datos que se leen en primera instancia. Se puede tratar de una entrada analógica a la que se conecta un potenciómetro, un teclado o interruptores. Estos datos se formatean y luego se convierten a la forma de un paquete DCC, constituido de un número variable de bytes:

  • 1 o 2 bytes para el direccionamiento

  • 1 a 3 bytes para el comando

  • 1 byte de suma de verificación

Por tanto, este paquete DCC puede tener entre 3 y 6 bytes, según el caso. Los paquetes solo se crean y almacenan en caso de cambio de velocidad de las teclas de función; es inútil hacerlo sistemáticamente si nada ha cambiado.

Este paquete se almacena, a continuación, en la memoria, ya que los datos DCC deben reenviarse regularmente, aunque no cambien, pues de lo contrario las locomotoras acabarán parándose solas. Se trata de una cuestión de seguridad. Este almacenamiento adopta la forma de una tabla que lista todos los paquetes que se van a transmitir. Cuando se debe almacenar un paquete, primero hay que comprobar si va a sustituir a uno ya existente o si es uno nuevo.

Finalmente, el envío se realiza mediante una rutina en interrupción llamada cada 56 µs. Se necesitan dos llamadas para enviar un bit 1 y cuatro llamadas para enviar un bit 0. Además de los datos que componen el paquete en sí, también hay que enviar la cabecera y añadir los bits de separación y de STOP.

2. La creación de los bits

Cada vez que se llama a una interrupción, cada 58 µs, solo se transmite una señal. Esto corresponde, según el caso, a medio bit (en el caso de un bit 1) o a un cuarto de bit (en el caso de un bit 0). Por lo tanto, es necesario guardar el estado actual para saber a qué estado pasar durante la siguiente llamada. Esto es posible gracias a las variables de estado. Hablar de variables de estado es hablar de máquina de estados, que generalmente se conoce como autómata finito.

El generador de bits es el autómata de más bajo nivel. Se basa en dos variables:

  • dccBit (variable de entrada): indica si se debe emitir...

La programación

1. La interfaz de usuario

Como la memoria disponible en un Arduino Uno es bastante limitada, es necesario crear una interfaz de usuario lo más escueta posible. Por fortuna, hay pocas interacciones que gestionar; esencialmente, la navegación por los menús y la introducción de texto o valores numéricos. La programación de la interfaz de usuario ya se ha explicado brevemente en el capítulo Los otros circuitos y no se tratará con más detalle, ya que no es el objetivo de este libro.

Se puede descargar desde la página Información: at-multi2.ino.

Hay que gestionar los siguientes puntos:

  • Direccionamiento de la locomotora, en modo corto o largo.

  • Aplicación de la consigna de velocidad, en 14, 28 o 128 muescas.

  • Control de las funciones.

La consigna de velocidad se obtiene a partir de la lectura de una entrada analógica a la que se ha conectado un potenciómetro.

Como este programa está diseñado para controlar una sola locomotora, podemos conformarnos con una interfaz de usuario muy sencilla, que se basa en solo dos pantallas.

En primer lugar, la pantalla de inicio, que permite elegir los parámetros de control de la locomotora. Los parámetros se modifican con las teclas izquierda y derecha; el cursor parpadeante indica el parámetro seleccionado. Se puede, a continuación, variar el parámetro seleccionado con las teclas arriba y abajo.

  • Selección del modo de direccionamiento (corto o largo).

  • Selección de la dirección (2 o 4 dígitos, según el modo de direccionamiento).

  • Selección del número de muescas de velocidad (14, 27, 28 o 128)

images/cap05_img_03.png

Una vez elegidos los parámetros, se puede pasar a la siguiente pantalla pulsando el botón OK. Se trata de la pantalla de control. Si se pulsa [Esc], se vuelve al menú principal.

images/cap05_img_04.png

La velocidad se selecciona con el potenciómetro. Las teclas izquierda y derecha permiten cambiar la dirección de la marcha. Cuando el tren está avanzando, este se detiene si se pulsa una vez la tecla izquierda; si se pulsa una segunda vez esta tecla, el tren se mueve, pero marcha atrás. Al pulsar el botón derecho, el tren se detiene nuevamente, y al pulsar este botón por segunda vez, se pone en marcha hacia delante. Las teclas arriba y abajo se utilizan para navegar...

Optimizaciones

1. El problema

La memoria libre se agota rápidamente y es por una razón sorprendente: aunque el programa y los datos estén almacenados en la memoria flash, tienen que copiarse de nuevo a la RAM en el momento de la puesta en marcha, lo que consume memoria innecesariamente en el caso de las constantes (por ejemplo, las cadenas que aparecen en la pantalla).

Este problema se debe a la arquitectura de memoria de los microprocesadores Atmel que equipan los circuitos Arduino, que es del tipo Harvard. En este caso, las áreas de memoria de programa y de datos están separadas. El área de programa apunta a la memoria flash, mientras que el área de datos apunta a la RAM.

2. El uso de la memoria

Este es un punto que comúnmente se omite, ya que a menudo hay suficiente memoria para que todo funcione bien. Pero vale la pena mencionarlo porque explica algunos de los bloqueos que se producen con los sketchs (programas) ligeramente cargados.

Es importante optimizar el uso de la memoria RAM y más aún, puesto que almacena muchos datos y de formas diversas. En la práctica, esto se divide en tres bloques distintivos, pero, sin embargo, adyacentes, cada uno dedicado a ciertos tipos de variables:

  • Estáticas: variables globales, así como variables locales estáticas.

  • Pila (stack): parámetros de funciones y variables locales no estáticas.

  • Montículo (heap): instancias de objetos (new) y asignaciones de memoria dinámica (malloc). 

Entre estos dos últimos bloques de memoria hay una la zona de memoria libre, que evoluciona durante la ejecución del programa.

images/cap05_img_05.png

El área estática no se mueve; su contenido puede variar, pero su tamaño no cambia. Sin embargo, la pila y el montículo cambian y esto puede ser un problema.

Cuando se llama a una subfunción, se consume pila. Si hay muchos parámetros y muchas variables locales, se consume aún más. Si una subfunción llama a otra, que a su vez llama a otras más, se consume todavía más pila. El tamaño de la pila puede aumentar o disminuir...