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"
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:
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.
Al abrir el Monitor Serial del NODO 1 obtendremos lo siguiente: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.
# 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 }
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
# 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.
/* 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; } }
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; } }
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:
No hay comentarios:
Publicar un comentario