Reintentos y confirmación de envío

Detecta cuándo un envío I2C falla y reintenta automáticamente, con un número máximo de intentos.

Qué vas a construir

Un maestro que envía un valor a un esclavo y verifica si llegó. Si no llega, reintenta hasta tres veces. Vas a provocar un fallo a propósito para verlo funcionar.

Lo que aprendes

  • Qué significa confirmar un envío (ACK).
  • Por qué un mensaje puede fallar sin que nadie lo avise.
  • Cómo leer el resultado de endTransmission().
  • Cómo limitar los reintentos para no quedar atrapado en un bucle.

Idea clave

En una red, enviar no garantiza que el otro lado reciba. El protocolo tiene que decir cómo saberlo. En I2C, el esclavo confirma cada byte con un ACK. Si el maestro no recibe la confirmación, endTransmission() devuelve un código de error. El maestro puede entonces reintentar.

Los valores que devuelve endTransmission():

  • 0: envío correcto.
  • 2: no hubo respuesta del esclavo en esa dirección.
  • Otro valor: error de datos o de bus.

Materiales en Tinkercad

  • Dos Arduino Uno R3, conectados como en Comunicación I2C entre dos Arduinos
  • Cables

Paso 1: Código del esclavo

Usa el mismo esclavo de Comunicación I2C entre dos Arduinos:

#include <Wire.h>

void setup() {
  Wire.begin(8);
  Wire.onReceive(recibir);
  Serial.begin(9600);
}

void recibir(int cantidad) {
  while (Wire.available()) {
    Serial.print("Recibido: ");
    Serial.println(Wire.read());
  }
}

void loop() {}

Paso 2: Código del maestro con reintentos

#include <Wire.h>

bool enviar(int valor) {
  for (int intento = 1; intento <= 3; intento++) {
    Wire.beginTransmission(8);
    Wire.write(valor);
    int resultado = Wire.endTransmission();

    if (resultado == 0) {
      Serial.print("Enviado en intento ");
      Serial.println(intento);
      return true;
    }

    Serial.print("Fallo en intento ");
    Serial.print(intento);
    Serial.print(", codigo ");
    Serial.println(resultado);
    delay(50);
  }
  return false;                  // se agotaron los reintentos
}

void setup() {
  Wire.begin();
  Serial.begin(9600);
}

void loop() {
  if (!enviar(25)) {
    Serial.println("No se pudo enviar el dato");
  }
  delay(2000);
}

Paso 3: Provoca un fallo

  1. Inicia la simulación con el circuito completo. Debe mostrar “Enviado en intento 1”.
  2. Detén la simulación y quita el cable de SDA del esclavo.
  3. Inicia de nuevo. El maestro debe mostrar fallos y, al final, “No se pudo enviar el dato”.
  4. Vuelve a conectar el cable y comprueba que el envío se recupera.

Cómo sabes que lo lograste

  • Con el circuito completo, el envío funciona en el primer intento.
  • Con el cable desconectado, el maestro reintenta tres veces y luego informa el error.
  • Puedes explicar qué significa el código 2 de endTransmission().

Qué salió mal

El maestro reintenta sin parar. Revisa que el bucle use intento <= 3 y que return false esté fuera del if.

El fallo no aparece aunque quitas el cable. En Tinkercad, la simulación puede mantener el último estado. Detén la simulación antes de cambiar el circuito y vuelve a iniciarla.

Siguiente clase

En la siguiente clase vas a juntar todo en una red de dos sensores con pantalla, alerta y pruebas documentadas.