Archivo por meses: diciembre 2018

Arduino: bibliotecas de funciones personales

A menudo tenemos fragmentos de código con funciones que podemos reutilizar en muchos programas. Algo muy habitual en programación. Creamos una función que resuelve una necesidad concreta y queremos tenerla disponible para reutilizarla en cualquier otro programa en el que debamos resolver la misma necesidad.

Lo habitual —pero no lo más práctico— es copiar el código de esa función especial dentro de cada nuevo programa. Pero conviene tenerla en un formato reutilizable con facilidad, sobre todo si la función es muy extensa.

Para lograrlo, guardamos esa función (y todas las variables y constantes que incluya) en un archivo .ino separado, pero no debemos cargarlo individualmente en una placa Arduino, sino que luego lo incluiremos en cada programa que necesitemos, de al modo que siempre lo tendremos disponible.

( Nota: no le llamamos “sketch” sino “programa” para Arduino. )

¿Cómo incluimos un trozo de programa en otro?

Vamos a crear un código reutilizable, y lo guardaremos en una ubicación conocida del disco, un “reservorio” de funciones útiles que llevan un nombre que nos recuerde qué es y lo que hace.

Quedará con la extensión .INO, pero no es un programa para cargar al Arduino y ejecutarlo. Queda con esa extensión porque todos los programas editados en la IDE de Arduino se graban siempre con la extensión .ino.

El código es uno que hayamos creado como función o grupo de funciones dentro de un programa mayor.

Tomaremos como ejemplo una cantidad de funciones creadas para los distintos movimientos de los motores en un programa para un robot navegador.

El circuito que este programa mueve, para mejor comprensión de los ejemplos, es este:

Veamos el programa original con las funciones incluidas dentro de él:

Ahora vamos a escribir un programa diferente, con otra serie de movimientos. Suponemos que estamos editando en el IDE de Arduino, como sigue:

Pero así no funcionaría, ya que tiene llamados a funciones (como adelanteDerecho, atrasIzquierdo, etc.) que están en otro lugar.

De modo que abrimos el programa que las tiene, copiamos las funciones que necesitamos…

… y las pegamos en una ventana vacía del IDE. Luego las guardamos con Guardar como… en la carpeta que deseemos. A esta carpeta podemos llamarla, por ejemplo: /FuncionesUtiles/

El archivo de funciones que creamos y guardamos es este: FuncionesMotor.ino, y es así:

Ahora sólo debemos ver cómo hacemos para incluir el archivo de funciones auxiliares en nuestro nuevo programa.

Para eso desplegamos el menú Programa en la barra de menúes de la parte superior del IDE. Seleccionamos la opción Añadir fichero… y se nos abre un cuadro de diálogo para que busquemos el .ino que guardamos allí, con las funciones de motor que queremos incluir en este programa nuevo.




Lo abrimos, como si fuera un .ino estándar, pero, debido a la opción que hemos elegido, en lugar de abrirse en una nueva ventana del IDE se abre en una nueva pestaña auxiliar de la misma ventana. Nuestra ventana de trabajo queda como vemos aquí:

Ya podemos regresar a la pestaña principal, compilar y subir el programa al Arduino.

Cuando guardemos este programa principal, y volvamos a abrirlo otro día, el IDE de Arduino se abrirá con las dos pestañas. Si se observa dentro de la carpeta que, como es habitual, lleva el nombre del programa (en este ejemplo Otro_control_de_motores) veremos que dentro de ella están los dos archivos .ino: Otro_control_de_motores.ino y FuncionesMotor.ino

Esto no significa que el IDE haya movido FuncionesMotor.ino desde la carpeta /FuncionesUtiles/ que creamos, sino que sólo lo ha copiado. Así que, por supuesto, este archivo .ino de funciones auxiliares para adjuntar podemos incluirlo en todos los programas donde sea necesario. No será propiedad exclusiva de ninguno de ellos.


RCWL-0516: Módulo sensor de movimiento de microondas con radar Doppler

Este módulo ha sido diseñado como una alternativa a los conocidos sensores de movimiento PIR (Sensor Infrarrojo Pasivo), ampliamente utilizados en alarmas antirrobo, y en luces de seguridad. Contiene en su interior todos los componentes electrónicos esenciales, incluyendo un regulador de tensión interno en el chip, que entrega 3,3V.

Al igual que el sensor PIR, este sensor también detecta solamente algo que esté en movimiento dentro de su rango de detección, pero en lugar de percibir la radiación del cuerpo negro (infrarrojo) de una persona que se mueve, este sensor utiliza una técnica de “radar Doppler de microondas” para detectar cualquier tipo de objetos en movimiento.

Tamaño:

Tiene un rango de sensibilidad de alrededor de 7 metros. Cuando se dispara, su pin de salida de nivel TTL (OUT) cambia de BAJO (0 V) a ALTO (3,3 V) por un tiempo de 2 a 3 segundos antes de volver a su estado inactivo (BAJO).

Características:

1. Voltaje de Operación: 4-28V
2. Corriente de Operación: 2,8mA (típica); 3mA (máx)
3. Distancia de Detección: 5-7m
4. Potencia de Transmisión: 20mW (típica); 30mW (máx)
5. Voltaje de Salida: 3,2-3,4V
6. Capacidad de Corriente del Voltaje de Salida: 100mA
7. Modo de Disparo: repetición de disparo
8. Nivel de Salida Bajo: 0V
9. Nivel de Salida Alto: 3,3V
10. Temperatura de Operación: -20º a 80º celsius
11. Temperatura de almacenamiento: -40º a 100º celsius

Como se ve en sus características, el sensor puede manejar un amplio rango de alimentación: desde 4 hasta 28 V. El pin de salida se puede utilizar para una multitud de tareas, como el manejo de un indicador auditivo o visual, o incluso para conectarlo a la entrada de un microcontrolador para su procesamiento.

Donde se instale, se debe evitar que haya partes metálicas delante del módulo. Del mismo modo, siempre hay que mantener un mínimo de espacio libre de 1 cm en la parte frontal y posterior del módulo.

Pines de salida:

CDS – Entrada de desactivación del sensor (bajo = desactivado)
VIN – entrada de alimentación de 4 a 28V CC
OUT – ALTO (3,3V) movimiento detectado / BAJO (0V) inactivo
GND – Tierra / 0V
3V3 – Salida de CC regulada (100mA máx)

El LDR es opcional. Si se instala, inhibe el funcionamiento del módulo cuando recibe la luz del día. Es evidente que se convierte en una función útil cuando se utiliza el sensor para encender luces de seguridad, ya que al hacerse de día dejará de encenderla por no ser necesaria esa iluminación con luz diurna.

La distancia de detección, y la duración de la salida del módulo cuando hay una detección, se pueden ajustar añadiendo componentes pasivos en unos puntos de soldadura de la parte posterior de la placa de circuito.

Los elementos opcionales para realizar distintos ajustes van soldados sobre los puntos marcados C-TM, R-GN y R-CDS (abajo, imagen del lado de la soldadura de la placa).

Hay puntos de soldadura donde agregar una resistencia dependiente de la luz LDR (marcado CDS). El pin de entrada CDS sirve para desactivar (anular la opción de detección de luz ambiental) en el sensor, si fuese necesario.

C-TM: Ajusta el tiempo de activación de repetición (predeterminado: 2 segundos). Agregar un condensador dará una repetición más extensa del tiempo de disparo.

R-GN: ajuste de la distancia de detección (por defecto 7 metros). Añadiendo una resistencia a la detección la distancia se hará más corta. Si está conectado con una resistencia de 1 MΩ, el rango de detección es de aproximadamente 5 m.

R-CDS: al agregar una resistencia (en paralelo con la resistencia interna de 1 MΩ), el usuario puede cambiar el umbral de detección de luz según su necesidad individual. Esto es aplicable solo cuando hay un sensor de luz soldado en los puntos de soldadura (CDS) en la parte frontal de la placa de circuito.

Una resistencia de 47–100K funciona bien con un LDR estándar de 5 mm.

Funcionamiento

La electrónica del módulo posee dos secciones igualmente importantes: un transmisor / receptor / mezclador de frecuencia de microondas basado en un transistor NPN de alta frecuencia MMBR941M, y una sección de frecuencia mucho más baja basada en un circuito integrado RCWL-9196.

Técnicamente, la sección de microondas se parece a un “oscilador Colpitt” con el inductor requerido (y los capacitores) hechos con trazas de la placa de circuito. El inductor (~ 10 nH) es el trazado de la curva S en la superficie superior, y los condensadores son la estructura en anillo en la superficie inferior, y también el bloque rectangular a la izquierda de la S curva.

Circuito de la placa

Ubicación de los componentes

Circuito del chip

Dos modos de salida

Un circuito de prueba

Antes de profundizar en algo, le recomiendo que se familiarice con el hardware y el procedimiento inicial de instalación/ejecución y tratar de hacer algunos pequeños experimentos.

Aunque puede usar RCWL-0516 solo con una fuente de alimentación y un LED en su salida, se puede agregar un circuito controlador de relé para controlar cargas externas que requieran mayor corriente al accionarse cuando se detecta un movimiento.




Esquemático de la primera prueba:

Tenga en cuenta que la resistencia de 1 k (R1) no es necesaria ya que el módulo tiene una resistencia de 1 kΩ entre el pin OUT y el pin de salida real del chip de 16 patas (RCWL-9196).

El relé (RL1) en el circuito es accionado por un transistor estándar BC547 o 2N3904 (T1), y hay un indicador de “relé encendido” (LED1) que se enciende cuando el relé está en estado activo. Si lo desea, también puede utilizar otros relés de voltaje diferente. Sin embargo, en ese caso, la entrada de la fuente de alimentación (que es de 5 V) tendría que ser cambiada (con algunas otras modificaciones menores, por supuesto). El conector de 2 pines (JP1) está reservado para pruebas futuras, y sólo es utilizable cuando hay un sensor de luz conectado al módulo.

Para fines experimentales, este circuito se puede construir en una placa de pruebas. Se puede usar un conector de 5 patas (sólo se requieren tres para la primera prueba) para conectar el módulo de radar.

A continuación se muestra el montaje de esta configuración de prueba (ver también el video de prueba):

Video

  

Efecto Doppler

En principio, el efecto Doppler es un cambio en la frecuencia recogida por un receptor de la señal reflejada en un objeto en movimiento. En los radares de efecto Doppler, para detectar un objeto en movimiento se puede usar una señal no modulada (CW). El receptor del sensor procesa la señal transmitida con la señal reflejada en un objetivo.

Debido al efecto Doppler, la velocidad de desplazamiento de un objeto en relación con la antena provoca un cambio en la frecuencia. Se puede estimar, simplemente, que la frecuencia Doppler (que es la frecuencia obtenida en el receptor) es la cantidad de medias-ondas de la frecuencia de señal enviada por el objetivo por segundo. Una velocidad más alta producirá una frecuencia Doppler más alta. Un sistema de este tipo, con una disposición para detectar la fase de la señal, también puede indicar el sentido del movimiento del objetivo: los objetos que se alejan generan una frecuencia más baja que la de la señal de sondeo, mientras que los objetos que se aproximan generan una frecuencia más alta.

Oscilador Colpitts

El oscilador Colpitts es un tipo popular de oscilador LC inventado por Edwin Colpitts en 1918. La figura que se ve a continuación muestra un oscilador Colpitts típico basado en un BJT con un circuito tanque, en el cual un inductor L está conectado en paralelo a la combinación en serie de condensadores C1 y C2. La frecuencia del oscilador Colpitts depende de los componentes de su circuito tanque, y se puede calcular mediante una fórmula simple (ver figura). Por ejemplo: si L = 27 uH, C1 = 1 nF y C2 = 15 nF, entonces F = 1 MHz. Tenga en cuenta que el oscilador Colpitts se puede sintonizar variando la inductancia o la capacitancia.

Diagrama de un oscilador Colpitts

En mi opinión, el sensor de microondas RCWL-0516 es una poderosa alternativa al sensor PIR común, pero este modelo tiene una documentación muy limitada (escasa), lo que lo convierte en un problema para los principiantes. Además de leer el material “chino” encontrado, también se han hecho algunas investigaciones para agregar alguna información para que alguien pueda usarla rápidamente. Mientras que, por el momento, no se ve otro uso para este módulo de sensor aparte de su aplicación de detección de movimiento, se puede adaptar fácilmente para agregar o modificar funciones. Una de ella sería una discriminación más detallada de las trayectorias de objetos que se alejan o se acercan. Debido a sus características de emisión de RF, no se deben colocar sensores a menos de 1 metro uno de otro, pero con dos sensores colocados a la distancia correcta sería posible, también, conocer si el objeto en movimiento lo hace de derecha a izquierda o a la inversa, de izquierda a derecha. Combinando ambas detecciones, es decir, aproximación y alejamiento, y desplazamiento en sentido horizontal respecto a los sensores, sería posible saber detalles de cómo se está desplazando el objeto detectado en el área monitoreada.


[Varias partes de este artículo están basadas en la recopilación de Joe Desbonnet y otros colaboradores mencionados en ésta en GitHub bajo licencia Creative Commons y autorización expresa del autor]

Uso de la placa L298N para motores de CC

Este artículo es el paso 1 para ir adelantando explicaciones sobre el funcionamiento de un robot navegador con dos sensores de obstáculos al frente y uno en la parte trasera, que publicaré en breve. Nos muestra cómo se debe utilizar la placa de manejo (doble puente H) L298N para controlar un motor de CC.

Este módulo tan común en el Mercado, basado en el chip L298, permite controlar dos motores de corriente continua, o un motor paso a paso bipolar, en ambos casos de hasta 2 A por salida.

Diagrama de circuito del circuito integrado L298

El módulo es autosuficiente para funcionar en el control de los motores, sin que sea necesario disponer de elementos adicionales. Ya tiene los diodos de protección de contracorriente y un regulador LM7805 interno que suministra 5V a la parte lógica del integrado L298.

La salida en la bornera A esta compuesta por las líneas OUT1 y OUT2, y la salida B por OUT3 y OUT4.

En la parte inferior se encuentran los pines de control del módulo, marcados como IN1, IN2, IN3 e IN4. A los lados de estas señales encontramos un pin de 5V preparado para colocar puentes de selección (jumpers) que habilitar cada una de las salidas del módulo, A y B). Los pines de habilitación son nombrados, respectivamente, ENA y ENB (por la palabra en inglés Enable = habilitación).

Conexión de alimentación

Este módulo se puede alimentar de dos maneras: utilizando o no el regulador LM7805 integrado en la placa.

Cuando el puente de selección de 5V se encuentra activo, el módulo permite ingresar una alimentación para toda la placa, motores y lógica, de entre 6V a 12V CC. Dado que de esta manera el regulador se encuentra activo, el pin marcado como +5V tendrá un voltaje de salida de 5V CC. Este voltaje alimenta dentro de la placa la lógica del chip, y también se puede usar para dar alimentación a la parte de control del módulo, ya sea un microcontrolador de otro tipo o una placa Arduino, pero recomendamos que el consumo externo que se tome de la placa L298N no supere los 500 mA.

Cuando el jumper de selección de 5V es retirado, el módulo admite una alimentación más amplia para los motores: de entre 12V a 35V CC. Como en este caso el regulador interno 7805 no se utiliza, tendremos que conectar el pin de +5V a una tensión de 5V externa, regulada, para alimentar la parte lógica del L298N. Usualmente esta tensión puede ser la misma de la parte de control, ya sea un microcontrolador de otra línea o una placa Arduino.

No se debe conectar una tensión de entrada al pin de +5V cuando se encuentre colocado el puente de selección de 5V. Esto provocaría un conflicto entre ambas fuentes de alimentación y podría dañar permanentemente el módulo.

Control de un motor de CC

Como demostración, vamos a controlar un motor de CC usando la salida B del módulo. El pin de habilitación ENB se mantiene en ALTO por medio de la conexión al pin 3 del Arduino, puesto en ALTO por el programa. Opcionalmente se puede conectar ENB a +5V con el jumper (marcado amarillo en los diagramas) —como se observa en la imagen de abajo—, aunque luego deberemos modificar la conexión para el segundo ejercicio.

El ejemplo fue desarrollado en Arduino UNO, pero el código es compatible con cualquier Arduino.

Esquema de conexión del ejemplo 1

Tabla de señales de control

Código en el Arduino – Ejemplo 1

El programa activará el motor en un sentido por cuatro segundos, luego detiene el motor por medio segundo, después activa el motor en sentido inverso por cuatro segundos, y por último detiene el motor durante cinco segundos. Este ciclo se repite indefinidamente.

Control de un motor CC con variación de su velocidad

Si queremos controlar la velocidad del motor, debemos hacer uso de una salida PWM, en este ejemplo la salida digital 3 del Arduino Uno. Esta señal PWM será aplicada a los pines de activación de cada salida, ENA y ENB respectivamente, de manera que en este caso los jumper de habilitación a +5V no deben ser colocados.




Esquema de conexión del ejemplo 2

Código en el Arduino – Ejemplo 2

Este programa controla la velocidad de un motor CC aplicando una señal PWM al pin ENB del módulo L298N. Se observará un ciclo de tres velocidades diferentes. Usted puede probar diversos valores de velocidad, pero nunca baje el valor 55 porque un motor que no esté libre (con caja de engranajes, por ejemplo) pude quedar sin girar pero alimentado, lo que producirá una corriente elevada.

Diagrama de circuito del módulo

Diagrama de ejemplo para un robot


Arduino: Comunicación inalámbrica con NRF24L01

La función de este artículo es ofrecer una explicación sobre cómo establecer una comunicación inalámbrica entre dos placas Arduino usando el módulo transceptor NRF24L01.

La primera comunicación inalámbrica que explicaré será básica: enviar un simple mensaje de texto, tipo “Hola Mundo”, de un Arduino a otro.

A continuación podremos extender este ejemplo de comunicación al envío de comandos de texto —usando el mismo circuito y estructura de programa— para controlar un sistema cualquiera ubicado en el extremo receptor.

Más adelante ofreceré un artículo con un ejemplo de comunicación bidireccional entre placas Arduino. Un Arduino tiene conectado un potenciómetro con el que se controla un servo en el segundo Arduino. Y en el otro sentido, unos interruptores en el segundo Arduino servirán para controlar LEDs en el primero.

Módulo transceptor NRF24L01

En la imagen se observa el módulo transceptor NRF24L01. Utiliza la banda de 2,4 GHz y puede operar con velocidades de transmisión de 250 kbps hasta 2 Mbps. Si se usa en espacios abiertos y, con menor velocidad de transmisión, su alcance puede llegar hasta los 100 metros. Para mayores distancias, hasta 1000 metros, existen módulos provistos con una antena externa en lugar de una antena trazada sobre la misma placa, como se observa en la imagen.

El módulo puede usar 125 canales diferentes, lo que da la posibilidad de tener una red de 125 módems que funcionen con independencia uno de otro en un solo lugar. Cada canal puede tener hasta 6 direcciones, es decir, cada unidad puede comunicarse con hasta otras 6 unidades al mismo tiempo.

El consumo de este módulo es de alrededor de 12 mA durante la transmisión, un valor menor al de un LED encendido. El voltaje de operación del módulo es de 1,9 a 3,6V, pero lo bueno es que los demás pines toleran la lógica de 5V, por lo que podemos conectarlo sin problemas a un Arduino sin necesidad de un convertidor de niveles lógicos.

Tres de estos pines son para la comunicación SPI: MOSI, MISO y SCK, que deben conectarse a los pines de la interfaz SPI del Arduino. Se debe tener en cuenta que diferentes placas Arduino pueden tener los pines del interfaz SPI en diferentes posiciones. Los pines CSN y CE se pueden conectar a cualquier pin digital de la placa Arduino, y su función es configurar el módulo en modo de espera o activo, así como para alternar entre modo de transmisión o de comando. El último pin, IRQ, es un pin de interrupción que no es necesario utilizar.

Una vez conectados los módulos NRF24L01 a las placas Arduino, llegará el momento de escribir los programas para el transmisor, y para el receptor.

Conexionado para utilizar Arduinos Uno R3 en ambos lados de la comunicación:

Código para los Arduino

Primero debemos descargar e instalar la librería RF24.

Aquí están los dos códigos para la comunicación inalámbrica y abajo, en los archivos, hay amplias explicaciones. He puesto la mayor parte de las explicaciones dentro del programa, como comentarios.

Código del Transmisor

Código del receptor

Una vez cargados ambos programas, podemos abrir el monitor serie en el Arduino receptor y observaremos la aparición del mensaje “Hola Mundo” cada 1 segundo.






CONTROL INALÁMBRICO A DISTANCIA

Esta prueba consiste en tener un Arduino (con el programa TRANSMISOR listado más abajo) conectado a la PC a través de USB / Conexión Serie, con el Monitor Serie del IDE de Arduino abierto (Herramientas > Monitor Serie) y asignado en el COM que corresponde, y transmitiendo en forma inalámbrica los caracteres que son tipeados dentro de este Monitor.

Nota: Un defecto que tiene el Monitor Serie del IDE del Arduino es que para que se transmita un caracter, o una serie de caracteres, hay que tipearlo y pulsar ENTER (ENTRAR). Eso es incómodo para controlar un equipo remoto pulsando teclas. Por eso recomiendo utilizar un programa simple y gratuito de terminal. Quizás usted ya tenga uno. En mi caso utilizo el programa Parallax Serial Terminal (PST.EXE), que se puede bajar de aquí (Página de manual de uso).

El otro Arduino lleva grabado el programa RECEPTOR, y en ese Arduino se ha agregado un pequeño servo al diagrama estándar, como muestra la figura más abajo.

El funcionamiento será básico: pulsando los números de 1 a 0 ubicados en la hilera superior del teclado, o si lo desea y lo tiene, en el teclado numérico a la derecha. Para cada uno de estos números el servo se ubicará en 10 posiciones diferentes, separadas 20º. Desde 0 a 180º, que es el rango que tiene todo servo, y más aún estos pequeños. Los servos mayores se pueden mover 270º. La selección de acciones que corresponden a cada comando se realiza por medio de comparaciones IF en el primer programa ejemplo de RECEPTOR, y por medio de una estructura SWICH-CASE en el segundo programa ejemplo. El primero es así porque puede resultar más comprensible para los recién iniciados, y el segundo ejemplo es más simple, elegante y profesional. Puse enlaces en los nombres de las estructuras de programa que apuntan a la sección de REFERENCIA del sitio oficial de Arduino.

La elección de cuál programa RECEPTOR desea usar queda a su gusto. En realidad, es conveniente probar ambos. En lo funcional se comportarán igual.

DIAGRAMA

TRANSMISOR

RECEPTOR – Basado en elección de comandos por IF

RECEPTOR – Basado en elección de comandos por SWITCH-CASE


AQUÍ LOS ARDUINOS ARMADOS

En breve: Comunicación bidireccional simultánea con NRF24L01

Arduino: Entradas y salidas – Manipulación de puertos

NOTA: Para ver el uso de los pines del ATmega328P en Arduino recomiendo leer el artículo Arduino UNO R3 – Conectándolo al mundo exterior.

Programación avanzada de puertos

En principio, es importante recordar que los puertos de un microcontrolador de 8 bits tienen esa misma cantidad de entradas/salidas, o sea ocho líneas. Esto nos haría pensar que el ATmega328P, que posee tres puertos (B, C y D), dispone de 3 x 8 = 24 líneas de entrada/salida disponibles. Sin embargo, utilizado en un Arduino no es así, como veremos.

La mayoría de los bits de los puertos de los microcontroladores son de uso múltiple, es decir que se comportan de una forma u otra de acuerdo con su configuración. Varias líneas de puertos cumplen funciones vitales en la operación de un Arduino, funciones que no son líneas de entrada/salida de uso general.

El PORTB (puerto B) tiene ocupadas dos líneas de entrada/salida que se utilizan para conectar el cristal oscilador. Estos pines, el PORTB bit-6 y PORTB bit-7, pueden quedar libres si se configura al chip para utilizar el oscilador interno, pero esta opción no podemos utilizarla en el Arduino debido a que ya tiene su sistema basado en la velocidad de cristal de 16 MHz, además de que el cristal está soldado a esos pines en el circuito de la placa.

El PORTC tiene dos bits que no están disponibles, uno de ellos, el PORTC bit-6 se utiliza como entrada de reinicio (RESET), y el otro bit (7) no está cableado hacia el exterior del ATmega328P con cápsula PDIP que viene enchufado en el zócalo del Arduino Uno R3, porque no posee suficientes líneas disponibles en su encapsulado de 28 patas. Y cuando se trata de un chip con encapsulado de montaje superficial TQFP de 32 pines (como en el Arduino Nano y en algunos clones de Arduino Uno), las dos líneas faltantes están dedicadas al convertidor analógico digital (ADC6 y ADC7) y no son pines de entrada/salida digital.

Dos bits del PORTD, el PORTD bit-0 y el PORTD bit-1, se utilizan durante la programación del Arduino, ya que están conectados a la interfaz USB, además de ser los pines TX y RX utilizados para la comunicación serie. Estos pines se pueden utilizar para comunicación serie asincrónica hacia el exterior, y también como entradas o salidas cuando no se está grabando un programa. Pero no deben tener conexiones instaladas mientras se programa el Arduino.

En consecuencia, no se llega a disponer de la cantidad de 24 entradas/salidas que ofrecerían tres puertos de 8 bits.

El ATmega328P, como cualquier otro microcontrolador, tiene registros para cada puerto con los cuales se define si cada bit del puerto será usado como entrada o como salida, y en varios casos otra función. El ATmega328P tiene tres puertos: PORTB, PORTC y PORTD, por lo cual hay tres bancos de registros de configuración, uno para cada puerto.

Bancos y puertos de ATmega 328p
Banco 27 26 25 24 23 22 21 20
PORTB     Digital 13 Digital 12 Digital 11 Digital 10 Digital 9 Digital 8
PORTC     A5 A4 A3 A2 A1 A0
PORTD Digital 7 Digital 6 Digital 5 Digital 4 Digital 3 Digital 2 Digital 1 Digital 0
Valor 128 64 32 16 8 4 2 1

Registros

El ATmega328P tiene tres registros de 8 bits con los que administra estos tres puertos:

  • DDRx (donde x es B, C o D en este caso) determina si un bit es entrada (fijándolo en 0) o salida (fijándolo en 1)
  • PORTx controla si el pin está en nivel ALTO (HIGH) o BAJO (LOW). También define la existencia o no de un resistor de polarización a Vcc (pull-up, en inglés) si es una entrada.
  • PINx permite leer el estado de los pines de un puerto (solo es para lectura)

Antes de entrar de lleno a explicar el uso de los registros, veamos primero para qué podría servir este esfuerzo.

Ventajas de usar registros:

  • Cada instrucción de máquina necesita un ciclo de reloj a 16 MHz. Las funciones digitalRead() y digitalWrite() se componen cada una de ellas de varias instrucciones de máquina, lo que puede influir negativamente en aplicaciones muy dependientes del tiempo. El uso de los registros PORTx puede hacer el mismo trabajo en muchos menos ciclos de reloj.
  • Si es necesario cambiar de estado varios pines simultáneamente en lugar de ir haciéndolo de a uno con un ciclo for, que tomaría mucho tiempo, es posibles escribir directamente al registro y establecer los valores de varios pines de una sola vez.
  • Si el código está llegando al límite de memoria de programa disponible (memoria Flash), es posible usar este método para hacer que el código use menos bytes de programa.




Desventajas de usar registros:

  • El código no es fácil de entender para novatos.
  • Es mucho mas fácil cometer errores de difícil depuración. Por ejemplo con DDRD = B11111111 se pone a todos los pines, D0 a D7 como salida, inclyendo el pin D0 (RX), lo que causará que el puerto serie deje de funcionar.

En las librerías es muy recomendable usar la manipulación directa de registros, de modo de hacerlas mucho más eficientes.

Registro DDRx – Definición de pines como entrada o salida

Al utilizar los registros DDR tenemos la ventaja de que con solo una instrucción podemos declarar el pin como entrada o salida, en cambio, utilizando pinMode() necesitaríamos 8 instrucciones.

Veamos un ejemplo con el registro DDRB del PORTB:

El ejemplo de la imagen define los 4 bits bajos o menos significativos (0 a 3) como entradas, y los 4 bits altos o más significativos (4 a 7) como salidas. Veamos cómo se verían este y otros ejemplos en el programa del IDE de Arduino.

Mediante estos registros también podemos controlar las resistencias internas de pull-up que se usan, básicamente, para no dejar los pines de entrada al aire, ya que esto genera ruido eléctrico. Se puede resolver el problema de dos maneras: poner una resistencia externa de 10K a Vcc (+5V) o usar los pull-up internos del microcomputador, que polarizan de la misma forma las entradas y hacen más simple el circuito.

Para habilitar las resistencias pull-up, primero tenemos que configurar como entrada el puerto (con el bit 0), mediante registro DDRx, y luego escribir un 1 en el registro PORTx.

Es el equivalente de usar varias veces las funciones digitalRead() y digitalWrite() de Arduino. Sin embargo, con acceso directo al puerto se puede ahorrar espacio en la memoria flash, porque cada operación con funciones de leer estados de un puerto ocupa varios bytes de instrucciones, y también se puede ganar mucha velocidad, porque las funciones Arduino puede tomar más de 40 ciclos de reloj para leer o escribir un solo bit en un puerto.

Nada mejor que un ejemplo concreto para entender las instrucciones de programa. Veamos un ejemplo con Leds.

Diagrama:

En este ejemplo, durante dos segundos todos los leds encienden, durante otros dos segundos se encienden los impares, luego los pares, y durante dos más se apagan todos.

Abrimos Arduino IDE y escribimos el siguiente código:

Un segundo ejemplo que puede resultar más divertido. Enciende un led en secuencia hacia a un lado y hacia el otro. No hice más sofisticado el programa para claridad y comprensión. Se puede hacer dentro de una estructura for, por ejemplo, tomando el dato a poner el puerto de una matriz. O usando otros recursos más complicados, como desplazar el dato sobre un registro antes de ponerlo al puerto. Pero prefiero que sea didáctico y comprensible para todos.

La secuencia suelen llamarla “El auto fantástico”. Hasta se vende un dispositivo con ese efecto de luces para adornar los autos.

El programa es:

@nbsp;

Un chip de la liga mayor:

Sólo por completar la información, y dar una idea de la importancia de este tipo de ahorro de código en otros microcontroladores, voy a mostrar algunos datos de los puertos del ATMega2560, el núcleo del Arduino Mega 2560 R3 (esquemático). Un tremendo chip con nada menos que 100 pines y ONCE puertos, que van desde el PORTA al PORTL. ¡Imagínense el banco de registros que hay para manejar!

Microcontrolador ATmega2560-16AU

Placa Arduino Mega 2560 R3

Encapsulado del ATmega2560-16AU utilizado en el Mega 2560