Escaner I2C para Arduino.

En el proyecto de Pecepececitos me encontré con que las 2 pantallas LCD de 4x20 y el reloj RTC que tenia pensado instalar usaban el protocolo I2C, pines SDA (línea de datos) y SCL (reloj de sincronización), por suerte este protoclo permite comunicarse con hasta 128 componentes mediante esos dos pines, únicamente.
El uso de tan solo 2 pines para poder comunicar con hasta 128 componentes obliga a tener que identificarlos correctamente para evitar errores inesperados. Me refiero que no tendría sentido alguno indicar al microcontrolador que en la dirección de lo que pretendemos sea el reloj RTC realmente esté una de las pantallas. Con esto estaríamos indicando a la librería del reloj RTC que solicite la hora a una de las pantallas con lo que provocaríamos un error ya que no obtendríamos la respuesta esperada.

Bus I2C en placas arduino

Placa Pines I2C / TWI
Uno, Ethernet A4 (SDA), A5 (SCL)
Mega2560 20 (SDA), 21 (SCL)
Leonardo 2 (SDA), 3 (SCL)
Due 20 (SDA), 21 (SCL), SDA1, SCL1

Pasemos a revisar el código:

Codigo Escaner I2C

//
// Escaner I2C
//
// Versión 1
// Este programa (o código que lo parece)
// puede encontrarse en diferentes sitios.
// Por ejemplo en el foro de Arduino.cc.
// El autor original no se conoce.
// Versión 2, Juni 2012, Using Arduino 1.0.1
// Simplificación de código realizada por Krodal en Arduino.cc.
// Cambios de louarnold eliminados.
// Escaneo de dirección modificado de 0...127 a 1...119,
// según i2c scanner por Nick Gammon
// http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
// Como la versión 4, pero direcciones escaneadas ahora a 127.
// Un sensor parece usar dirección 120.
// Version 6, November 27, 2015.
// Se añadió espera para inicio de puerto Serial en Leonardo.
// Versión 6.1, Febrero 15, 2017.
//    Se traduce al español por Deudei.es (Eduardo de Vicente). 
//    Se agregan comentarios explicativos del código fuente.
//
// Este Sketch comprueba direcciones estandar de 7-bits
//

#include <Wire.h>         // Cargamos librería I2C.

void setup(){
  Wire.begin();              // Iniciamos librería bus I2C.
  Serial.begin(9600);        // Iniciamos el puerto serie.
  while (!Serial);               // Leonardo: esperando a monitor serie.
  Serial.println("Escaner I2C"); // Saludamos por monitor serie.
}

void loop(){
  byte error, direccion;   // definimos variables para direcciones.
  int nComponentes;    // Variable almacen de numero de componentes encontrados.

  Serial.println("Escaneando...");  // Iniciamos escáner.

  nComponentes = 0;     // Ponemos el contador de componentes a cero.
  for(direccion = 1; direccion < 127; direccion++ ){  // Recorremos direcciones.
    
    //
    // El escaner usa el valor retornado de
    // Write.endTransmisstion para ver si
    // algún componente se reconoció en dicha dirección.
    //
    Wire.beginTransmission(direccion);  // Se trata de transmitir en la dirección.
    error = Wire.endTransmission(); // Guardamos la respuesta.

    if (error == 0){    // Si no hay error.
      Serial.print("Componente I2C encontrado en la dirección 0x"); // Avisamos por puerto serie.
      
    if (direccion < 16)  // Mostramos dirección por puerto serie.
            Serial.print("0");
            Serial.print(direccion,HEX);
        Serial.println("  !");

        nComponentes++;     // Suma 1 al almacén de componentes
    } else if (error==4) {  // Si hay error.
      Serial.print("Error desconocido en la dirección 0x");// Avisamos por puerto serie.
      if (direccion<16)  // Mostramos dirección por puerto serie.
        Serial.print("0");
        Serial.println(direccion,HEX);
    }    
  }
  if (nComponentes == 0)    // Si no se encuentran componentes en el bus I2C
    Serial.println("No se encontraron componentes I2C \n");
  else              // Si se encuentran componentes en el bus I2C
    Serial.println("Hecho \n");

  delay(5000);           // esperamos 5 segundos para re-escanear

}

Espero que os sea de utilidad.

Comentarios del artículo

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *