Learning   Examples | Foundations | Hacking | Links

Interfaz Serie por Software para Arduino

Nota: Si sólo quieres usar un interfaz serie por software, mira la librería SoftwareSerial incluida en Arduino 0007 y posteriores. Léelo si quieres saber cómo funciona esa librería.

En este tutorial aprenderás a implementar una comunicación serie asíncrona desde el programa de Arduino para comunicarte con otros dispositivos serie. Mediante la conexión serie por software podrás crear una conexión serie en cualquiera de los pines digitales E/S de Arduino. Esto debería ser usado cuando son necesarias varias conexiones serie. Si sólo es necesaria una conexión serie debería usarse el puerto serie hardware. Este es un tutorial del software de propósito general, NO un tutorial específico del dispositivo. Puedes encontrar un tutorial sobre comunicación con un ordenador aquí. Tutoriales sobre dispositivos específicos hay en la página de tutoriales. Para una buena explicación de comunicación serie mira Wikipedia.

La conexión serie por software puede funcionar a 4800 o a 9600 baudios.

Funciones disponibles:

SWread(); Devuelve un entero de longitud un byte de la conexión serie por software

Ejemplo:

byte RXval; 
RXval = SWread();

SWprint(); Envía un entero de longitud un byte a través de la conexión serie por software

Ejemplo:

byte TXval = 'h';
byte TXval2 = 126;
SWprint(TXval);
SWprint(TXval2);

Definiciones necesarias:

#define bit9600Delay 84  
#define halfBit9600Delay 42
#define bit4800Delay 188 
#define halfBit4800Delay 94

Estas definiciones configuran los tiempos de espera necesarios para el funcionamiento del puerto serie a 9600 baudios y 4800 baudios.

Material necesario:

  • Dispositivo con el que comunicar
  • Placa de entrenamiento
  • Cables
  • Placa Arduino
  • LED - opcional, para depurar

Prepara la placa de entrenamiento

Conecta el dispositivo con el que quieres comunicarte en la placa de entrenamiento. Conecta la tierra de la placa de entrenamiento a la tierra del Arduino. Si tu dispositivo utiliza alimentación de 5V conecta el pin de 5V de la placa Arduino a los 5V de la placa de entrenamiento. Si no es así conecta alimentación y tierra de una fuente de alimentación alternativa a la placa de entrenamiento. Haz otras conexiones si son necesarias para tu dispositivo. Adicionalmente es posible que quieras conectar el LED para depurar entre el pin 13 y tierra.

Decide que pines quieres usar para transmitir y para recibir. En este ejemplo usaremos el pin 7 para transmitir y el pin 6 para recibir, pero cualquiera de los pines digitales debería funcionar.

Programa el Arduino

Ahora programaremos el código para habilitar la comunicación serie. Este programa simplemente esperará un carácter que llegará por el puerto serie, luego lo transmite de vuelta en mayúsculas por el puerto serie. Este es un buen programa general para comprobar el puerto serie, deberías ser capaz de extrapolarlo para cubrir tus necesidades de puerto serie. Vamos a examinar el código por secciones.

#include <ctype.h>

#define bit9600Delay 84  
#define halfBit9600Delay 42
#define bit4800Delay 188 
#define halfBit4800Delay 94 

Aquí configuramos las directrices de nuestra pre-compilación. Estas directrices de pre-compilación son procesadas antes de que la compilación real comience. Empiezan con "#" y no terminan con punto y coma.

Primero incluimos el fichero ctype.h en nuestra aplicación. Esto nos da acceso a la función toupper() de la librería de C de operaciones con caracteres, que usaremos después en nuestro programa. Esta librería es parte de Arduino, así que no necesitas hacer nada más que escribir la línea #include para usarla. Después establecemos nuestras definiciones para el baudrate. Estas son las directrices de pre-compilación que definen los tiempos de espera para los diferentes baudrates. La línea #define bit9600Delay 84 hace que el compilador sustituya el número 85 en todos los sitios donde se encuentre la etiqueta "bit9600Delay". Las definiciones de pre-compilado se usan a menudo para constantes porque no utilizan espacio de memoria de programa en el microcontrolador.

byte rx = 6;
byte tx = 7;
byte SWval;

Aquí configuramos nuestros pines de transmisión (tx) y recepción (rx). Cambia los números de los pines para adaptarlo a tu aplicación. También asignamos una variable para guardar los datos recibidos SWval.

void setup() {
  pinMode(rx,INPUT);
  pinMode(tx,OUTPUT);
  digitalWrite(tx,HIGH);
  digitalWrite(13,HIGH); //turn on debugging LED
  SWprint('h');  //debugging hello
  SWprint('i');
  SWprint(10); //carriage return
}

Aquí inicializamos las líneas, encendemos nuestro LED de depuración y enviamos un mensaje de depuración para confirmar que todo está funcionando según lo planeado. Podemos pasar caracteres individuales a la función SWprint.

void SWprint(int data)
{
  byte mask;
  //startbit
  digitalWrite(tx,LOW);
  delayMicroseconds(bit9600Delay);
  for (mask = 0x01; mask>0; mask <<= 1) {
    if (data & mask){ // choose bit
     digitalWrite(tx,HIGH); // send 1
    }
    else{
     digitalWrite(tx,LOW); // send 0
    }
    delayMicroseconds(bit9600Delay);
  }
  //stop bit
  digitalWrite(tx, HIGH);
  delayMicroseconds(bit9600Delay);
}

Esta es la función SWprint. Primero la línea de transmisión se pone en bajo para señalar un bit de inicio. Luego, utilizando una máscara de bits vamos cambiando el valor de la salida del pin alto o bajo 8 veces para los 8 bits del valor a transmitir. Finalmente ponemos la línea en alto otra vez para señalar un bit de parada. Por cada bit que transmitimos, mantenemos la línea en alto o bajo el tiempo especificado. En este ejemplo estamos usando un baudrate de 9600. Para usar 4800 simplemente reemplaza la variable bit9600Delay por bit4800Delay.

int SWread()
{
  byte val = 0;
  while (digitalRead(rx));
  //wait for start bit
  if (digitalRead(rx) == LOW) {
    delayMicroseconds(halfBit9600Delay);
    for (int offset = 0; offset < 8; offset++) {
     delayMicroseconds(bit9600Delay);
     val |= digitalRead(rx) << offset;
    }
    //wait for stop bit + extra
    delayMicroseconds(bit9600Delay); 
    delayMicroseconds(bit9600Delay);
    return val;
  }
}

Esta es la función SWread. Esta función espera a que llegue un byte por el pin de recepción y luego lo devuelve en la variable asignada. Primero esperamos a que la línea de recepción se ponga en bajo. Comprobamos después de la mitad del tiempo de espera para estar seguros de que la línea está todavía en bajo y no estamos recibiendo simplemente ruido en la línea. Luego repetimos utilizando una máscara de bits y desplazamos unos (1) o ceros (0) en nuestro byte de salida basándonos en lo que recibimos. Finalmente permitimos una pausa para el bit de parada y luego devolvemos el valor.

void loop()
{
    SWval = SWread(); 
    SWprint(toupper(SWval));
}

Finalmente implementamos el loop de nuestro programa principal. En este programa simplemente esperamos a que lleguen caracteres, los cambiamos a mayúsculas y los enviamos de vuelta. Este será siempre un buen programa para ejecutar cuando queramos estar seguros de que la conexión serie está funcionando correctamente.

Para ver montones de dispositivos serie mira el catálogo online de Sparkfun. Tienen montones de módulos fáciles de usar para GPS, bluetooth, wi-fi, LCD's, etc.

Para facilitarte el trabajo, copia y pega el programa completo de este tutorial:

//Created August 15 2006
//Heather Dewey-Hagborg
//http://www.arduino.cc

#include <ctype.h>

#define bit9600Delay 84  
#define halfBit9600Delay 42
#define bit4800Delay 188 
#define halfBit4800Delay 94 

byte rx = 6;
byte tx = 7;
byte SWval;

void setup() {
  pinMode(rx,INPUT);
  pinMode(tx,OUTPUT);
  digitalWrite(tx,HIGH);
  digitalWrite(13,HIGH); //turn on debugging LED
  SWprint('h');  //debugging hello
  SWprint('i');
  SWprint(10); //carriage return
}

void SWprint(int data)
{
  byte mask;
  //startbit
  digitalWrite(tx,LOW);
  delayMicroseconds(bit9600Delay);
  for (mask = 0x01; mask>0; mask <<= 1) {
    if (data & mask){ // choose bit
     digitalWrite(tx,HIGH); // send 1
    }
    else{
     digitalWrite(tx,LOW); // send 0
    }
    delayMicroseconds(bit9600Delay);
  }
  //stop bit
  digitalWrite(tx, HIGH);
  delayMicroseconds(bit9600Delay);
}

int SWread()
{
  byte val = 0;
  while (digitalRead(rx));
  //wait for start bit
  if (digitalRead(rx) == LOW) {
    delayMicroseconds(halfBit9600Delay);
    for (int offset = 0; offset < 8; offset++) {
     delayMicroseconds(bit9600Delay);
     val |= digitalRead(rx) << offset;
    }
    //wait for stop bit + extra
    delayMicroseconds(bit9600Delay); 
    delayMicroseconds(bit9600Delay);
    return val;
  }
}

void loop()
{
    SWval = SWread(); 
    SWprint(toupper(SWval));
}

Código y tutorial de Heather Dewey-Hagborg

Share