Prototipos - Robots boxeadores

PROTOTYPE THIS! o PROTOTIPOS en latinoamérica fue una serie de una sola temporada que "buscaba la viabilidad de realizar prototipos de máquinas y productos en dos semanas"; conformado por un grupo de 4 personas con un arsenal de personas apoyándolos atrás, dependiendo del proyecto. Desarrollaban inventos desde robots gigantes boxeadores hasta simuladores de toboganes de agua en "Treasure Island", un taller en San Fransisco.

El grupo de inventores se componía de:

# PhD Mike North : Doctor en Ciencia de Materiales, Universidad de California - Santa Bárbara.
# Ing. Joe Grand : Ingeniero Eléctrico, Universidad de Boston. Hardware Hacker y más conocido como "Kingpin"
# PhD Adrew "Zoz" Brooks : Licenciado en Química Orgánica y Ciencias de la Computación, Universidad de Adelaida. Magister en Educación con mención en robótica, Universidad Nacional de Australia. PhD del Insituto Tecnológico de Massachusetts (MIT). Software Hacker.
# Terry Sandin : Especialista en efectos especiales, Hollywood.


En este episodio fabricarán robots boxeadores gigantes para simular las peleas de robots en el futuro.

PARTE 1:

PARTE 2: 

PARTE 3:
  
Autor: 

Prototipos - Entrega automatizada de pizzas

PROTOTYPE THIS! o PROTOTIPOS en latinoamérica fue una serie de una sola temporada que "buscaba la viabilidad de realizar prototipos de máquinas y productos en dos semanas"; conformado por un grupo de 4 personas con un arsenal de personas apoyándolos atrás, dependiendo del proyecto. Desarrollaban inventos desde robots gigantes boxeadores hasta simuladores de toboganes de agua en "Treasure Island", un taller en San Fransisco.

El grupo de inventores se componía de:

# PhD Mike North : Doctor en Ciencia de Materiales, Universidad de California - Santa Bárbara.
# Ing. Joe Grand : Ingeniero Eléctrico, Universidad de Boston. Hardware Hacker y más conocido como "Kingpin"
# PhD Adrew "Zoz" Brooks : Licenciado en Química Orgánica y Ciencias de la Computación, Universidad de Adelaida. Magister en Educación con mención en robótica, Universidad Nacional de Australia. PhD del Insituto Tecnológico de Massachusetts (MIT). Software Hacker.
# Terry Sandin : Especialista en efectos especiales, Hollywood.


En este episodio prueban robots móviles con sistemas de navegación automática. Como un dato adicional, en este episodio se muestra a uno de los pioneros del auto autónomo de Google.

PARTE 1:

PARTE 2: 

PARTE 3:
  
Autor: 

Tutorial - Servomotores analógicos y digitales

TEORÍA DE SERVOMOTORES
Los servomotores son actuadores rotativos o lineales que permiten el control preciso ya sea del ángulo o la posición lineal, velocidad y aceleración. Su construcción básica comprende de un motor con un sensor de posición acoplado al mismo, que sirve como retroalimentación; todo el conjunto es manejado por un controlador o un módulo dedicado para realizar la tarea.
El término Servo es generalmente usado para todo aquel motor que posea un sistema de control de lazo cerrado.

Algunas de las aplicaciones de los mismos se pueden ver en:
# Robótica.
# Maquinaria CNC.
# Manufactura automatizada.

Las partes que construyen un servo motor se pueden dividir en tres:
# ENCODERS : Sirven como retroalimentación, pueden ser construidos tanto por discos ranurados o dentados, potenciómetros o encoders rotativos absolutos o incrementales.
# MOTORES : Generalmente son usados los motores DC que pueden ser controlados con Mosfets para usos de baja potencia y motores AC con variadores de frecuencia para usos industriales.
# CONTROL : Dependiendo de la aplicación y resolución, existen controladores basados en circuitos dedicados o hechos a partir de microcontroladores.


SERVOS ANALÓGICOS Y DIGITALES
Los circuitos de control de servomotores son construidos generalmente a partir de un control proporcional. El ángulo o set point se ingresa por medio de una señal PWM, cuyo margen de operación de trabajo va de 1 a 2 milisegundos. Para determinar el ángulo para la mayoría de servos, se usa la fórmula "t = 1 + ángulo/180" siendo el tiempo en microsegundos y el ángulo en grados.

La cantidad de microsegundos en comparación del ángulo, se puede ver en la siguiente figura:


A diferencia de los servos analógicos, los digitales cuentan con la siguientes ventajas:
# Mayor torque.
# Mayor precisión.
# Tiempo de respuesta menor.
# Posibilidad de cambiar los valores de ángulos mínimo y máximo.

Pero sus desventajas son:
# Mayor costo.
# Mayor consumo de energía.

Todos los servos ya sean digitales o analógicos tienen la misma disposición de pines que en su mayoría son tres:
# Cable negro o marrón : GND.
# Cable rojo : Alimentación de voltaje.
# Cable blanco, amarillo o naranja : Entrada de señal PWM

LIBRERÍA "SERVO"
Esta librería permite que la plataforma Arduino controle servomotores. Los servomotores usualmente van de los 0 a los 180 grados. Esta librería permite trabajar hasta con 12 servomotores en la mayoría de plataformas y 48 en caso del Arduino Mega.

En caso de usar un Arduino UNO o similares, al usar 12 motores la utilización de la función analogWrite() de los pines 9 y 10 son desabilitadas. Para el caso del Arduino Mega al usar más de 12 motores, la utilización de la función analogWrite() de los pines 11 y 12 son desabilitados.

Algunas de las funciones de la librería se explican a continuación:
# Servo nombre : Asigna al nombre las facultades de las funciones de la librería Servo.
# nombre.attach(pin) o nombre.attach(pin, min, max) : Configura la plataforma para el uso del servo para un pin específico. En caso de usar valores máximos y mínimos consideramos lo siguiente:
   * MIN : Es el valor correspondiente en microsegundos a los 0 grados de ángulo (Por defecto es 544).
   * MAX : Es el valor correspondiente en microsegundos a los 180 grados de ángulo (Por defecto es 2400).

# nombre.write(ángulo) : Asigna el valor del ángulo deseado para el servo que puede ir de 0 a 180.
# nombre.writeMicroseconds(microsegundos) : Asgina el valor del ángulo deseado para el servo a partir de los microsegundos como valor "integer" sin decimales. En servos estándar 1000 microsegundos es el extremo antihorario, 1500 microsegundos el medio y 2000 microsegundos es el extremo horario. Fuera de lo escrito, los valores pueden cambiar de fabricante en fabricante y generalmente se encuentran en el rando de los 700 a los 2300 microsegundos.
# nombre.read() : Retorna el último ángulo del servo escrito por la función write(). Nos devuelve un dato "integer" de 0 a 180.
# nombre.attached() : Retorna "true" si el servo está asignado al pin y "falso" en el caso contrario.
# nombre.detach() : Desliga al servo asignado "nombre" del pin. Esto es bueno en caso de querer usar los pines 9 y 10 con las funciones analogWrite().

