arduino-rs485-max485

Comunicación RS485 con Arduino y conversor MAX485

¿Qué es el RS485?

El RS485 es un estándar de comunicaciones ampliamente empleado en industria que podemos emplear en procesadores como Arduino para leer o escribir en otros dispositivos.

El RS485 es sencillo, robusto y, a diferencia de otras tecnologías propietarias, su uso es es gratuito. Por estos motivos, muchos dispositivos sensores y actuadores lo han adoptado como forma de comunicación, siendo frecuente en el ámbito industrial.

Una de las ventajas del RS485 es la larga distancia de transmisión. El alcance depende de la velocidad, siendo posible conseguir 35 Mbps en distancias inferiores a 10 metros, y hasta 100 Kbps en distancias hasta 1200 metros.

El RS485 es un protocolo de capa física según el modelo OSI. Es decir, no pone normas ni restricciones sobre el contenido, forma, o codificación de los mensajes enviados. Por tanto, podemos emplearlo para enviar cualquier tipo de señal, como por ejemplo una sea digital, PWM, puerto serie o bus I2C.

Un bus RS485 dispone de dos conductores denominados A y B (inversora). Para ellos se suele emplear un cable de par trenzado para aumentar la inmunidad al ruido. Es posible acceder hasta 32, 128 o 254 estaciones empleando un único par trenzado.

El protocolo funciona, simplemente, invirtiendo la tensión entre A (no inversora) y B (inversora):

  • Cuando A+ y B- se considera estado LOW.
  • Cuando A- y B+ se considera estado HIGH.

Con RS485 podemos establecer comunicación simplex, half-duplex y full-duplex. Sin embargo, para la comunicación full-duplex tendremos que establecer dos canales distintos, y disponer de un receptor y emisor en cada uno de los terminales.

El RS485 se emplea frecuentemente en combinación con UARTs, para enviar la señales a largas distancias. También es habitual encontrarlo como capa física en una implantación de protocolo Modbus.

Proyectos con RS485 incluyen automatización de plantas industriales. También se emplea en ámbitos de automoción e incluso en aviones para la conexión de dispositivos. Otros ejemplos de uso incluyen automatización de edificios, monitorización de sistemas fotovoltaicos, o control grandes sistemas de iluminación o sonido como en conciertos de música.

Precio

Los conversores de RS485 para Arduino, como el MAX485, son dispositivos muy baratos. Podemos encontrarlos por 0.35€, buscando en vendedores internacionales de eBay o AliExpress.

arduino-rs485-componente

Esquema de montaje

La conexión de los módulos con MAX485 es sencilla. En primer lugar, alimentamos el módulo conectando Vcc y Gnd, respectivamente, a 5V y Gnd de Arduino.

Por otro lado, tendremos que conectar los conductores A y B del par trenzado que constituyen el propio bus RS485, y al que estarán conectados todos los dispositivos que pertenezcan al mismo bus.

Ahora, deberemos configurar el módulo como emisor o receptor, para lo cual empleamos los pines RE (receiver enable) y DE (driver enable). Si conectamos estos pines a Vcc el módulo actuará como emisor, y si los conectamos a Gnd como receptor.

Finalmente, tendremos que conectar, respectivamente la entrada de datos al módulo DI (drive input) en el caso de que actué como emisor, o la salida de datos del módulo RO (receiver output) en el caso que actué receptor.

Por tanto, si estamos empleando la UART de Arduino, la conexión en modo emisor es la siguiente,

arduino-rs485-simplex-emisor

Mientras que la conexión en modo receptor es la siguiente,

arduino-rs485-simplex-receptor

Si queremos que durante la conexión el conversor RS485 pueda cambiar su papel de emisor a receptor (conexión half duplex) simplemente tenemos que conectar los pines RE y DE a una salida digital para poder cambiar su tensión de Gnd a Vcc.

arduino-rs485-esquema-duplex

En todos los casos, la conexión de Arduino es similar. La siguiente imagen muestra la conexión half-duplex vista desde Arduino.

arduino-rs485-esquema

Lógicamente, si sólo vamos a actuar como emisor o receptor, podemos prescindir de uno de los pines de datos (RX o TX) y de la conexión al pin digital de RE/DE conectándolas permanentemente a Gnd o Vcc, respectivamente, según hemos visto en los esquemas anteriores para receptor y emisor.

Como ya habíamos dicho, si queremos comunicación full-duplex (emisor y receptor simultáneamente) tendremos que usar dos conversores RS485 en cada dispositivo y dos bus RS485 paralelos independientes, uno para TX y otro para RX.

Ejemplos de código

El RS485 sólo es un protocolo de capa física, es decir, un “medio de transmisión” por el que podemos mandar cualquier señal digital, lo que incluye UART, Modbus, bus SPI, I2C.

Para conectarnos con un dispositivo RS485, como por ejemplo un termostato, un sensor, o un actuador industrial, necesitaremos saber el protocolo que emplea y la trama (al igual que hacemos siempre que conectamos un dispositivo).

Para ilustrar su uso, a modo de ejemplo, vamos a mostrar el uso del RS485 usando el puerto serie. Por tanto, serán válidos todos los ejemplos que vimos al ver el uso del puerto serie en Arduino.

Comunicación simplex

En el primer ilustra el funcionamiento del modo simplex, es decir, en el que cada dispositivo tiene una configuración fija. En el ejemplo un Arduino emisor envía un único byte a un Arduino receptor. En un proyecto real el emisor o el receptor podría ser cualquier otro dispositivo como un sensor, un actuador, o incluso otro procesador o un ordenador como Raspberry Pi.

El código es muy simple, el emisor envía un byte a través del puerto serie, y el receptor lo captura. En este caso, hemos tomado hemos tomado millis()/1000 como dato de ejemplo, pero podría ser cualquier otro dato, como la medición de un sensor, o un comando a ejecutar.

Código emisor

void setup() 
{ 
  Serial.begin(9600);
} 
 
void loop() 
{ 
  byte data = millis() / 1000;
  Serial.write(data);
  delay(250);                           
} 

Código receptor

void setup() 
{ 
  Serial.begin(9600);  
} 
 
void loop() 
{  
  if (Serial.available()) 
  {
    byte data = Serial.read(); 
  }
} 

Comunicación half-duplex

El siguiente ejemplo muestra el funcionamiento half-duplex, es decir, cada Arduino puede actuar como emisor o receptor, pero no simultáneamente. Para ello disponemos de un pin digital (pin 2 en el ejemplo) para cambiar el modo de cada Arduino. También indicamos el modo en el que está operando cada Arduino con el pin integrado en la placa.

El ejemplo simula la solicitud de un dato desde un Arduino master a un Arduino slave. Para ello, el master envía una trama simple, en este caso una simple ‘H’. El slave responde enviando una variable integer, que es recogida por el master. En un proyecto real podríamos enviar distintos comandos, o una dirección para comunicarnos con varios slave.

Código master

const int ledPin =  13;  // Led integrado
const int ReDePin =  2;  // HIGH = Driver / LOW = Receptor
const char HEADER = 'H';

void setup() 
{ 
  Serial.begin(9600);
  Serial.setTimeout(100);
  
  pinMode(ledPin, OUTPUT);
  pinMode(ReDePin, OUTPUT);
} 
 
void loop() 
{ 
  //RS485 transmisor 
  digitalWrite(ReDePin, HIGH);
  digitalWrite(ledPin, HIGH); 
  Serial.print(HEADER);
  Serial.flush();  
  delay(50); 
   
  //RS485 como receptor
  digitalWrite(ReDePin, LOW); 
  digitalWrite(ledPin, LOW); 
  if(Serial.find(HEADER))
  {
    int data = Serial.parseInt(); 
     
    // Aqui hariamos lo que queramos con data
  }
} 

Código slave

const int ledPin =  13;  // Led integrado
const int ReDePin =  2;  // HIGH = Driver / LOW = Receptor
const char HEADER = 'H';

void setup() 
{ 
  Serial.begin(9600);  

  pinMode(ReDePin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(ReDePin, OUTPUT);
} 
 
void loop() 
{ 
  //RS485 como receptor
  digitalWrite(ReDePin, LOW); 
  digitalWrite(ledPin, LOW); 
  
  if(Serial.available())
  {
    if(Serial.read()==HEADER)
    {
      //RS485 transmisor 
      digitalWrite(ReDePin, HIGH);
      digitalWrite(ledPin, HIGH); 
      
      int data = millis() / 1000;
      Serial.print(HEADER);
      Serial.print(data);
      Serial.flush();
    }
  }
  delay(10);
}