Tutorial - Comunicación serial e I2C a la vez (Tercera parte - 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 Processing.

# 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 Maestro => EXTREMO : Potenciómetro 1, 2, 3 y 4 => 5V : Arduino UNO del Esclavo 1 y 2
# 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 ","
        }
      }
      String pot_1_mod = String(pot_1); // Conversion del dato en string para enviar el mensaje
      
      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
      }
      String pot_2_mod = String(pot_2); // Conversion del dato en string para enviar el mensaje

      if (i == 1){                      // Discriminacion del esclavo 1
        String cabecera = String("A,"); // Creacion de la cabecera
        String mensaje = cabecera + pot_1_mod + ',' + pot_2_mod + ','; // Construccion del mensaje de salida
        Serial.print(mensaje); Serial.println(); // Envio del mensaje del esclavo 1
      }
      
      if (i == 2){                      // Discriminacion del esclavo 2
        String cabecera = String("B,"); // Creacion de la cabecera
        String mensaje = cabecera + pot_1_mod + ',' + pot_2_mod + ','; // Construccion del mensaje de salida 
        Serial.print(mensaje); Serial.println(); // Envio del mensaje del esclavo 2
      }      
    }
  delay(100);
  }
}
Al momento de abrir el Monitor Serial para observar como salen los datos podemos ver lo siguiente:


El programa usado para Processing es el siguiente:
/* 
   PROGRAMA DE PRUEBA DE COMUNICACION SERIAL CON MULTIVARIABLE Y MULTIESCLAVO
   
   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
             
   El siguiente programa nos ayuda a realizar la lectura del voltaje de 2 potenciometro y mostrarlo por
   puerto serial.
   
   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
*/

import processing.serial.*; // Inicio de la comunicación serial

Serial puerto;                  // Crea el puerto serial
char cab_1 = 'A', cab_2 = 'B';  // Cabecera de inicio de mensaje del esclavo 1 y 2
short LF = 10;                  // ASCII linefeed
int POT_1, POT_2, POT_3, POT_4; // Variables de almacenamiento del potenciometro del esclavo 1 y 2
String mensaje;                 // Mensaje leido

void setup() {
  size(100, 350); // Tamaño de la pantalla
  
  // println(Serial.list());
  String ArduinoPuerto = Serial.list()[0];        // Encuentra el primer puerto serial para iniciar la comunicacion
  puerto = new Serial(this, ArduinoPuerto, 9600); // Inicio de la comunicacion con el primer puerto encontrado
}

void draw() {
  mensaje = puerto.readStringUntil(LF); // Lee todo el mensaje hasta encontrar el linefeed
  
  if (mensaje != null) { // Si el dato no es null
    
    // Muestra en pantalla del mensaje original
    print("Mensaje original: ");
    println(mensaje);
    
    lectura(); // Rutina de lectura de potenciometros
  }
  
  background(167);         // Rellena el espacio de trabajo de color plomo
  fill(0);                 // Llena el espacio del rectangulo dibujado en negro
  rect(0, 0, POT_1, 50);   // Dibujo del rectangulo 1
  rect(0, 100, POT_2, 50); // Dibujo del rectangulo 2
  rect(0, 200, POT_3, 50); // Dibujo del rectangulo 3
  rect(0, 300, POT_4, 50); // Dibujo del rectangulo 4
}

void lectura(){ // Rutina de lectura de potenciometros
  String [] data = mensaje.split(","); // Division del mensaje a partir de la coma ","
    
  if (data[0].charAt(0) == cab_1 && data.length > 3){ // Verifica la cabecera y el tamaño del dato
     
    // Lectura de los datos divididos
    for (int i = 1; i < data.length - 1; i++){
      
      // Escritura de los datos por puerto serial
      print("Esclavo: 1 ");
      println("Valor potenciometro " + i + ": " + data[i]); 
       
      POT_1 = Integer.parseInt(data[1]); // Conversion del dato 1 del String a Integer 
      POT_2 = Integer.parseInt(data[2]); // Convserion del dato 2 del String a Integer 
    }
    println(); // Espacio de division para el siguiente mensaje
  } 
  
  if (data[0].charAt(0) == cab_2 && data.length > 3){ // Verifica la cabecera y el tamaño del dato
     
    // Lectura de los datos divididos
    for (int i = 1; i < data.length - 1; i++){
      
      // Escritura de los puertos por puerto serial
      print("Esclavo: 2 ");
      println("Valor potenciometro " + i + ": " + data[i]); 
       
      POT_3 = Integer.parseInt(data[1]); // Conversion del dato 1 del String a Integer 
      POT_4 = Integer.parseInt(data[2]); // Convserion del dato 2 del String a Integer 
    }
    println(); // Espacio de division para el siguiente mensaje
  }  
}
El resultado es el siguiente:




Autor: 

No hay comentarios:

Publicar un comentario