SERVO ANALÓGICO: TOWER PRO SG90
Uno de los servos de mayor uso comercial de bajo coste son los "Tower Pro SG90".



Sus características principales son las siguientes:
# Torque : 1.8 kg - cm.
# Voltaje : 4.8 a 6 V.
# Posiciones : "0" (1.5 ms), "90" (2 ms) y "-90" (1 ms).
# Ciclo de trabajo : 1 a 2 ms.
# Periodo PWM : 20 ms.
# Disposición de cables : Naranja (Señal PWM), Rojo (VCC) y Marrón (GND).
# Engranes : Nylon

SERVO DIGITAL: LS 0009AF
Un servo digital comercial es el "LS 0009AF", puedes también bajar su "datasheet".



Sus características principales son las siguientes:
# Torque : 1.3 a 1.5 kg - cm.
# Voltaje : 4.8 a 6 V.
# Consumo : 120 a 150 mA. 
# Posiciones : "0" (1.5 ms), "90" (2 ms) y "-90" (1 ms).
# Ciclo de trabajo : 1 a 2 ms
# Periodo PWM : 800 a 2200 microsegundos.
# Disposición de cables : Amarillo (Señal PWM), Rojo (VCC) y Marrón (GND).
# Engranes : Metálicos

PRUEBAS DE PROGRAMACIÓN CON SERVOS Y ALGUNOS TRUCOS
La conexión para las pruebas es la siguiente:

# PIN 11 : Arduino UNO => SEÑAL : Servomotor (Cable naranja o amarillo)
# GND : Arduino UNO  => VCC : Servomotor (Cable rojo)
# 5V : Arduino UNO  => GND : Servomotor (Cable negro)


