I2C
Inter-integrated comunication; eso es lo que significa I2C, un sistema inventado por Philips allá por los 80, pensaron en crear dispositivos sencillos que tuvieran una tarea concreta y desarrollasen un trabajo específico, y diese como resultado un valor, un evento, o acción.
Aquella idea dio el protocolo I2C que han adoptado muchos fabricantes, y hoy en día hay infinidad de dispositivos I2C.
En este ejercicio vamos probar 2 pantallas I2C, y un sistema de reloj basado en un circuito I2C DS3231.
SDA y SCL
Los pines SDA y SCL, son especiales en arduino y están situados en los pines analógicos 4 (SDA) y 5(SCL), estos pines se utilizan como bus de datos. No alcanzan mucha longitud, pero se pueden poner repetidores, pero lo que es para un proyecto en una caja es más que suficiente.
Aquí podemos ver la explicación de wikipedia
Conexionado I2C
El conexionado es muy sencillo, se utilizan 2 cables más los de alimentación.
Todos los dispositivos se conectan al bus del canal de datos por donde mandan la información, y en función a la dirección que va dirigida responde un dispositivo u otro.
Vamos a la gestión de librerías y aquí añadimos una librería a modo de ejemplo “i2cdetect”, que nos indica las direcciones de los dispositivos I2C conectados al bus de datos.
Normalmente las direcciones físicas nos las puede proporcionar el fabricante, pero puede haber diferencias entre modelos, o fabricantes del mismo tipo, o cualquier motivo por el que nuestra dirección no sea conocida, vamos a dar la solución.
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — 3c — — 3f
40: — — — — — — — — — — — — — — — —
50: — — — — — — — 57 — — — — — — — —
60: — — — — — — — — 68 — — — — — — —
70: — — — — — — — —
Nos instalamos la librería I2Cdetect y buscamos el ejemplo I2Cdetect.
Veamos el código de ejemplo para nuestro reloj
Vamos a usar la librería de arduino RTC_BY_Makuna.
Es una librería que se puede descargar del repositorio oficial.
Podemos descargar el archivo ejemplo o copiar este (una vez descargada la librería).
// CONNECTIONS: // DS3231 SDA --> SDA // DS3231 SCL --> SCL // DS3231 VCC --> 3.3v or 5v // DS3231 GND --> GND #include <Wire.h> // must be incuded here so that Arduino library object file references work #include <RtcDS3231.h> RtcDS3231 Rtc; void setup () { Serial.begin(9600); Serial.print("Tiempo de compilación: "); Serial.print(__DATE__); Serial.println(__TIME__); //--------RTC SETUP ------------ Rtc.Begin(); RtcDateTime compilado = RtcDateTime(__DATE__, __TIME__); printDateTime(compilado); Serial.println(); if (!Rtc.IsDateTimeValid()) { Serial.println("RTC sin hora correcta"); Rtc.SetDateTime(compilado); } if (!Rtc.GetIsRunning()) { Serial.println("RTC no está activado"); Rtc.SetIsRunning(true); } RtcDateTime ahora = Rtc.GetDateTime(); if (ahora < compilado) { Serial.println("RTC fuera de hora (actualizando)"); Rtc.SetDateTime(compilado); } else if (ahora > compilado) { Serial.println("RTC El tiempo es mas tarde que el compilado (lo esperado)"); } Rtc.Enable32kHzPin(false); Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); } void loop () { if (!Rtc.IsDateTimeValid()) { Serial.println("RTC Perdida de la hora, cambie la batería"); } RtcDateTime ahora = Rtc.GetDateTime(); printDateTime(ahora); Serial.println(); RtcTemperature temp = Rtc.GetTemperature(); Serial.print(temp.AsFloat()); Serial.println("C"); delay(1000); // cada segundo } #define countof(a) (sizeof(a) / sizeof(a[0])) void printDateTime(const RtcDateTime & dt) { char datestring[20]; snprintf_P(datestring, countof(datestring), PSTR("%02u/%02u/%04u %02u:%02u:%02u"), dt.Month(), dt.Day(), dt.Year(), dt.Hour(), dt.Minute(), dt.Second() ); Serial.print(datestring); }
Problemas con los ESP8266 Wemos
Los dispositivos ESP8266 también disponen de I²C pero hay que indicar los pines que son usados para las comunicaciones SDA y SCL y hay que hacer una pequeña modificación en el programa I2cdetect para que nos funcione en nuestro dispositivo
En la llamada de inicialización del dispositivo I²C wire.begin() hay que añadir que pines estamos usando como SDA y SCL
Incluimos unos defines donde indicamos cuales son los pines de SDA y SCL
#define SDA D1
#define SCL D2
<br data-mce-bogus="1"> #include <Wire.h> #include <i2cdetect.h> #define SDA D1 #define SCL D2 void setup() { Wire.begin(SDA,SCL); Serial.begin(9600); Serial.println("i2cdetect example\n"); Serial.print("Scanning address range 0x03-0x77\n\n"); } void loop() { i2cdetect(); // default range from 0x03 to 0x77 delay(2000); }
Con esto ya veríamos si nuestros dispositivos están bien conectados y recibiendo / enviando información.
La diferencia entre el I2C de Arduino y el de un ESP8266 es que para el ESP8266 hay que indicar que pines van a ser utilizados.
Con esto podemos modificar las librerías de arduino que por defecto no tienen ésta opción habilitada.
Veamos un ejemplo.
Vamos a actualizar la librería de RTC by Makuna usada anteriormente.
(usuario/librerías) depende si eres windows o linux
1º Localizar la librería #include <RtcDS3231.h>
2º Buscar donde nos indica el “wire.begin()”;
void Begin()
{
_wire.begin();
}
3º Sobrecargamos el método Begin () y añadimos uno nuevo
void Begin(int sda,int scl)
{
_wire.begin(sda,scl);
}
Guardamos nuestro nuevo fichero con la función sobrecargada.
4º Ahora en nuestro programa ya podemos hacer la llamada
void setup () { Serial.begin(57600); Serial.print("compiled: "); Serial.print(__DATE__); Serial.println(__TIME__); //--------RTC SETUP ------------ Rtc.Begin(SDA,SCL);