Arduino en la práctica (parte 1): manejo del módulo de visualización
Arduino en la práctica (parte 1): manejo del módulo de visualización
Arduino en la práctica (parte 1): manejo del módulo de visualización
Arduino en la práctica (parte 2.)
El dispositivo terminado consta de bloques funcionales que a menudo se pueden usar varias veces. Por ejemplo, si estamos construyendo un medidor de frecuencia con un microcontrolador – entonces, además del bloque amplificador – necesitaremos casi los mismos componentes que para la construcción de un temporizador. Nos referimos a un microcontrolador con un "entorno" (resistencias, condensadores, cuarzo y otros), pantalla, botones y conectores. Obviamente, el contador de frecuencia no necesitará un relé para cambiar el dispositivo externo y el temporizador del amplificador de entrada de banda ancha, pero el núcleo seguirá siendo el mismo. Por lo tanto, la clave para el autodesarrollo de aplicaciones es comprender los principios de funcionamiento de los bloques funcionales individuales y luego combinar sus funcionalidades.
Plataformas como Arduino no requieren que el usuario conozca el principio de funcionamiento de los componentes individuales. Simplemente puede conectar la placa base al módulo / tapa de expansión y ejecutar una aplicación en funcionamiento. Por otro lado, si no tenemos al menos un conocimiento básico sobre los componentes, entonces en caso de problemas con el funcionamiento de nuestro dispositivo, estamos condenados a vagar en la oscuridad. Mientras tanto, cuando buscamos componentes Arduino, la mayoría de las veces esperamos un efecto rápido. Es difícil conciliar tales expectativas con la necesidad de adquirir los conocimientos adecuados, porque basta con ingresar algunos comandos para ver los primeros efectos en la pantalla, pero comprender por qué sucedió esto a veces lleva mucho tiempo.
Teniendo en cuenta las discrepancias descritas anteriormente, cada uno de los artículos de esta serie se dividirá en dos partes. En el primero, mostraremos cómo lograr el efecto. La segunda parte presentará cómo funciona un determinado componente o solución.
Comenzaremos con el módulo de pantalla LCD, porque gracias a él se puede ver el efecto del trabajo realizado más rápido. A continuación, analizaremos otros elementos de la interfaz de usuario y luego los sistemas externos seleccionados: sensores y actuadores. Mientras tanto, también nos familiarizaremos con algunos trucos y métodos de programación. Y todo ello basado en la plataforma Arduino, que es económica, de fácil acceso y, además, te permitirá utilizar los conocimientos adquiridos para construir dispositivos prefabricados o sus prototipos.
Módulo de visualización de caracteres LCD
La interfaz básica entre el microcontrolador y el usuario generalmente consta de una pantalla y un botón o botones. Como puede adivinar fácilmente, el primero se usa para informar al usuario sobre las actividades del microcontrolador, mientras que los botones, a veces reemplazados por el pulsador, se pueden usar para ingresar comandos o datos. Puedes encontrar en oferta muchas pantallas (incluidas las que tienen un panel táctil), sin embargo, las pantallas de caracteres con el controlador HD44780 se han convertido en un cierto estándar informal.
Pantallas con controlador HD44780
En el primer ejemplo de programación, usaremos una placa Arduino UNO R3, una placa de pruebas, un módulo LCD de caracteres con 2 líneas de 16 caracteres cada una y algunos cables de conexión. Por supuesto, esto es solo una sugerencia: la pantalla se puede conectar de cualquier manera, por ejemplo, soldándola a la PCB. Aquí, se utilizó el método que brinda la mayor posibilidad de modificar y cambiar el diseño de la conexión.
Si el módulo de visualización tiene pines dorados soldados, simplemente conéctelo a la placa de contacto. Luego conectamos la pantalla con la placa Arduino UNO, como se describe en la tabla 1.
Tabla 1. Conexiones de la pantalla de caracteres con la placa Arduino UNO
| Nº contactos de la pantalla | Nombre de la señal de visualización | Nombre del conector Arduino | Nombre de la señal Arduino |
|---|---|---|---|
| 1 | VSS | Power | GND |
| 2 | VDD | Power | +5V |
| 3 | V0 | Power | GND |
| 4 | RS | Analog In | A4 (PC4) |
| 5 | R/W | Power | GND |
| 6 | E | Analog In | A5 (PC5) |
| 7 | DB0 | – | – |
| 8 | DB1 | – | – |
| 9 | DB2 | – | – |
| 10 | DB3 | – | – |
| 11 | DB4 | Analog In | A0 (PC0) |
| 12 | DB5 | Analog In | A1 (PC1) |
| 13 | DB6 | Analog In | A2 (PC2) |
| 14 | DB7 | Analog In | A3 |
| 15 (opcional) | LED+ | Power | 3.3V |
| 16 (opcional) | LED- | Power | GND |
Recuerde que, por ejemplo, teniendo la tierra GND conectada desde el conector de alimentación a la placa de contactos, puedes hacer conexiones dentro de la placa de contactos y no tenemos que conectarnos al conector de alimentación cada vez.
El uso del conector descrito como Power es necesario porque suministrará energía a la pantalla. El conector Analogi In está montado justo al lado, por lo que, por conveniencia, se decidió utilizar los pines del microcontrolador disponibles. Sin embargo, no dejes que el nombre nos engañe: se requieren salidas digitales para controlar el módulo de visualización, no las E/S analógicas. El conector se llama Analog In porque tiene entradas analógicas opcionales, que, sin embargo, también se pueden configurar para funcionar en otros modos, incluidas las salidas digitales. Y así, la entrada analógica A0 es el puerto PC0, A1 - PC1, etc. (ver: Cables del microcontrolador ATmega328PU).
Entre las muchas posibilidades de controladores de software disponibles para Arduino, se seleccionó una biblioteca para controlar el funcionamiento de la pantalla LiquidCrystal. Después de crear el boceto, lo incluiremos en la primera línea del programa con una directiva #include. Con la pantalla conectada al microcontrolador de la manera descrita anteriormente, puede comenzar a hacer el primer boceto de control del módulo de pantalla LCD.
Conectamos la placa Arduino al puerto USB de nuestra PC. En el menú Arduino, elija Archivo y luego Nuevo (Ctrl+N). Aparecerá una ventana similar a la de la Figura 1. La palabra clave void nos dice que aquí es donde se creará una función que no devolverá ningún valor. La palabra void va seguida del nombre de la función, y la llave de apertura "{" indica su comienzo, y una "}" de cierre indica su final.
Al crear un nuevo boceto, el entorno Arduino informa sobre la necesidad de definir dos funciones especiales: una void setup (), que describe la configuración del microcontrolador y que contiene instrucciones realizadas una vez al comienzo del programa, y void loop (), que contiene actividades realizadas en un bucle sin fin.
Figura 1. Nueva ventana de boceto para Arduino
¿Por qué un programa de aplicación tiene que ejecutarse en un bucle infinito? Las aplicaciones de Windows o Linux se ejecutan bajo el control del sistema operativo. Si ejecutamos la aplicación en Windows, una vez finalizado el trabajo, vuelve al lugar donde se llamó y, por lo tanto, con mayor frecuencia para mostrar el llamado el escritorio, la línea de comandos, etc. A partir de ese momento, el sistema operativo toma el control del procesador. El microcontrolador de la placa Arduino UNO no tiene ningún sistema operativo cargado, por lo que el programador debe asegurarse de que la aplicación finalice de forma segura. Esto se puede hacer apagando el microcontrolador (por ejemplo, poniéndolo en modo de suspensión) o ejecutando en bucle la ejecución de instrucciones para evitar la ejecución de instrucciones fuera del rango de memoria requerido. Esto se puede hacer en la función void loop () o en algún otro método, un ejemplo del cual se proporciona a continuación.
Antes de mostrar información en la pantalla, se debe configurar el microcontrolador. En este ejemplo, solo necesita configurar correctamente las salidas de control de pantalla.
Al comienzo de nuestro boceto, incluimos una biblioteca de funciones de visualización:
#include Luego, para nuestra conveniencia y legibilidad del programa, usando la directiva #define definimos los nombres de los pines – salidas del puerto C del microcontrolador:
//purto PC #define pc0 A0 #define pc1 A1 #define pc2 A2 #define pc3 A3 #define pc4 A4 #define pc5 A5 Ahora informamos al microcontrolador a qué pines está conectada la pantalla. Para esto se utiliza la función lcd (), en la que la lista de argumentos indica al procesador dónde va cada señal. Al reemplazar los pines, mantenga el orden correcto:LiquidCrystal lcd(RS, Enable, D4, D5, D6, D7). Al crear una lista de argumentos, usaremos la tabla 1, que contiene una lista de conexiones entre el Arduino y el módulo de pantalla LCD.: LiquidCrystal lcd(pc4, pc5, pc0, pc1, pc2, pc3).
Ahora debe ocuparse de la configuración del modo de funcionamiento de los pines; debe configurarlos para que funcionen como salidas digitales. Esta configuración se almacena dentro de la función void setup ():
pinMode(pc0, OUTPUT); pinMode(pc1, OUTPUT); pinMode(pc2, OUTPUT); pinMode(pc3, OUTPUT); pinMode(pc4, OUTPUT); pinMode(pc5, OUTPUT); Luego realizamos la inicialización de la pantalla, configurando el número de columnas, filas y en el primer paso, limpiando la pantalla. Después de la inicialización, la pantalla LCD debe estar en blanco, pero por seguridad y un inicio adecuado del trabajo, vale la pena seguir esta instrucción más:
lcd.begin(16, 2); lcd.clear(); Después de todo, un comando es suficiente para mostrar el mensaje:
lcd.print("Hello!"); No ponemos ningún comando en la función loop (). Después de mostrar el mensaje, el programa simplemente "girará" en un bucle sin fin, desperdiciando tiempo de CPU. En principio, sería posible en este punto, por ejemplo, ingresar al modo de ahorro de energía, porque el mensaje en la pantalla no cambiaría de todos modos, pero requeriría más investigación de hardware, lo cual no es recomendable en esta etapa.
Todo el programa que muestra el mensaje "¡Hola!" se puede encontrar en los materiales complementarios de este texto. Si la descripción anterior y el efecto logrado son satisfactorios, puede omitir la lectura del resto del texto. En el próximo artículo, nos ocuparemos de operaciones un poco más avanzadas en el contenido mostrado que solo mostrar el mensaje.
Operación del módulo de pantalla LCD
Un análisis más detallado del tema debería comenzar discutiendo la estructura del microcontrolador que está montado en la placa Arduino, pero es un tema muy extenso. Por lo tanto, primero consideraremos cómo funciona el módulo LCD.
Se requieren conocimientos básicos de chips de memoria y chips digitales en general para comprender cómo controlar el módulo LCD. El conocimiento de términos como lógica alta, baja, forma de onda, datos, 8-bit, byte, bit, flanco descendente y ascendente es esencial. Esto es necesario porque, desde el punto de vista del manipulador, el módulo de visualización se ve como una especie de memoria digital con la que el microcontrolador puede comunicarse bidireccionalmente. Mientras tanto, de hecho, el módulo de pantalla LCD tiene su propio microcontrolador (este es el mencionado al principio HD44780 o similar), que no solo recibe los datos a mostrar, sino que también ejecuta los comandos relacionados con el funcionamiento del módulo LCD. y es compatible con la pantalla. Debido al hecho de que en el sistema el microcontrolador integrado en el módulo de visualización tiene una función autónoma estrictamente especializada, tales sistemas a menudo se denominan esclavos o subordinados. El microcontrolador integrado en la placa Arduino realiza una función de control superior. Por lo general, estos sistemas se denominan maestro o maestro. Nos encontraremos con estos conceptos muchas veces en las descripciones de varios dispositivos conectados al microcontrolador.
Lógicos “0” y “1”
Volvamos a lo básico por un momento. En los circuitos CMOS, y la mayoría de los circuitos integrados modernos se utilizan en dicha tecnología, el "1" lógico es al menos el 95% del voltaje de suministro y el "0" lógico es un voltaje menor o igual a 0.3 V. Si el circuito del procesador tiene una fuente de alimentación incorporada, que suele ser el caso de procesadores más complejos, el "1" lógico se define con referencia a la fuente de alimentación interna. También puede ser diferente – si el sistema CMOS tiene entradas compatibles con los niveles TTL, entonces el "1" lógico es un voltaje superior a 2,4 V. Por lo tanto, en caso de duda, vale la pena consultar la hoja de datos de un sistema dado. Lo podemos encontrar fácilmente en Internet.
Pendiente ascendente y descendente
Un cambio en el nivel lógico provoca un cambio en el voltaje. Este cambio se produce a pasos agigantados, pero no obstante, con el tiempo. Cuando el nivel cambia de "0" a "1" es un flanco ascendente, y cuando cambia de "1" a "0" es un flanco descendente. La duración de la transición se denomina tiempo de subida o tiempo de bajada, respectivamente. Por lo general, son unos pocos nanosegundos, pero este no es necesariamente el caso.
En un microcontrolador, una sola línea que lleva el nivel "0" o "1" se denomina bit de datos. 8 de tales líneas forman un byte. Un microcontrolador AVR, como el Arduino UNO incorporado, tiene una palabra de datos de 8 \ -bit, por lo que puede procesar palabras de 1-byte, decimal de 0… 255. Si el número es mayor que 255, es necesario dividirlo en "trozos", ealizar una operaci n en ellos y luego ensamblar el resultado. Sin embargo, no tenemos que preocuparnos por eso, porque el compilador Arduino lo hace en segundo plano. Sin embargo, debe tener en cuenta que cuantos más bits requiera una determinada variable, más tiempo será procesada por el microcontrolador.
Control del módulo de pantalla LCD
En este ejemplo, el microcontrolador maestro controla el módulo de pantalla LCD con señales de salida. Al cambiar sus señales de salida, controla los niveles lógicos en las entradas del módulo de visualización. Gracias a esto, puede seleccionar el momento de guardar los datos y el área de memoria en la que se guardarán los datos:
- El lógico "1" en la entrada RS (Selección de registro) guarda los datos en la memoria de imagen, mientras que el "0" lógico - guarda los datos en el registro de control del módulo de visualización. El microcontrolador maestro debe poder controlar esta entrada para poder enviar correctamente los comandos al controlador de pantalla (RS=0) y los datos que se mostrarán (RS=1). Poner en cortocircuito esta entrada a un nivel lógico alto y constante evitará que el módulo de visualización ejecute los comandos del tipo "borrar pantalla" y no permitirá la inicialización correcta (el registro de control no estará disponible).
- El lógico "1" en la entrada R/W (lectura/escritura) lee los datos y el "0" lógico escribe. En nuestro ejemplo, forzamos permanentemente esta entrada del módulo LCD a baja conectándola a tierra. Esto es correcto asumiendo que solo escribiremos datos en la pantalla y no los leeremos. Al agregar esta entrada al nivel lógico constante, perdemos la capacidad de leer la memoria de la pantalla y su registro de control y, por lo tanto, la señal de "ocupado". La prueba "Ocupado" acelera el trabajo del módulo de visualización y también le permite probar la exactitud de la respuesta de su controlador a los datos recibidos, pero también ocupa una línea de puerto adicional del microcontrolador maestro y requiere una conexión más y complica la programa de servicio un poco.
- El flanco descendente en la entrada "E" (Habilitar) reescribe los niveles lógicos (que constan de palabras de datos de 4- u 8-bits) desde las entradas DB0… DB7 a la memoria interna del módulo LCD.
Al controlar el funcionamiento del módulo de visualización de caracteres LCD, tenemos dos modos de funcionamiento a nuestra disposición, normalmente 8-bit y 4-bit. En el primero, conectar la pantalla requiere al menos 10 líneas de datos (RS, E, D0… D7). Desde el punto de vista del controlador, este modo es muy eficaz si puede conectar una pantalla al sistema host como memoria en un bus de datos de 8 bits. El direccionamiento del módulo de visualización establece la entrada de habilitación alta, baja o alta (dependiendo de si se trata de un comando o de un dato para mostrar) en RS, coloca los datos en el bus y cambia el nivel a Habilitar a bajo. En algunos sistemas, el controlador simplifica enormemente esto.
En el modo de 4-bit todavía usamos la palabra de 8-bit, pero solo las entradas D4… D7 del módulo de visualización están conectadas al sistema host, y las palabras de datos de 8 \ -bit se dividen en dos porciones de 4 bits cada uno. Esto complica el programa de mantenimiento y no permite una fácil conexión del módulo de visualización al sistema de supervisión, pero ahorra 4 líneas GPIO del microcontrolador.
En los manipuladores de módulos LCD simplificados que no utilizan las líneas R/W a priori, se supone que el módulo de visualización funciona correctamente. Se establece un cierto tiempo predeterminado, como la ejecución del comando de ejecución más larga (generalmente alrededor de 2 milisegundos), y se supone que después de este tiempo la pantalla ha ejecutado el comando o mostrado un carácter y se pueden enviar datos posteriores. Por lo general, el microcontrolador integrado en el módulo de visualización es más rápido: solo la ejecución del comando clear (limpieza de pantalla) tarda hasta 2 milisegundos. Por otro lado, si, como en este ejemplo, tenemos 2 líneas de 8 caracteres en la pantalla, entonces no importa mucho si enviamos 16 bytes en 32 milisegundos o 100 microsegundos. Ningún usuario podrá notarlo de todos modos. Esto solo cambia cuando se trata de pantallas gráficas a las que se transmite una cantidad mucho mayor de datos.
Arduino no nos da demasiado margen de maniobra a la hora de controlar la pantalla. El microcontrolador ATmega328 integrado en Arduino UNO no tiene líneas de dirección externas, por lo que controlar la pantalla en modo de 8-bit con direccionamiento como una memoria externa está fuera de discusión. Sin embargo, si usamos un puerto GPIO, más para controlar la señal R/W, podemos probar la bandera de ocupado y leer el contenido de los registros y la memoria del módulo LCD.
La función del mismo nombre, es decir, LiquidCrystal (), se utiliza para configurar el método de adjuntar la pantalla en la biblioteca LiquidCrystal.h. La forma de adjuntar la pantalla está determinada por la función que llama a la lista de argumentos:
- LiquidCrystal(rs, enable, d4, d5, d6, d7) – Interfaz de 4 bits, sin módulo de visualización, control de entrada R/W y, por lo tanto, sin legibilidad de datos.
- LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) – Interfaz de 4 bits, con control de la entrada R/W del módulo LCD y la capacidad de leer datos de la pantalla.
- LiquidCrystal(rs, enable, d0, d1, d2, d3, d4, d5, d6, d7) – Interfaz de 8 bits, pero no puede leer datos.
- LiquidCrystal(rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7) – Interfaz de 8 bits, datos legibles.
El controlador HD44780 es un sistema universal, adaptado para admitir pantallas LCD con un número diferente de caracteres (columnas y líneas). Como resultado, después de encender la alimentación, el controlador "no sabe" qué pantalla está conectada y debe configurarse para su correcto funcionamiento. En Arduino, la función begin () se usa para esto, cuyos argumentos son el número de columnas y el número de filas. Por ejemplo, si tiene una pantalla con 2 líneas de 16 caracteres, llamaríamos begin (16, 2).
El programa de ejemplo también usa la función clear () para borrar la pantalla. Es una buena práctica usarlo primero, después de inicializar el módulo LCD, porque podemos encontrar pantallas que muestren caracteres aleatorios después de la inicialización. También usamos la función print (). Sus argumentos son los datos a mostrar, como un número o texto, y - en el caso de números - una base, que para números decimales es "DEC", binario "BIN", hexadecimal "HEX", octal "OCT" . La función print () se encarga de convertir números por nosotros, si es necesario mostrarlos en diferentes sistemas numéricos:
- print(10) o print(10, DEC) –> causa la visualización 10,
- print(10, BIN) –> causa la visualización 1010,
- print(10, HEX) –> causa la visualización A,
- print(10, OCT) –> causa la visualización 12.
- print("Hello!") –> causa la visualización del comunicado Hello!
Imprimir coloca los caracteres mostrados desde la posición actual del cursor. Normalmente, después del comando clear (), el cursor se encuentra en la esquina superior izquierda de la pantalla LCD.La biblioteca de funciones LiquidCrystal.h contiene muchas otras funciones útiles, pero cubriremos cómo usarlas en el próximo artículo. En cuanto al principio, hemos aportado una gran parte de conocimiento, es hora de descansar un poco.