En este primer programa haremos una prueba introduciendo ángulos a través del Monitor Serial:
/*
   PROGRAMA DE PRUEBA DE SERVOS: SERVOS ANALOGICOS

   CONEXION:
             PWM: Pin 11 del Arduino UNO
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la posicon angular de un servo por medio de escritura de su 
   angulo por monitor serial. El angulo inicial es 0 grados.
   
   NOTA: Para el siguiente programa necesitamos la libreria "Servo.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 <Servo.h> // Libreria de manejo de servos

Servo servo_prueba;        // Nombre asignado al servo
const int salida_pwm = 11; // Variable para configuracion del pin de salida de senal PWM
int angulo;                // Variable de almacenamiento del angulo ingresado por Monitor Serial

void setup() {
  Serial.begin(9600);              // Configuracion del puerto serial de comunicacion con la PC
  servo_prueba.attach(salida_pwm); // Configuracion del pin de salida de la senal PWM
  servo_prueba.write(0);           // Angulo inicial 
  
  // Mensaje inicial en el monitor serial
  Serial.println("Escribir la posicion de angulo de 0 a 180: ");
}

void loop() {
  if (Serial.available()) {    // Verificacion que el puerto serial recibe datos                                  
   delay(10);               
   angulo = Serial.parseInt(); // Lee solo los datos tipo int del buffer
   servo_prueba.write(angulo); // Escritura de microsegundos ingresado por Monitor Serial
   
   // Mensaje de confirmacion del angulo ingresado por Monitor Serial
   Serial.print("Posicion angular: "); 
   Serial.print(angulo);
   Serial.println(" grados");
   
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer del puerto serial
  }
}
Podemos ver como cambia la posición introduciendo el ángulo.
# -90° que corresponde a la posición 0.
# 0° que corresponde a la posición 90.
#  90° que corresponde a la posición 180.




De la misma manera, podemos obtener el mismo resultado a través de la escritura de microsegundos. Como sabemos nuestro rango va de los 1000 us a los 2000 us según las especificaciones del fabricante.
/*
   PROGRAMA DE PRUEBA DE SERVOS: SERVOS ANALOGICOS

   CONEXION:
             PWM: Pin 11 del Arduino UNO
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la posicon angular de un servo por medio de escritura de su 
   posicion angular en microsegundos por monitor serial. El angulo inicial es 0 grados o 1000 us.
   
   NOTA: Para el siguiente programa necesitamos la libreria "Servo.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 <Servo.h> // Libreria de manejo de servos

Servo servo_prueba;        // Nombre asignado al servo
const int salida_pwm = 11; // Variable para configuracion del pin de salida de senal PWM
int usegundos;             // Variable de almacenamiento del microsegundo ingresado por Monitor Serial
float angulo;              // Variable para calculo del angulo a partir de microsegundos

void setup() {
  Serial.begin(9600);                   // Configuracion del puerto serial de comunicacion con la PC
  servo_prueba.attach(salida_pwm);      // Configuracion del pin de salida de la senal PWM
  servo_prueba.writeMicroseconds(1000); // Posicion angular inicial de 1000 us
 
  // Mensaje inicial en el monitor serial
  Serial.println("Escribir la posicion angular en microsegundos de 1000 a 2000: ");
}

void loop() {
  if (Serial.available()) {       // Verificacion que el puerto serial recibe datos                                  
   delay(10);               
   usegundos = Serial.parseInt(); // Lee solo los datos tipo int del buffer
   servo_prueba.writeMicroseconds(usegundos); // Escritura del angulo ingresado por Monitor Serial
   
   // angulo por interpolacion 
   // angulo = 0 + (usegundos - 1000)*(180 - 0)/(2000 - 1000);
   angulo = 0 + (usegundos - 1000) * 0.18;
   
   // Mensaje de confirmacion del angulo ingresado por Monitor Serial
   Serial.print("Posicion en microsegundos: "); 
   Serial.print(usegundos);
   Serial.print(" us || ");
   Serial.print("Posicion angular: ");
   Serial.print(angulo,0);
   Serial.println(" grados");
   
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer
  }
}
Ahora probamos tres diferentes posiciones:
# 1000 us que corresponde a -90° o la posición 0.
# 1500 us que corresponde a 0° o la posición 90.
# 2000 us que corresponde a 90° o la posición 180.




Como se observa en las figuras anteriores, en comparación de usar los ángulos para el caso de los microsegundo se tiene que tener más cuidado; y es preferible hacer pruebas de ajuste para tener una mayor precisión de la posición angular (Es recomendable usar las especificaciones como referencia).

Usando el mismo programa modificado para no tener el valor del ángulo podemos ajustar el ángulo y la posición física del brazo, todo ello para tener una mayor precisión de la posición angular.
/*
   PROGRAMA DE PRUEBA DE SERVOS: SERVOS ANALOGICOS

   CONEXION:
             PWM: Pin 11 del Arduino UNO
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la posicon angular de un servo por medio de escritura de su 
   posicion angular en microsegundos por monitor serial. El angulo inicial es 0 grados o 1000 us.
   
   NOTA: Para el siguiente programa necesitamos la libreria "Servo.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 <servo .h> // Libreria de manejo de servos

Servo servo_prueba;        // Nombre asignado al servo
const int salida_pwm = 11; // Variable para configuracion del pin de salida de senal PWM
int usegundos;             // Variable de almacenamiento del microsegundo ingresado por Monitor Serial

void setup() {
  Serial.begin(9600);                   // Configuracion del puerto serial de comunicacion con la PC
  servo_prueba.attach(salida_pwm);      // Configuracion del pin de salida de la senal PWM
 
  // Mensaje inicial en el monitor serial
  Serial.println("Escribir la posicion angular en microsegundos: ");
}

void loop() {
  if (Serial.available()) {       // Verificacion que el puerto serial recibe datos                                  
   delay(10);               
   usegundos = Serial.parseInt(); // Lee solo los datos tipo int del buffer
   servo_prueba.writeMicroseconds(usegundos); // Escritura del angulo ingresado por Monitor Serial
   
   // Mensaje de confirmacion del angulo ingresado por Monitor Serial
   Serial.print("Posicion en microsegundos: "); 
   Serial.print(usegundos);
   Serial.println(" us");
   
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer
  }
}
El resultado es el siguiente:



De esa manera podemos modificar el programa anterior. De esa manera, la modificación al programa es la siguiente:
/*
   PROGRAMA DE PRUEBA DE SERVOS: SERVOS ANALOGICOS

   CONEXION:
             PWM: Pin 11 del Arduino UNO
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la posicon angular de un servo por medio de escritura de su 
   posicion angular en microsegundos por monitor serial. El angulo inicial es 0 grados o 545 us.
   
   NOTA: Para el siguiente programa necesitamos la libreria "Servo.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 <Servo.h> // Libreria de manejo de servos

Servo servo_prueba;        // Nombre asignado al servo
const int salida_pwm = 11; // Variable para configuracion del pin de salida de senal PWM
int usegundos;             // Variable de almacenamiento del microsegundo ingresado por Monitor Serial
float angulo;              // Variable para calculo del angulo a partir de microsegundos

void setup() {
  Serial.begin(9600);                   // Configuracion del puerto serial de comunicacion con la PC
  servo_prueba.attach(salida_pwm);      // Configuracion del pin de salida de la senal PWM
  servo_prueba.writeMicroseconds(545);  // Posicion angular inicial de 545 us
 
  // Mensaje inicial en el monitor serial
  Serial.println("Escribir la posicion angular en microsegundos de 545 a 2250: ");
}

void loop() {
  if (Serial.available()) {       // Verificacion que el puerto serial recibe datos                                  
   delay(10);               
   usegundos = Serial.parseInt(); // Lee solo los datos tipo int del buffer
   servo_prueba.writeMicroseconds(usegundos); // Escritura del angulo ingresado por Monitor Serial
   
   // angulo por interpolacion 
   // angulo = 0 + (usegundos - 545)*(180 - 0)/(2250 - 545);
   angulo = (usegundos - 545) * 0.1056;
   
   // Mensaje de confirmacion del angulo ingresado por Monitor Serial
   Serial.print("Posicion en microsegundos: "); 
   Serial.print(usegundos);
   Serial.print(" us || ");
   Serial.print("Posicion angular: ");
   Serial.print(angulo,0);
   Serial.println(" grados");
   
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer
  }
}
El resultado en el Monitor Serial es el siguiente:


A partir de lo que sabemos ahora, podemos combinar las dos aproximaciones y usarlos en parametrizar el servo usando la función "nombre_servo.attach(pin, min, max)". De esta manera, el programa inicial se puede modificar y quedaría de la siguiente manera:
/*
   PROGRAMA DE PRUEBA DE SERVOS: SERVOS ANALOGICOS

   CONEXION:
             PWM: Pin 11 del Arduino UNO
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la posicon angular de un servo por medio de escritura de su 
   angulo por monitor serial. El angulo inicial es 0 grados.
   
   NOTA: Para el siguiente programa necesitamos la libreria "Servo.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 <Servo.h> // Libreria de manejo de servos

Servo servo_prueba;        // Nombre asignado al servo
const int salida_pwm = 11; // Variable para configuracion del pin de salida de senal PWM
int angulo;                // Variable de almacenamiento del angulo ingresado por Monitor Serial

void setup() {
  Serial.begin(9600); // Configuracion del puerto serial de comunicacion con la PC
  servo_prueba.attach(salida_pwm, 545, 2250); // Configuracion del pin de salida de la senal PWM
  servo_prueba.write(0); // Angulo inicial 
  
  // Mensaje inicial en el monitor serial
  Serial.println("Escribir la posicion de angulo de 0 a 180: ");
}

void loop() {
  if (Serial.available()) {    // Verificacion que el puerto serial recibe datos                                  
   delay(10);               
   angulo = Serial.parseInt(); // Lee solo los datos tipo int del buffer
   servo_prueba.write(angulo); // Escritura de microsegundos ingresado por Monitor Serial
   
   // Mensaje de confirmacion del angulo ingresado por Monitor Serial
   Serial.print("Posicion angular: "); 
   Serial.print(angulo);
   Serial.println(" grados");
   
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer del puerto serial
  }
}
Los resultados del programa son los siguientes:

 



Autor: 

Tutorial - Comunicación Maestro / Esclavo : Parte 3 (Comunicación I2C - Introducción)

COMUNICACIÓN I2C
La comunicación I2C (Inter - Integrated Circuit ) es un protocolo de multi-maestro, multi-esclavo inventado por Philips Semiconductor, y es estándar de comunicación usado extendidamente en la electrónica. Algo a tomar en cuenta, es el uso de resistencias pull-up; ciertas aplicaciones ameritan este detalle y su debido cálculo se puede encontrar acá´: "Cálculo de resistencias pull - up para redes I2C"; sobre todo, a medida que la red crece es necesario asegurarse. 

Otro dato importante es el uso de direcciones, la red amerita un maestro que no necesita dirección, en cambio los demás elementos o esclavos si deben estar correctamente identificados; tomando esto último en consideración las direcciones pueden ser únicas o también programables y a su vez, las direcciones tambíen se pueden multiplexar.


USO DE LA LIBRERÍA "WIRE"
Para este tipo de comunicaciones en la plataforma Arduino, se usa la librería Wire que permite tanto administrar la red como configurarla. Los pines usados son los correspondientes a SDA (Línea de datos) y SCL (Línea de reloj). Algunas de las funciones se explican a continuación:
# Wire.begin() o Wire.begin(dirección) : Inicializa la librería Wire y se una a la red I2C como maestro o esclavo. La dirección es opcional para el caso del Maestro y única para el caso del Esclavo. La dirección debe ser de 7 bits como máximo.
# Wire.available() : Para uso sólo del Maestro, retorna el número de bytes disponibles.
# Wire.requestFrom(dirección, cantidad_bytes) : Para uso sólo del Maestro, pide bytes de un esclavo
# Wire.read() : Lee el byte tarnsmitido del Esclavo despúes de haberlo llamado con la función Wire.requestFrom().
# Wire.beginTransmission(dirección) : Comienza la transmisión I2C con el Esclavo de la dirección mencionada. Su uso va acompañado de la función Wire.write() y termina la comunicación con Wire.endTransmission().
# Wire.endTransmission() : Termina la transmisión inicializada con la función Wire.beginTransmission().
# Wire.write(valor) o Wire.write(string) o Wire.write(data, tamaño) : Escribe un dato y se usa entre las funciones Wire.beginTransmission() y Wire.endTransmission().
# Wire.onRequest(función) : Registra una función a ser llamada cuando el Maestro pide datos del Esclavo.
# Wire.onReceive(función) : Registra una función a ser llamada cuando el Esclavo recibe una transmisión del Maestro.

A partir de lo descrito antes, desarrollamos una aplicación simple de lectura entre un solo maestro y un esclavo. Conectamos un potenciómetro de 10 kohm al PIN A0 del Arduino que tiene el papel de esclavo y el Maestro recibirá los datos y los mostrará en el Monitor Serial. La conexión es la siguiente:

# PIN A4 (SDA) : Arduino UNO del Maestro => A4 (SDA) : Arduino UNO del Esclavo 1
# PIN A5 (SCL) : Arduino UNO del Maestro => A5 (SCL) : Arduino UNO del Esclavo 1
# PIN A0 : Arduino UNO del Esclavo => PIN CENTRAL : Potenciómetro
# GND : Los dos GND deben estar conectados => EXTREMO : Potenciómetro
# 5V : Los dos 5V deben estar conectados => EXTREMO : Potenciómetro


El programa usado para el Maestro es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION ENTRE DOS PUNTOS: USO DE LA LIBRERIA WIRE
   (PROGRAMA PARA EL MAESTRO)
   
   MAESTRO: Arduino UNO (1)
   ESCLAVO: Arduino UNO (2)
   
   CONEXION:
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (2) / SDA - ESCLAVO)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (2) / SCL - ESCLAVO)
             Potenciometro: Pin A0 (Arduino UNO(2) - 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

int POT; // Variable de almacenamiento del valor leido del potenciometro

void setup()
{
  Wire.begin();        // Unirse a la red I2C (Maestro)
  Serial.begin(9600);  // Configuracion del puerto serial a 9600 baudios
  
  // Mensaje inicial en el Monitor Serial
  Serial.println("Los valores del potenciometro se observan de 0 a 100% ");
  Serial.println("Esperar...");
  delay(100);
}

void loop(){
  Wire.requestFrom(1,1);     // Pedido de informacion del Esclavo 1 de 1 byte
  while (Wire.available()) { // Verificacion que el puerto serial virtual recibe datos                                      
    POT = Wire.read();       // Lectura de datos del I2C
    
    // Mensaje de muestra del porcentaje del voltaje leido del potenciometro
    Serial.print("Porcentaje de voltaje: "); 
    Serial.print(POT);                       
    Serial.println(" %");         
  }
  delay(100);
}
El programa usado para el Esclavo es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION ENTRE DOS PUNTOS: USO DE LA LIBRERIA WIRE
   (PROGRAMA PARA EL ESCLAVO)
   
   MAESTRO: Arduino UNO (1)
   ESCLAVO: Arduino UNO (2)
   
   CONEXION:
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (2) / SDA - ESCLAVO)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (2) / SCL - ESCLAVO)
             Potenciometro: Pin A0 (Arduino UNO(2) - 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

int POT = A0;      // Pin de entrada de senal del potenciometro
int POT_valor = 0; // Variable de almacenamiento del porcentaje del potenciometro 
int porcentaje;    // Variable de conversion a porcentaje

void setup() {
  Wire.begin(1);             // Unirse a la red I2C (Esclavo con direccion "1")
  Wire.onRequest(escritura); // Registro de evento de la funcion "escritura"
}

void loop() {
  delay(100);
}

void escritura(){
  POT_valor = analogRead(POT);              // Lee el valor del sensor (Rango de 0 a 1023)
  porcentaje = map(POT_valor,0,1023,0,100); // Porcentaje del rango de 0 a 100%
                                            // 100 corresponde a 5V y 0 a 0V
  Wire.write(porcentaje);                   // Escritura por I2C del porcentaje de voltaje 
}
Los resultados obtenidos en el Monitor Serial del Maestro se muestran a continuación:


COMUNICACIÓN MAESTRO / ESCLAVO USANDO TRES ARDUINOS Y LA PC
Estableceremos una red bidireccional (Emisión y recepción de datos) usando los pines I2C de tres Arduinos UNO conectados. 

Las conexiones que se deben realizar se pueden ver en la siguiente figura:

# PIN A4 (SDA) : Arduino UNO del Maestro => A4 (SDA) : Arduino UNO del Esclavo 1
# PIN A5 (SCL) : Arduino UNO del Maestro => A5 (SCL) : Arduino UNO del Esclavo 1
# PIN A4 (SDA) : Arduino UNO del Maestro => A4 (SDA) : Arduino UNO del Esclavo 2
# PIN A5 (SCL) : Arduino UNO del Maestro => A5 (SCL) : Arduino UNO del Esclavo 2
# GND : Los dos GND deben estar conectados.
# 5V : Los dos 5V deben estar conectados


PROGRAMA DE PRUEBA
Como prueba de comunicación, realizaremos un pequeño de ejercicio de envio y recepción de datos en el cual los dos esclavos se identificarán. Para ello, el siguiente procedimiento se debe cumplir:

# El Maestro al enviar la letra "a" ingresada por "Monitor Serial" de la PC, y debe hacer que encienda el led del Pin 13 del "Esclavo 1", quien a su vez enviará el dato "1" que corresponde al identificador del Esclavo. Al recibir dicho mensaje, en el Monitor Serial deberá aparecer "Esclavo id: 1", siendo el número quien identifique el Esclavo y que recibió el mensaje.
# El Maestro al enviar la letra "b" ingresada por "Monitor Serial" de la PC, y debe hacer que encienda el led del Pin 13 del "Esclavo 2", quien a su vez enviará el dato "2" que corresponde al identificador del Esclavo. Al recibir dicho mensaje, en el Monitor Serial deberá aparecer "Esclavo id: 2", siendo el número quien identifique el Esclavo y que recibió el mensaje.

El programa del Maestro es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION MAESTRO / ESCLAVO: MAESTRO / ESCLAVO POR I2C
   (PROGRAMA PARA EL MAESTRO)
   
   MAESTRO: Arduino UNO (1)
   ESCLAVO 1: Arduino UNO (2)
   ESCLAVO 2: Arduino UNO (3)
   
   CONEXION:
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (2) / SDA - ESCLAVO 1)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (2) / SCL - ESCLAVO 1)
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (3) / SDA - ESCLAVO 2)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (3) / SCL - ESCLAVO 2) 
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la comunicacion Maestro / Esclavo usando un Arduino UNO como
   Maestro y dos Arduino UNO como esclavos. El Maestro envia la letra "a" para discriminar al primer
   esclavo para que encienda el led del PIN 13 y envie A1 para identificarse; de la misma manera, al 
   enviar la letra "b" se discrimina el segundo esclavo para que encienda el led del PIN 13 y envie 
   A2
   
   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 id;       // Variable del identificador del Esclavo
int flag = 0; // Flag de control de autentificacion de mensaje

void setup() {
  Wire.begin();       // Unirse a la red I2C (Maestro)
  Serial.begin(9600); // Configuracion del puerto serial a 9600 baudios

  // Mensaje inicial en el monitor serial
  Serial.println("Envio de datos pueden ser de la siguiente manera: ");
  Serial.println("a: Para el esclavo 1");
  Serial.println("b: Para el esclavo 2"); 
}

void loop() {
  if (Serial.available()) {   // Verificacion que el puerto serial recibe datos                                  
    delay(10);                
    identificacion_esclavo(); // Rutina de identificacion de esclavos 1 y 2     
    mensaje_esclavo();        // Rutina de recepcion de mensaje de autentificacion
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer del puerto serial
  }
}

void identificacion_esclavo(){    // RUTINA DE IDENTIFICACION DE ESCLAVOS 1 Y 2

                                  // RUTINA DE IDENTIFICACION DEL ESCLAVO 1
  while (Serial.peek() == 'a'){   // Discriminacion de la letra como diferenciador del esclavo 
    Serial.println("Esperar..."); // Mensaje de espera por datos de verificacion
    flag = 1;                     // Activacion del flag 1
    Wire.beginTransmission(1);    // Comienzo de transmision al Esclavo 1
    Wire.write('a');              // Redireccionamiento del mensaje al Esclavo 1
    Wire.endTransmission();       // Fin de transmision al Esclavo 1
  break;
  }

                                  // RUTINA DE IDENTIFICACION DEL ESCLAVO 2
  while (Serial.peek() == 'b'){   // Discriminacion de la letra como diferenciador del esclavo 
    Serial.println("Esperar..."); // Mensaje de espera por datos de verificacion
    flag = 2;                     // Activacion del flag 2
    Wire.beginTransmission(2);    // Comienzo de transmision al Esclavo 2
    Wire.write('b');              // Redireccionamiento del mensaje al Esclavo 2
    Wire.endTransmission();       // Fin de transmision al Esclavo 2
  break;
  }
}

void mensaje_esclavo(){              // RUTINA DE ACREDITACION DE IDENTIFICACION
  
  while (flag == 1){                 // RUTINA DE ACREDITACION DEL ESCLAVO 1        
    Wire.requestFrom(1,1);           // Pedido de informacion del Esclavo 1 de 1 byte
     while(Wire.available()){        // Verificacion de informacion en el puerto I2C
       id = Wire.read();             // Lectura de datos del buffer   
       Serial.print("Esclavo id: "); // Mensaje de acreditacion del esclavo
       Serial.println(id);           // Numero de identificacion del esclavo
       flag = 0;                     // Desactivacion del flag 1
     }
  break;
  }

  while (flag == 2){                 // RUTINA DE ACREDITACION DEL ESCLAVO 2        
    Wire.requestFrom(2,1);           // Pedido de informacion del Esclavo 2 de 1 byte
     while(Wire.available()){        // Verificacion de informacion en el puerto I2C
       id = Wire.read();             // Lectura de datos del buffer   
       Serial.print("Esclavo id: "); // Mensaje de acreditacion del esclavo
       Serial.println(id);           // Numero de identificacion del esclavo
       flag = 0;                     // Desactivacion del flag 2
     }
  break;
  }
}

El programa de los Esclavos es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION MAESTRO / ESCLAVO: MAESTRO / ESCLAVO POR I2C
   (PROGRAMA PARA EL ESCLAVO)
   
   MAESTRO: Arduino UNO (1)
   ESCLAVO 1: Arduino UNO (2)
   ESCLAVO 2: Arduino UNO (3)
   
   CONEXION:
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (2) / SDA - ESCLAVO 1)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (2) / SCL - ESCLAVO 1)
             A4 (Arduino UNO (1) / SDA - MAESTRO): A4 (Arduino UNO (3) / SDA - ESCLAVO 2)
             A5 (Arduino UNO (1) / SCL - MAESTRO): A5 (Arduino UNO (3) / SCL - ESCLAVO 2) 
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la comunicacion Maestro / Esclavo usando un Arduino UNO como
   Maestro y dos Arduino UNO como esclavos. El Maestro envia la letra "a" para discriminar al primer
   esclavo para que encienda el led del PIN 13 y envie A1 para identificarse; de la misma manera, al 
   enviar la letra "b" se discrimina el segundo esclavo para que encienda el led del PIN 13 y envie 
   A2
   
   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

const int led = 13; // Variable de almacenamiento del pin del puerto de salida del led
char id;            // Variable de almacenamiento de indentificacion

void setup() {
  pinMode(led, OUTPUT);      // Configuracion del Pin 13 como salida
  Wire.begin(1);             // Unirse a la red I2C (Esclavo con direccion "1")
  // Cambiar el 1 por 2 para el caso del Esclavo 2
  Wire.onReceive(lectura);   // Registro de funcion de lectura ante evento
  Wire.onRequest(escritura); // Registro de funcion de escritura ante evento
}

void loop() {
  delay(100);
}

void lectura(int x){           // RUTINA DE IDENTIFICACION FISICA Y AUTENTIFICACION
  while (Wire.available()){    // Verificacion de datos en el puerto I2C
    id = Wire.read();          // Lectura de datos en el puerto I2C
    if (id == 'a'){            // Discriminacion del puntero de identificacion del Esclavo
    // Cambiar 'a' por 'b' para el caso del Esclavo 2
      digitalWrite(led, HIGH); // Encendido del LED del PIN 13  
    }      
  break;
  }
}

void escritura(){ // RUTINA DE AUTENTIFICACION DE LA IDENTIFICACION DEL ESCLAVO
  Wire.write(1);  // Escritura de la identificacion del esclavo
  // Cambiar el 1 por 2 para el caso del Esclavo 2
}
NOTA: En el programa encontrarán diferentes comentarios para cambiar el programa correspondiente al Esclavo 1. El modelo final del programa del Esclavo 2 es el siguiente:
#include <Wire.h>  // Libreria de manejo de red I2C

const int led = 13; // Variable de almacenamiento del pin del puerto de salida del led
char id;            // Variable de almacenamiento de indentificacion

void setup() {
  pinMode(led, OUTPUT);      // Configuracion del Pin 13 como salida
  Wire.begin(2);             // Unirse a la red I2C (Esclavo con direccion "1")
  // Cambiar el 1 por 2 para el caso del Esclavo 2
  Wire.onReceive(lectura);   // Registro de funcion de lectura ante evento
  Wire.onRequest(escritura); // Registro de funcion de escritura ante evento
}

void loop() {
  delay(100);
}

void lectura(int x){           // RUTINA DE IDENTIFICACION FISICA Y AUTENTIFICACION
  while (Wire.available()){    // Verificacion de datos en el puerto I2C
    id = Wire.read();          // Lectura de datos en el puerto I2C
    if (id == 'b'){            // Discriminacion del puntero de identificacion del Esclavo
    // Cambiar 'a' por 'b' para el caso del Esclavo 2
      digitalWrite(led, HIGH); // Encendido del LED del PIN 13  
    }      
  break;
  }
}

void escritura(){ // RUTINA DE AUTENTIFICACION DE LA IDENTIFICACION DEL ESCLAVO
  Wire.write(2);  // Escritura de la identificacion del esclavo
  // Cambiar el 1 por 2 para el caso del Esclavo 2
}

Al abrir el Monitor Serial y colocar "a" o "b" encontraremos en pantalla lo siguiente:


Autor: 

Tutorial - Comunicación Maestro / Esclavo : Parte 2 (Comunicación Serial Simulada)

PUERTOS SERIALES POR MEDIO DE SIMULACIÓN
La transferencia de información entre dos computadores se usa comunmente un puerto serial, este puerto serial se basa en el hardware llamado "UART" (Universal Asynchronous Receiver / Transmitter) que se contiene en el procesador de un chip. El UART se encarga de generar y decodifcar las señales usadas que pasan a través de RX y TX, por lo que el programador sólo debe enfocarse en el mensaje a enviar y el formato en que se envian.

Muchas veces las desventajas en varios proyectos es la necesidad de tener más de un puerto serial, pero algunas plataformas como el Arduino basado en el ATmega328 sólo dispone de un solo puerto UART; en cambio los basados en el ATmega2560 tienen hasta cuatro UARTs por lo que este obstáculo puede ser solucionado usando una plataforma como la descrita al final. Lamentablemente, unas veces no tenemos a la mano una plataforma como el Arduino MEGA2560, o por otro lado, el costo es mucho mayor para un proyecto donde sólo necesitamos unas cuantas entradas y salidas.

Para casos donde lo último mencionado es importante, debemos saber que la misma función que realiza el UART en Hardware también se puede simular en Software. Para ello, usamos una librería llamada "New Software Serial Library", que fué desarrollado por Mikal Hart.

PRUEBA DE LA LIBRERÍA "NEW SOFTWARE SERIAL"
Primero debemos saber como utilizar esta librería, para ello debemos las siguientes funciones:
#  SoftwareSerial nombre_puerto(Pin_receptor, Pin_transmisor) : Con esta función establecemos que pines usaremos para comunicación. El "nombre_puerto" será el que deseemos.
# nombre_puerto.begin(baudios) : Con esta función especificamos los baudios usados para la comunicación.
# nombre_puerto.print(argumento) : Esta función funciona de la misma manera que Serial.print() y se puede escribir tanto números como texto.
# nombre_puerto.println(argumento) : Esta función funciona de la misma manera que Serial.println() y se puede escribir tanto números como texto y saltar a una línea nueva.
# nombre_puerto.available() : Esta función retorna el número de bytes recibidos, que también pueden ser leídos.
# nombre_puerto.read() : Esta función lee el byte del puerto. En caso no se tenga ningún byte, se recibirá -1 como dato.
# nombre_puerto.write(byte) : Transmite un byte a la vez.
# nombre_puerto.flush() : Esta función descarta cualquier dato que no haya sido leído.
# nombre_puerto.parseInt() : Recolecta los datos tipo integer del byte del buffer del puerto serial.
# nombre_puerto.peek() : Discrimina la letra del puntero del byte que se lee en el buffer del puerto serial.
# nombre_puerto.listen() : Discrmina el puerto que se va a escuchar uno a la vez.

NOTA: Al momento de querer recibir datos de parte de dos nodos a uno central "No se podrá", debemos discriminar el puerto del que se va a recibir datos, "Uno a la vez". En cambio, sí se pueden enviar datos a dos nodos a partir de uno central sin discriminar.

Teniendo en cuenta lo anterior, desarrollaremos una simple aplicación usando un potenciómetro de 10 kohm conectado al PIN A0 de un Arduino mientras que otro recibe los datos y los muestra en pantalla. La conexión será la siguiente:

# PIN 4 : Arduino UNO del Nodo 1 => TX : Arduino UNO del Nodo 2
# PIN 3 : Arduino UNO del Nodo 1 => RX : Arduino UNO del Nodo 2
# PIN A0 : Arduino UNO del Nodo 2 => PIN CENTRAL : Potenciómetro
# GND : Los dos GND deben estar conectados => EXTREMO : Potenciómetro
# 5V : Los dos 5V deben estar conectados => EXTREMO : Potenciómetro


El programa para el NODO 1 se muestra a continuación:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION ENTRE DOS PUNTOS: USO DE LA LIBRERIA NEW SOFTWARE SERIAL
   (PROGRAMA PARA EL NODO 1)
   
   NODO 1: Arduino UNO (1)
   NODO 2: Arduino UNO (2)
   
   CONEXION:
             Pin 4(Arduino UNO (1) / RX_1 - NODO 1): TX (Arduino UNO (2) - NODO 2)
             Pin 3(Arduino UNO (1) / TX_1 - NODO 1): RX (Arduino UNO (2) - NODO 2)
             Potenciometro: Pin A0 (Arduino UNO(2) - NODO 2) 
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la comunicacion entre dos nodos 1 y 2; el primer nodo permite 
   la visualizacion de los datos obtenidos de leer el potenciometro que va conectado al nodo 2. 
   
   Para correr el programa se necesita la libreria New Software Serial Library (NewSoftSerial.h)
   
   Se pueden encontrar en: 
   http://arduiniana.org/libraries/newsoftserial/

   Tambien en el tutorial de correspondiente en http://beetlecraft.blogspot.pe/  
   
   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 <SoftwareSerial.h> // Libreria de manejo de comunicacion serial alterna

const int RX_1 = 4; // Pin de UART virtual RX del NODO 1 conectado al pin TX del NODO 2
const int TX_1 = 3; // Pin de UART virtual TX del NODO 1 conectado al pin RX del NODO 2
int POT = 0;        // Variable de almacenamiento del valor leido del potenciometro del NODO 2

SoftwareSerial Serialvirt(RX_1, TX_1); // Declaracion de pines usados para comunicacion con el NODO 2
                                       // y el nombre del puerto virtual

void setup() {
  Serial.begin(9600);     // Velocidad de comunicacion con la PC
  Serialvirt.begin(9600); // Velocidad de comunicacion del NODO 2
  
  // Mensaje inicial en el Monitor Serial
  Serial.println("Los valores del potenciometro se observan de 0 a 100% ");
  Serial.println("Esperar...");
  delay(100);
}

void loop() {
  if (Serialvirt.available()) { // Verificacion que el puerto serial virtual recibe datos                                  
   delay(10);                
                             
   lectura_pot(); // Rutina de lectura del potenciometro
   delay(100);    // Tiempo de demora para siguiente lectura de puerto
  }
}

void lectura_pot(){        // RUTINA DE LECTURA DE DATOS DEL POTENCIOMETRO
  POT = Serialvirt.read(); // Lectura del valor del potenciometro del NODO 2
  
  // Mensaje de muestra del porcentaje del voltaje leido del potenciometro
  Serial.print("Porcentaje de voltaje: "); 
  Serial.print(POT);                       
  Serial.println(" %");                    
}
El programa para el NODO 2 se muestra a continuación:

NOTA: Al momento de querer programar el NODO 2, debe tener desconectado las conexiones del puerto serial con las correspondientes al NODO 1 para evitar problemas de compilación.
/*
   PROGRAMA DE PRUEBA DE COMUNICACION MAESTRO / ESCLAVO: MAESTRO / ESCLAVO POR SERIAL VIRTUAL
   (PROGRAMA PARA EL NODO 2)
   
   NODO 1: Arduino UNO (1)
   NODO 2: Arduino UNO (2)
   
   CONEXION:
             Pin 4(Arduino UNO (1) / RX_1 - NODO 1): TX (Arduino UNO (2) - NODO 2)
             Pin 3(Arduino UNO (1) / TX_1 - NODO 1): RX (Arduino UNO (2) - NODO 2)
             Potenciometro: Pin A0 (Arduino UNO(2) - NODO 2) 
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la comunicacion entre dos nodos 1 y 2; el primer nodo permite 
   la visualizacion de los datos obtenidos de leer el potenciometro que va conectado al nodo 2. 
   
   NOTA: Al momento de compilar el programa para el NODO 2, evitar que los cables del puerto serial
   esten conectados con los correspondientes al NODO 1.
   
   Para correr el programa se necesita la libreria New Software Serial Library (NewSoftSerial.h)
   
   Se pueden encontrar en: 
   http://arduiniana.org/libraries/newsoftserial/

   Tambien en el tutorial de correspondiente en http://beetlecraft.blogspot.pe/  
   
   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
*/

int POT = A0;      // Pin de entrada de senal del potenciometro
int POT_valor = 0; // Variable de almacenamiento del porcentaje del potenciometro 
int porcentaje;    // Variable de conversion a porcentaje

void setup() {
  Serial.begin(9600); // Inicializacion del puerto serial a 9600 baudios
}

void loop() {
  POT_valor = analogRead(POT);              // Lee el valor del sensor (Rango de 0 a 1023)
  porcentaje = map(POT_valor,0,1023,0,100); // Porcentaje del rango de 0 a 100%
                                            // 100 corresponde a 5V y 0 a 0V
  Serial.write(porcentaje);                 // Escritura por puerto del porcentaje de voltaje
  delay(100);                               // Tiempo de retraso para siguiente rutina
}
Al abrir el Monitor Serial del NODO 1 obtendremos lo siguiente:


COMUNICACIÓN MAESTRO / ESCLAVO USANDO TRES ARDUINOS Y LA PC
Una de las varias variantes que se pueden establecer en este tipo de comunicación, es establecer una red bidireccional (Emisión y recepción de datos) usando como enlace los puertos seriales cruzados de dos Arduinos UNO conectados a cuatro pines ajenos de un Arduino UNO (que cumplirán la función de dos puertos seriales virtuales).

Las conexiones que se deben realizar se pueden ver en la siguiente figura:

