RETO 5: COMUNICÁNDONOS CON ARDUINO – PUERTO SERIE

Vamos a aprovechar este momento para explicar qué es un puerto serie y para qué nos puede servir con nuestra pequeña, pero gran, placa Arduino. Para finalizar, y antes de que os haga las ya tradicionales propuestas de ampliación, veremos cómo el puerto serie nos puede ayudar a programar el parking domótico.

Una buena definición de puerto serie sería la siguiente:

“Un puerto serie o puerto en serie es una interfaz de comunicaciones de datos digitales, frecuentemente utilizado por computadoras y periféricos, donde la información es transmitida bit a bit, enviando un solo bit a la vez; en contraste con el puerto paralelo que envía varios bits simultáneamente.”

Es decir, el puerto serie nos va a servir para comunicar nuestro ordenador con la placa de Arduino, tanto para mandar datos -en forma de secuencias de bits, te recomiendo este interesantísimo vídeo acerca del sistema binario– desde el ordenador a Arduino, como al revés y a una velocidad determinada, en bits por segundo (baudios, o lo que es lo mismo, número de unidades de señal por segundo, teniendo en cuenta que un bauido puede contener varios bits, dependiendo del esquema de modulación). También podríamos usar el puerto serie para realizar la comunicación entre dos Arduinos u otros dispositivos.

.

EXPLICACIÓN FÍSICA PUERTO SERIE

Para el envío físico de las secuencias de bits el puerto serie necesita de al menos dos conectores, RX (recepción) y TX (transmisión), a través de ellos podrá realizar la comunicación de datos.

La otra forma de envío de datos, la comunicación en paralelo, usa múltiples canales de forma simultánea. Por ello necesita un mayor número de conductores de comunicación, que varían en función del tipo de puerto.

 .

c

.

La ventaja de los puertos en paralelo parece evidente, lo que ocurre es que conforme los microporcesadores se han ido haciendo más rápidos, o potentes, el puerto en serie ha ido desplazando al puerto en paralelo.

Nuestros ordenadores disponen de varios puertos serie, como por ejemplo los conectores USB (Universal Serial Bus), aunque existen una gran variedad de tipos de puerto serie en el ámbito de la informática, por ejemplo el RS-232, Serial Ata, Ethernet…

.

PUERTOS SERIE EN NUESTRO ARDUINO

Físicamente en la placa de Arduino UNO los pines empleados para el puerto serie son el 0 (RX) y 1 (TX). En la imagen los elementos 5 y 6:

.

Partes de la placa de ARDUINO UNO

.

Es evidente que mientras usemos el cable conector USB para el puerto serie (lo cual simplifica el proceso de conexión en gran medida) no podremos usar como entradas o salidas digitales los pines asociados con dicho puerto. Algunos casos, como la placa Arduino Pro Mini, no tienen conector USB ni micro USB, por lo que la única forma de conectarse a la misma es usando los pines correspondientes.

.

Arduino pro mini

Arduino Pro Mini

.

Resumiendo, la placa Arduino UNO, dispone de dos puertos serie posibles. También existen otras placas como por ejemplo la Arduino Mega con 4 puertos de serie, muy usada en el ámbito de la Impresión 3D:

.

ArduinoMega

Arduino Mega

.

¿CÓMO CONECTAMOS NUESTRO ARDUINO POR EL PUERTO SERIE?

Muy fácil, no tendremos que hacer nada, sí como lo oyes, o lees mejor dicho, ya que se conecta por el mismo puerto por el cual cargamos los programas en el microcontrolador, esto es, el puerto COM correspondiente. Con conectar tu placa Arduino a través del cable usb con el ordenador, suficiente.

Acto seguido podremos abrir la ventana Monitor Serie para visualizar los datos que queramos comunicar:

.

Monitor serial en Arduino

.

A la hora de trabajar con el monitor serie, esta estupenda utilidad integrada en el IDE de Arduino, hay que tener en cuenta las dos zonas de que dispone: una  grande en la que muestra los datos enviados y la otra para enviarlos.

.

Monitor serie Arduino

.

PROGRAMANDO QUE ES GERUNDIO…

Para empezar a jugar con nuestro Monitor Serial y poder implementar este tipo de comunicación os propongo un programa que imprima un cronómetro.

Respecto a la configuración, dentro de la función setup() deberemos establecer la velocidad estándar de comunicación, que son 9600 baudios, mediante la instrucción Serial.begin(9600);

A continuación, dentro de la función loop(), escribiremos la instrucción necesaria para sacar el mensaje del segundero por monitor serie, con la instrucción Serial.println(“cronómetro”). Serial.println(texto) envía una cadena de texto hacia el ordenador incluyendo un salto de línea al final.

El código completo de nuestro cronógrafo sería el siguiente:

int cronometro=0;

void setup(){
 Serial.begin(9600);            // Iniciamos el puerto de serie.
 }

void loop(){

Serial.print("Cronometro: ");   // Imprimimos el texto "Cronometro: "
Serial.println(cronometro);     // Imprimimos a continuación del texto anterior el valor de la variable cronómetro y añade un salto de línea a continuación
                                // La función .println() es igual que la .print() pero es más fácil para la lectura de los datos en el Monitor Serie del software. 
cronometro++;                   // Incrementamos el cronómetro en una unidad y esperamos un segundo (1000 ms.)
delay(1000);                    // Pausa de un segundo.
}

Nota: usaremos Serial. println(); cuando vayamos a enviar un valor numérico y Serial.print(); con textos. Más información, aquí.

Cargamos el código y para ver el valor del monitor serie tendremos que pulsar sobre el icono de la lupa que está arriba a la derecha.

.

Monitor serial en Arduino

.

Comprobaremos que los valores se visualizan uno por línea, y a una gran velocidad. Para solucionar esto, podemos incluir la función delay(1000); que introducirá una pausa de 1 segundo en cada visualización.

Como acabamos de ver el monitor del puerto serie nos sirve para enviar y recibir fácilmente información a través del mismo, por esto, en la programación del parking domótico nos vendrá muy bien para comprobar el estado de las plazas libres y si el algoritmo que hemos programado funciona correctamente.

Será tan sencillo como añadir las siguientes instrucciones:

int plazas=2;

Aquí creamos como variable global y de tipo número entero las plazas totales del parking, serán las plazas disponibles existentes en todo momento en el parking. Empezaremos con un número bajo hasta que lo programemos a la perfección, por ejemplo 2. Por tanto, a esta variable deberemos sumarle una unidad al salir un vehículo o restarle al entrar.

Serial.printIn (plazas);

Dentro de la función loop() imprimimos la variable plazas con esta función Serial.prinIn (); para ver el número de plazas libres del parking.

delay(100);

Pequeña pausa de 100 milisengundos entre valor y valor impreso.

Otro ejemplo rápido que seguro utilizas en tus futuros proyectos robóticos: realizar la lectura analógica del pin 0 y enviar estos datos al ordenador cada segundo.

void setup()
{
Serial.begin(9600);               // Configura el puerto serie a 9600bps
}

void loop()
{
Serial.println(analogRead(0));    // Envía valor analógico leído en el pin 0
delay(1000);                      // Espera 1 segundo, y así hasta el fin de los días ;)
}

.

AMPLIACIÓN DE RETOS

En esta ocasión como propuestas de ampliación os reto a:

  • Encender y apagar un led desde el puerto serie, por ejemplo el integrado en la placa de Arduino, el led 13. Puedes usar el envío de los caracteres “e” para encendido y “a” para apagado, empleando el monitor serie. Para ello necesitarás usar la función avaliable() que lo que realiza es enviar los datos introducidos en el monitor serie cuando se escribe dicha información; y también la función Serial.read() para leer el carácter enviado.

En esta primera ampliación de reto habría que destacar las siguientes funciones:

Serial.available()

La cual devuelve un número entero con el número de bytes (carácteres) disponibles para leer desde el buffer serie, ó 0 si no hay ninguno. Si hay algún dato disponible, SerialAvailable() será mayor que 0. El buffer serie puede almacenar como máximo 128 bytes.

Serial.read()

Lee o captura un byte (carácter) desde el puerto serie. Devuelve: El siguiente byte (carácter) desde el puerto serie, ó -1 si no hay ninguno.

Un ejemplo de programa que enciende y apaga un led desde el monitor serie podría ser el siguiente:

/*
Enviamos un carácter a la placa Arduino, empleando el monitor serial. En caso de enviar ‘a’ la placa Arduino APAGA el LED, y en caso de enviar ‘e’ lo ENCIENDE.
*/

int ledPin = 13;
int input;       //Inicializamos la variable input como el carácter que recibirá la placa como input.

void setup() {
 pinMode(ledPin, OUTPUT); 
 Serial.begin(9600);
 Serial.println("Preparados para recibir datos!");
}

void loop() {

  if (Serial.available () > 0) { //Si existen datos disponibles los leemos. 
  input = Serial.read(); //Leemos el input enviado. 
  Serial.println('input');
   if (input== 'e'){             // Mucho ojo con las comillas, deben ser simples. 
    digitalWrite(ledPin, HIGH);
    Serial.println("ON");
   }
   if (input=='a'){              // De nuevo, atención a las comillas, deben ser simples. 
    digitalWrite(ledPin, LOW);
    Serial.println("OFF");
   }
  }
}

 


 

  • Hacer parpadear el led integrado en la placa de Arduino a través del número (número de repeticiones) que introduzcamos en el monitor serie (¿por ejemplo entre 0 y 9?).

En este caso hay que destacar dos aspectos:

char option = Serial.read(); Char significa carácter, es un tipo de dato que ocupa 1 byte (8 bits) de memoria y almacena el valor de un carácter. Se escriben entre comillas, simples cuando es un sólo carácter y dobles cuando se trata de una cadena. Por ejemplo, ‘A’ o «ABC».

Lo fundamental de este tipo de variable es comprender que se almacenan como números, puedes ver la tabla de equivalencia aquí, que proviene de la Carta ASCII (American Standard Code for Information Interchange). Por lo tanto podremos hacer operaciones matemáticas con los caracteres. Ejemplo ‘B’ + 2 = 68.

Así pues, el tipo de datos char es un tipo con signo, que codifica números entre -128 y 127. 

 

option =- ‘0’;

El código, como puedes ver en el ejemplo a continuación es similar al anterior, pero al enviarse los datos caracteres ASCII, debemos restar el valor ‘0’ al dato recibido para convertir el valor numérico enviado en tipo número entero.

Recuerda que 5 =- 2; significa 5 – 2 = 3. Tienes un resumen de las fórmulas algorítmicas, aquí.

 

int option;
int led = 13;

void setup(){
 Serial.begin(9600);
 pinMode(led, OUTPUT);
}

void loop(){

 if (Serial.available()>0){
   char option = Serial.read();
   if (option >= '1' && option <= '9') {
    option -= '0';
    for(int i=0; i<option; i++){
     digitalWrite(led, HIGH);
     delay(100);
     digitalWrite(led, LOW);
     delay(200);
     }
   }
 }
}

Para terminar, una de mis citas preferidas:

“Un sueño que sueñas solo es sólo un sueño. Un sueño que sueñas con alguien es una realidad”

John Lennon

John Lennon NY, 1964

John Lennon NY, 1964