Tutorial - Comunicación Maestro / Esclavo : Parte 5 (Comunicación I2C - Multivariable y Multi-esclavo)

Para esta experiencia, realizaremos la lectura de dos potenciómetros conectados a dos Arduinos que tendrán la función de dos nodos esclavos en una comunicación tipo I2C conectado a un Arduino que hará el papel de un maestro que hará una comunicación serial con una computadora que graficará el cambio de voltaje en el potenciómetro en tiempo real usando el Monitor Serial del Arduino IDE.

# PIN A0 : Arduino UNO del Esclavo 1 => PIN CENTRAL : Potenciómetro 1
# PIN A1 : Arduino UNO del Esclavo 1 => PIN CENTRAL : Potenciómetro 2
# PIN A0 : Arduino UNO del Esclavo 2 => PIN CENTRAL : Potenciómetro 3
# PIN A1 : Arduino UNO del Esclavo 2 => PIN CENTRAL : Potenciómetro 4
# GND : Arduino UNO del Maestro => EXTREMO : Potenciómetro 1, 2, 3 y 4 => GND : Arduino UNO del Esclavo 1 y 2
# 5V : Arduino UNO del Esclavo 1 y 2  => EXTREMO : Potenciómetro 1, 2, 3 y 4
# PIN A4 (SDA) : Arduino UNO del Maestro => A4 (SDA) : Arduino UNO del Esclavo 1 y 2
# PIN A5 (SCL) : Arduino UNO del Maestro => A5 (SCL) : Arduino UNO del Esclavo 1 y 2


El programa usado para el Esclavo es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION I2C A SERIAL MULTIVARIABLE Y MULTIESCLAVO
   (PROGRAMA PARA EL ESCLAVO)
     
   MAESTRO: Arduino UNO (1)
   ESCLAVO: Arduino UNO (2)
   ESCLAVO: Arduino UNO (3)
     
   CONEXION:
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (2) / SDA - ESCLAVO): A4 (Arduino UNO (3) / SDA - ESCLAVO)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (2) / SCL - ESCLAVO): A4 (Arduino UNO (3) / SCL - ESCLAVO)
             Potenciometro 1: Pin A0 (Arduino UNO(2) - ESCLAVO) 
             Potenciometro 2: Pin A1 (Arduino UNO(2) - ESCLAVO)
             Potenciometro 3: Pin A0 (Arduino UNO(3) - ESCLAVO) 
             Potenciometro 4: Pin A1 (Arduino UNO(3) - ESCLAVO)
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
     
   En el siguiente programa probaremos la comunicacion Maestro / Esclavo. El Maestro permite 
   la visualizacion de los datos obtenidos de leer los potenciometros que van conectados al Esclavo. 
     
   Para correr el programa se necesita la libreria Wire (Wire.h)
     
   Autor: Renato H.
   http://beetlecraft.blogspot.pe/
     
   El siguiente programa es de uso publico, cualquier modificacion o mal uso del mismo que pudiera 
   ocasionar el mal funcionamiento de la plataforma de uso de la misma no es responsabilidad del 
   autor
*/
  
#include <Wire.h>  // Libreria de manejo de red I2C
  
int POT_1, POT_2;            // Variable de almacenamiento del porcentaje del potenciometro 1 y 2
String Pmod_1, Pmod_2, data; // Variable para configuracion y envio de datos 
  
void setup() {
  Wire.begin(1);             // Unirse a la red I2C (Esclavo con direccion "1")
                             // cambiar por "2" para el segundo esclavo
  Wire.onRequest(escritura); // Registro de evento de la funcion "escritura"
  Serial.begin(9600);        // Inicio de comunicacion serial a 9600 bps
}
  
void loop() {
  POT_1 = map(analogRead(A0), 0, 1023, 0, 100); // Lee el valor del sensor (Rango de 0 a 100%)
  POT_2 = map(analogRead(A1), 0, 1023, 0, 100); // Lee el valor del sensor (Rango de 0 a 100%)

  // Visualizacion inicial de la data de los potenciometros leidos
  Serial.print("Potenciometro 1: "); Serial.print(POT_1);
  Serial.print(" :: Potenciometro 2: "); Serial.println(POT_2);

  Pmod_1 = String(POT_1, DEC); Pmod_2 = String(POT_2, DEC); // Conversion de los datos a Strings

  // Obtencion del tamano del dato convertido
  int Pmod_1_lon = Pmod_1.length(); 
  int Pmod_2_lon = Pmod_2.length();

  // NOTA: Se debe ajustar el tamano del dato de salida para que sea de 8 bytes
  while (Pmod_1_lon < 3){         // Ajuste del tamano del dato
    Pmod_1 = '0' + Pmod_1;        // Concatena un "0" adelante del dato
    Pmod_1_lon = Pmod_1.length(); // Realiza la operacion de obtencion de tamano nuevo del dato
  } 

  while (Pmod_2_lon < 3){         // Ajuste del tamano del dato
    Pmod_2 = '0' + Pmod_2;        // Concatena un "0" adelante del dato
    Pmod_2_lon = Pmod_2.length(); // Realiza la operacion de obtencion de tamano nuevo del dato
  } 

  data = Pmod_1 + ',' + Pmod_2 + ':'; // Construccion de la trama de salida
  
  Serial.print("Mensaje: "); Serial.println(data); // Visualizacion de la trama de salida
}
  
void escritura(){
  Wire.write(data.c_str()); // Envio de la trama de salida ajustada por I2C 
}
Al momento de abrir el Monitor Serial para observar como salen los datos podemos ver lo siguiente:


El programa usado para el Maestro es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION I2C A SERIAL MULTIVARIABLE Y MULTIESCLAVO
   (PROGRAMA PARA EL MAESTRO)
     
   MAESTRO: Arduino UNO (1)
   ESCLAVO: Arduino UNO (2)
   ESCLAVO: Arduino UNO (3)
     
   CONEXION:
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (2) / SDA - ESCLAVO): A4 (Arduino UNO (3) / SDA - ESCLAVO)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (2) / SCL - ESCLAVO): A4 (Arduino UNO (3) / SCL - ESCLAVO)
             Potenciometro 1: Pin A0 (Arduino UNO(2) - ESCLAVO) 
             Potenciometro 2: Pin A1 (Arduino UNO(2) - ESCLAVO)
             Potenciometro 3: Pin A0 (Arduino UNO(3) - ESCLAVO) 
             Potenciometro 4: Pin A1 (Arduino UNO(3) - ESCLAVO)
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
     
   En el siguiente programa probaremos la comunicacion Maestro / Esclavo. El Maestro permite 
   la visualizacion de los datos obtenidos de leer el potenciometro que va conectado al Esclavo.
     
   Para correr el programa se necesita la libreria Wire (Wire.h)
     
   Autor: Renato H.
   http://beetlecraft.blogspot.pe/
     
   El siguiente programa es de uso publico, cualquier modificacion o mal uso del mismo que pudiera 
   ocasionar el mal funcionamiento de la plataforma de uso de la misma no es responsabilidad del 
   autor
*/
  
#include <Wire.h> // Libreria de manejo de red I2C
  
String POT;       // Variable de almacenamiento del valor leido del potenciometro
int p;            // Variable de almacenamiento de la posicion
int pot_1, pot_2; // Variables de almacenamiento de la lectura de potenciometros

void setup(){
  Wire.begin();       // Unirse a la red I2C (Maestro)
  Serial.begin(9600); // Configuracion del puerto serial a 9600 baudios
}
  
void loop(){  
  for (int i = 1; i <= 2; i++){        // Eleccion del esclavo a leer datos
    Wire.requestFrom(i,8);             // Pedido de informacion del Esclavo 1 o 2 de 8 bytes
    while (Wire.available()){          // Verificacion que el puerto serial virtual recibe datos                                      
      POT = Wire.readStringUntil(':'); // Lectura de datos del I2C hasta encontrar ":"
      delay(10);                       // Retraso de 10 ms para manejo de flujo de datos
   
      for (int j = 0; j < POT.length(); j++){  // Lectura desde la posicion 0 del string generado
        if (POT.substring(j, j+1) == ","){     // Separa el string hasta desde la posicion 0 hasta ","
          pot_1 = POT.substring(0, j).toInt(); // Toma la palabra hasta "," y lo convierte a integer
          p = j + 1;                           // Nueva posicion de lectura de la letra p + 1
        break;                                 // Salto cuando se encuentra ","
        }
      }
      
      // Valor del potenciometro por puerto serial
      Serial.print("Esclavo: ");             
      Serial.print(i);
      Serial.print(" :: Potenciometro 1: ");       
      Serial.print(pot_1);        

      for (int j = p; j <= POT.length(); j++){ // Lectura desde la posicion p del string generado
        pot_2 = POT.substring(p, j).toInt();   // Toma la palabra hasta "line feed" y lo convierte a integer
      }
      
      // Valor del potenciometro por puerto serial
      Serial.print(" :: Potenciometro 2: ");       
      Serial.println(pot_2);
    }
  delay(500);
  }
}
Al momento de abrir el Monitor Serial para observar como salen los datos podemos ver lo siguiente:


Autor: 

2 comentarios:

  1. Maravilloso. Una preguna... Por que 10 bytes? podrias enviar 14, o 20... por ejemplo?? y en vez de ser 2 ptotenciometros que fueran 6, por ejemplo?

    ResponderEliminar
    Respuestas
    1. Justo logré notar un error en esa parte en el comentario, que ya corregí. En este caso, son 8 bytes y es para guardar un formato de correspondencia entre el maestro y el esclavo. Vas a observar que el Maestro dice "Wire.requestFrom(i,8);" que le pide al esclavo i (puede ser el 1 o el 2 o el 1000) que le mande 8 bytes. Y si puedes enviar 14 o 20, y te recomiendo que uses el algoritmo que hay en el programa para que rellenes de "0" adelante de tu dato para completar el formato de la palabra sino te podría escribir encima de un dato otro que quieras enviar y vas a tener problemas al momento de leer en el otro lado.

      Eliminar