# PIN 2 : Arduino UNO del Maestro => TX : Arduino UNO del Esclavo 1
# PIN 3 : Arduino UNO del Maestro => RX : Arduino UNO del Esclavo 1
# PIN 4 : Arduino UNO del Maestro => TX : Arduino UNO del Esclavo 2
# PIN 5 : Arduino UNO del Maestro => RX : Arduino UNO del Esclavo 2
# GND : Los dos GND deben estar conectados.
# 5V : Los dos 5V deben estar conectados


NOTA: Al momento de querer programar los Esclavos, estos deben tener desconectadas sus conexiones del puerto serial con el Maestro, en caso contrario, el programa no se podrá compilar y se establecerá un error en el IDE de Arduino.

PROGRAMA DE PRUEBA
Como prueba de comunicación, realizaremos un pequeño de ejercicio de envio y recepción de datos en el cual los dos esclavos se identificarán. Para ello, el siguiente procedimiento se debe cumplir:

# El Maestro al enviar la letra "a" ingresada por "Monitor Serial" serial de la PC y debe hacer que encienda el led del Pin 13 del "Esclavo 1", quien a su vez enviará el dato "A1" siendo "A" el puntero del mensaje y "1" el identificador del Esclavo. Al recibir dicho mensaje, en el Monitor Serial deberá aparecer "Esclavo id: 1", siendo el número quien identifique el Esclavo y que recibió el mensaje.
# El Maestro al enviar la letra "b" ingresada por "Monitor Serial" serial de la PC y debe hacer que encienda el led del Pin 13 del "Esclavo 2", quien a su vez enviará el dato "A2" siendo "A" el puntero del mensaje y "2" el identificador del Esclavo. Al recibir dicho mensaje, en el Monitor Serial deberá aparecer "Esclavo id: 2", siendo el número quien identifique el Esclavo y que recibió el mensaje.

El programa del Maestro es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION MAESTRO / ESCLAVO: MAESTRO / ESCLAVO POR SERIAL VIRTUAL
   (PROGRAMA PARA EL MAESTRO)
   
   MAESTRO: Arduino UNO (1)
   ESCLAVO 1: Arduino UNO (2)
   ESCLAVO 2: Arduino UNO (3)
   
   CONEXION:
             Pin 2 (Arduino UNO (1) / RX_1 - MAESTRO): TX (Arduino UNO (2) - ESCLAVO 1)
             Pin 3 (Arduino UNO (1) / TX_1 - MAESTRO): RX (Arduino UNO (2) - ESCLAVO 1)
             Pin 4 (Arduino UNO (1) / RX_1 - MAESTRO): TX (Arduino UNO (3) - ESCLAVO 2)
             Pin 5 (Arduino UNO (1) / TX_1 - MAESTRO): RX (Arduino UNO (3) - ESCLAVO 2)
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la comunicacion Maestro / Esclavo usando un Arduino UNO como
   Maestro y dos Arduino UNO como esclavos. El Maestro envia la letra "a" para discriminar al primer
   esclavo para que encienda el led del PIN 13 y envie A1 para identificarse; de la misma manera, al 
   enviar la letra "b" se discrimina el segundo esclavo para que encienda el led del PIN 13 y envie A2
   
   NOTA: El maestro discrimina de manera intercalada la recepcion de datos de cada Esclavo, por lo que
   solamente se puede ingresar sucesivamente a - b - a - b ...

   Para correr el programa se necesita la libreria New Software Serial Library (NewSoftSerial.h)
   
   Se pueden encontrar en: 
   http://arduiniana.org/libraries/newsoftserial/

   Tambien en el tutorial de correspondiente en http://beetlecraft.blogspot.pe/  
   
   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 <softwareserial.h> // Libreria de manejo de comunicacion serial alterna

const int RX_1 = 2; // Pin de UART RX_1 del Maestro conectado al pin TX del Esclavo 1
const int TX_1 = 3; // Pin de UART TX_1 del Maestro conectado al pin RX del Esclavo 1
const int RX_2 = 4; // Pin de UART RX_2 del Maestro conectado al pin TX del Esclavo 2
const int TX_2 = 5; // Pin de UART TX_2 del Maestro conectado al pin RX del Esclavo 2

SoftwareSerial Serialvirt1(RX_1, TX_1); // Declaracion de pines usados para comunicacion con el 
                                        // Esclavo 1 y el nombre del puerto virtual
SoftwareSerial Serialvirt2(RX_2, TX_2); // Declaracion de pines usados para comunicacion con el 
                                        // Esclavo 2 y el nombre del puerto virtual
                                        
int id; // Variable del identificador del Esclavo

void setup() {
  Serial.begin(9600);      // Velocidad de comunicacion con la PC
  Serialvirt1.begin(9600); // Velocidad de comunicacion del Esclavo 1
  Serialvirt2.begin(9600); // Velocidad de comunicacion del Esclavo 2
  Serialvirt1.listen();    // Discriminacion para recibir datos solo del Esclavo 1
  
  // Mensaje inicial en el monitor serial
  Serial.println("Envio de datos pueden ser de la siguiente manera: ");
  Serial.println("El programa comienza recibiendo datos del Esclavo 1");
  Serial.println("a: Para el esclavo 1");
  Serial.println("b: Para el esclavo 2"); 
  Serial.println(" ");
  Serial.println("Ingresar letra a: ");
}

void loop() {
  if (Serial.available()) {  // Verificacion que el puerto serial recibe datos                                  
   delay(10);                
                             
   identificacion_esclavo(); // Rutina de identificacion de esclavos 1 y 2
   delay(100);               // Retardo para la siguiente rutina
   mensaje_esclavo();        // Rutina de recepcion del mensaje del esclavo 1 o 2
   delay(100);               // Retardo para la siguiente rutina
   
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer del puerto serial
  }
}

void identificacion_esclavo(){    // RUTINA DE IDENTIFICACION DE ESCLAVOS 1 Y 2

                                  // RUTINA DE IDENTIFICACION DEL ESCLAVO 1
  while (Serial.peek() == 'a'){   // Discriminacion de la letra como diferenciador del esclavo 
    Serial.println("Esperar..."); // Mensaje de espera por datos de verificacion
    Serialvirt1.write('a');       // Redireccionamiento del mensaje al Esclavo 1
    break;
  }

                                  // RUTINA DE IDENTIFICACION DEL ESCLAVO 2
  while (Serial.peek() == 'b'){   // Discriminacion de la letra como diferenciador del esclavo  
    Serial.println("Esperar..."); // Mensaje de espera por datos de verificacion
    Serialvirt2.write('b');       // Redireccionamiento del mensaje al Esclavo 2
    break;
  }
}

void mensaje_esclavo(){                 // RUTINA DE ACREDITACION DE IDENTIFICACION

                                        // RUTINA DE ACREDITACION DEL ESCLAVO 2
  while (Serialvirt1.peek() == 'A'){    // Discriminacion de la letra como diferenciador del esclavo  
    Serialvirt1.read();                 // Lectura de datos del buffer
    id = Serialvirt1.parseInt();        // Extraccion de los numeros de las letras     
    Serial.print("Esclavo id: ");       // Mensaje de acreditacion del esclavo
    Serial.println(id);                 // Numero de identificacion del esclavo
    if (id == 1){Serialvirt2.listen();} // Eleccion del Esclavo 2 para recepcion de datos
    break;
  }

                                        // RUTINA DE ACREDITACION DEL ESCLAVO 2
  while (Serialvirt2.peek() == 'A'){    // Discriminacion de la letra como diferenciador del esclavo  
    Serialvirt2.read();                 // Lectura de datos del buffer
    id = Serialvirt2.parseInt();        // Extraccion de los numeros de las letras        
    Serial.print("Esclavo id: ");       // Mensaje de acreditacion del esclavo
    Serial.println(id);                 // Numero de identificacion del esclavo
    if (id == 2){Serialvirt1.listen();} // Eleccion del Esclavo 1 para recepcion de datos
    break;
  }
}
El programa de los Esclavos es el siguiente:
/*
   PROGRAMA DE PRUEBA DE COMUNICACION ENTRE DOS PUNTOS: USO DE LA LIBRERIA NEW SOFTWARE SERIAL
   (PROGRAMA PARA EL ESCLAVO)
   
   MAESTRO: Arduino UNO (1)
   ESCLAVO 1: Arduino UNO (2)
   ESCLAVO 2: Arduino UNO (3)
   
   CONEXION:
             Pin 2 (Arduino UNO (1) / RX_1 - MAESTRO): TX (Arduino UNO (2) - ESCLAVO 1)
             Pin 3 (Arduino UNO (1) / TX_1 - MAESTRO): RX (Arduino UNO (2) - ESCLAVO 1)
             Pin 4 (Arduino UNO (1) / RX_1 - MAESTRO): TX (Arduino UNO (3) - ESCLAVO 2)
             Pin 5 (Arduino UNO (1) / TX_1 - MAESTRO): RX (Arduino UNO (3) - ESCLAVO 2)
             GND: Conectar los dos GND
             VCC: Conectar los dos 5V
   
   En el siguiente programa probaremos la comunicacion Maestro / Esclavo usando un Arduino UNO como
   Maestro y dos Arduino UNO como esclavos. El Maestro envia la letra "a" para discriminar al primer
   esclavo para que encienda el led del PIN 13 y envie A1 para identificarse; de la misma manera, al 
   enviar la letra "b" se discrimina el segundo esclavo para que encienda el led del PIN 13 y envie A2
   
   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
*/

const int led = 13;

void setup() {
  pinMode(led, OUTPUT);
  Serial.begin(9600); // Configuracion del puerto serial de comunicacion con el ESCLAVO
}

void loop() {
  if (Serial.available()) {  // Verificacion que el puerto serial recibe datos                                  
   delay(10);                
                             
   identificacion(); // Rutina de identificacion de esclavos 1 y 2
   
    while (Serial.available() > 0){Serial.read();} // Rutina de limpieza del buffer del puerto serial
  }
}

void identificacion(){ 
                                // RUTINA DE IDENTIFICACION FISICA Y AUTENTIFICACION
  while (Serial.peek() == 'a'){ // Discriminacion de la letra de identificacion 
  // Cambiar 'a' por 'b' para el segundo esclavo
  
    digitalWrite(led, HIGH);    // Encendido del LED del PIN 13
    Serial.write('A');          // Envio de la letra de incio de trama de autentificacion
    Serial.print(1);            // Envio del numero de autentificacion del esclavo al Maestro
    // Cambiar Serial.print(1) por Serial.print(2) para el segundo esclavo         
    break;
  }
}
NOTA: En el programa encontrarán una subrutina llamada "void identificacion()" que debe ser modificada de la siguiente manera para el caso del Esclavo 2
void identificacion(){ 
                                // RUTINA DE IDENTIFICACION FISICA Y AUTENTIFICACION
  while (Serial.peek() == 'b'){ // Discriminacion de la letra de identificacion 
  // Cambiar 'a' por 'b' para el segundo esclavo
  
    digitalWrite(led, HIGH);    // Encendido del LED del PIN 13
    Serial.write('A');          // Envio de la letra de incio de trama de autentificacion
    Serial.print(2);            // Envio del numero de autentificacion del esclavo al Maestro
    // Cambiar Serial.print(1) por Serial.print(2) para el segundo esclavo         
    break;
  }
}
Al abrir el Monitor Serial y colocar "a" o "b" encontraremos en pantalla lo siguiente:


CONSIDERACIONES FINALES
# Debemos darle un tiempo de retraso (delay) entre cada proceso para este tipo de comunicación, que aumentará a medida que se añadan más subrutinas o se aumenten la cantidad de nodos. Esto en caso la comunicación sea bidireccional.
# Las pruebas se realizaron también a una distancia de 2 m de cable, por lo que es posible establecer nodos de 2 m de separación para este tipo de comunicación.

Autor: