Objetivos
Material requerido.
Modulo de radio TEA5767 | |
Un Arduino UNO o similar | |
Un display LCD, de 16×2 o LCD 20×4, I2C. |
Añadiendo un display a la radio
En la última sesión vimos como seleccionar una frecuencia determinada con el módulo de radio FM TEA5767, porque el objetivo de la sesión era básicamente quitar el miedo a los temas de radio que siempre hacen desconectar a una parte importante de oyentes.
Ya vimos que resulta muy fácil programar el modulo mediante I2C y vimos también que enviábamos información de la frecuencia sintonizada al puerto serie para no complicarnos la vida. Pero claro está, si estás leyendo esto es precisamente porque te gusta complicarte la vida y por eso queremos eliminar la siempre truculenta puerta serie y usar un display LCD de digamos 16×2 o quizás de 20×4 para mostrar la frecuencia de la radio.
Pero hete aquí que tenemos un problema, porque tanto el módulo de radio como el display LCD son I2C y esto de montar dos dispositivos I2C en el mismo bus es algo que genera múltiples consultas en la web e incontables terrores nocturnos a los novicios de Arduino.
Pero… un momento. El I2C es un bus pensado para incluir múltiples dispositivos compartiendo hilos y por tanto no tiene problema en manejar dos simples cacharritos. Por ello he querido aprovechar esta humilde sesión para mostrar un caso simple de cómo usar más de un dispositivo I2C con el mismo Arduino.
Pues estáis avisados. Vamos a ver como montamos una radio I2C junto con un display LCD i2C compartiendo el bus y sin problemas, faltaría más.
El bus I2C
Hemos hablado ya en estas páginas del bus I2C múltiples ocasiones por es un sistema de lo más cómodo de comunicar distintos dispositivos con nuestro Arduino y entre sí, pero creo que esta será la primera vez que tendremos 3 elementos conectados y así aprovechamos para ver como se hace y probar que no tiene dificultad.
Pero antes de empezar tenemos que recordar que el I2C comparte hilos de comunicación entre múltiples dispositivos a condición que cada uno de ellos tenga una dirección hexadecimal única y diferenciada del resto. Porque es precisamente el dirigir los comandos a una dirección concreta lo que nos permite compartir el bus sin que todos los nodos respondan a la vez.
En muchas ocasiones las librerías que usamos para manejar los módulos I2C suponen una dirección específica que es la que el fabricante pone por defecto a cada dispositivo. Este hecho es muy cómodo cuando solo tenemos un nodo además de nuestro Arduino porque la librería asume una dirección dada y se dirige a ella sin más.
El 90% de las veces funcionará, pero si el fabricante cambia esta dirección nos vamos a encontrar con un problema si no cambiamos la librería acorde con este cambio.
Si queremos usar varios nodos en el mismo bus (Como ahora) vamos a necesitar asegurarnos de que conocemos exactamente que direcciones tienen nuestros dispositivos para dirigirnos a ellos.
Normalmente los objetos definidos para el control de módulos I2C suponen esta dirección implícita sin necesidad que la especifiquemos (Por eso es implícita) pero siempre podemos detallar de forma explícita la dirección hexadecimal de cada módulo.
Imagínate que quieres poner 4 displays LCD que vienen por defecto con la misma dirección de fábrica. Tendremos que cambia la dirección de cada módulo para asegurarnos de que son diferentes y después tendremos que enviarles comandos con una dirección explicita, según queramos que cada uno muestre una cosa u otra.
El resumen de todo este rollo es que necesitas tener clara la dirección de cada módulo que conectes y para ello resulta muy útil un programa que ya usamos en su día: I2C scanner, que cuando lo ejecutas simplemente te da las direcciones hexadecimales de lo que hay enchufado al bus.
Por ejemplo voy a usar un display LCD 16×2 que si lo conecto me devuelve la dirección 0x3F hex y si añado (O quito el anterior y conecto este) el módulo de radio TEA5767 me devuelve también la dirección de este 0x60 hex
Modulo | Dirección hexadecimal |
Display LCD1602 | 0x3F |
Radio TEA5767 | 0x60 |
Armados ya con algunos datos de valor vamos a ver como conectamos los dos módulos al I2C con nuestro amado Arduino.
Conectando dos nodos a nuestro I2C
Como siempre nos dicen que el I2C está en los puertos analógicos A5 y A4 de nuestro Arduino Uno, pensareis naturalmente que habrá que usar una protoboard externa para compartir los hilos, pero mira por donde, no. Si solo necesitamos dos hay truco usando más pines que nos proporciona nuestro Arduino y que tendemos a ignorar por razones poco claras. Fíjate en este esquema de pines:
Veras que rotula A5 y A4 como SCL y SDA para el I2C, pero quizás no te hayas fijado que hay otros dos pines con el mismo rótulo (Están conectados internamente) en la línea superior a la izquierda del pin D13 con los mismos rótulos y que normalmente hacemos como que no existen.
Por tanto, y por pura vagancia, vamos a usar estos pines para conecta el display LCD. Los que vienen a por nota se darán cuenta de que también hay que alimentar el display pero solo hay un pin de 5V en un Arduino UNO y necesitamos dos.
¿Tendremos después de todo que usar una protoboard? Pues va a ser que no. Al menos en mi caso, porque como estoy usando USB para alimentar mi Arduino puedo emplear el pin Vin que como corresponde a la tensión de entrada del USB estará en los 5V que necesitamos.
Veamos cómo podemos cablear la conexión del display y la radio a nuestro Arduino:
El programa de control
En la última sesión ya hablamos del programa para controlar la radio FM y partiendo de él, bastara con añadir unas líneas para incluir la gestión del display LCD.
Así pues, empecemos por los includes necesarios para el manejo de todo. Descárgate esta librería para el display LiquidCrystal_I2C-master y la añadimos a la cabecera:
#include <Wire.h> #include <radio.h> #include <TEA5767.h> #include <LiquidCrystal_I2C.h>
Lo siguiente es definir la FM y frecuencia:
#define FIX_BAND RADIO_BAND_FM // Sintonizamos FM #define FIX_STATION 8950 // Los 40 de Bilbao 89.50 Mhz // #define FIX_STATION 8850 // Cadena dial // #define FIX_STATION 10370 // Cadena 100 //#define FIX_STATION 10790 // Hit FM
En cada sitio tendréis listas de frecuencia diferentes y bastará con una búsqueda rápida en Google para saber que emisoras tienes a tiro en tu área. Vamos a crear una instancia de los objetos de radio y LCD:
TEA5767 radio; // Creamos una instancia de radio LiquidCrystal_I2C lcd( 0x3F, 20, 4); // Asignamos la dirección 0x3F al display
No hemos cambiado la primera línea con respecto al programa anterior, pero ¿Por qué no ponemos su dirección 0x60? Simplemente porque la librería asume esa dirección por defecto para el objeto radio.
#define TEA5767_ADR 0x60 // I2C address of TEA5767
La función setup() cambia poco:
void setup() { radio.init(); // Inicializar el objeto radio lcd.init(); // initialize the lcd radio.setBandFrequency(FIX_BAND, FIX_STATION); radio.setVolume(2); radio.setMono(false); }
Simplemente hemos eliminado las líneas para asignar la puerta serie (Usaremos el display en su lugar) y hemos añadido una línea para iniciar el LCD: lcd.init()
Y el loop() no es mucho más complicado, recogemos la frecuencia seleccionada en el chip de radio:
char s[12]; radio.formatFrequency(s, sizeof(s));
Y pasamos directamente a la gestión del display
lcd.backlight(); lcd.setCursor(3,0); lcd.print("Emisora: "); lcd.setCursor(2,1); lcd.print(s);
La primera línea enciende la luz de fondo, La segunda coloca el cursor en la primera línea y escribe emisora y la siguientes instrucciones saltan a la 2ª línea e imprime el valor de frecuencia.
Bastará ahora con ir volcando diferentes emisoras por programa (porque por ahora no hemos implementado ningún mecanismo para seleccionar diferentes emisoras)
Simplemente podemos ir desocmentando la frecuencia deseada y recompilar el programa para enviárselo a nuestro venerable Arduino UNO.
Evidentemente esto no es la situación ideal y en la próxima sesión montaremos un sistema para cambiar de emisora , quizás con un rotary encoder
De momento aquí tenéis un mini video con el resultado: