[OFF-TOPIC] Circuito de control de dirección en RS485/Modbus

Hola chicos.

Estoy investigando una serie de circuitos para el control automático de la dirección de escritura/lectura en un bus RS485 con ModBus como protocolo. Estos circuitos controlan al transceptor, ya sea un MAX485 o similar, actuando sobre los pines DE/RE poniendo al chip en modo emisión o recepción.

Si me preguntáis ¿para qué? Obviamente para ahorrarme un pin del Arduino. No es que sea algo importante pero me gustaria entender bien dichos circuitos.

Veamos el primer circuito basado en un inversor 74xx14:

CONINVERSOR

Cuando no estamos transmitiendo la señal TX se encuentra en estado HIGH. Vamos a suponer que hemos conectado hace un rato el circuito, por lo tanto el condensador C estará ya cargado. Por lo tanto en la entrada del inversor tendremos un valor HIGH y la salida será LOW. En este estado el MAX485 tiene la unión de patillas DE/RE a nivel bajo lo que indicará que está en modo recepción.

Cuando enviamos un byte lo primero que ocurrirá será un start bit en la señal, es decir, un cambio a nivel bajo de la señal TX. En ese momento el condensador se descargará rápidamente a través del diodo D, haciendo que la entrada del inversor se ponga a LOW. La salida del inversor se pondrá a nivel alto poniendo a su vez al MAX485 en modo escritura.

Obviemos los datos de momento. Al terminar la transimisión del byte se producen los bits de parada y si no enviamos nada mas la señal TX vuelve a estar en HIGH. Como el condensador estaba descargado empieza a cargarse lentamente a través de la resistencia R. Hasta que el valor de tensión no alcance un nivel suficiente para que el 74xx14 lo acepte como nivel alto, la señal permanecerá en modo escritura. Cuando la tensión alcanza dicho valor el inversor cambia su salida poniéndose a LOW de nuevo (en modo lectura).

¿Que pasa con los datos? Generalmente cuando se produzca el start bit el chip pasa a modo escritura y debe permanecer así al menos hasta que se haya enviado todo el byte. Para una trama Modbus un byte suele ser: un bit de inicio, 8 de datos y dos de parada; haciendo un total de 11bits.

Dependiendo de la velocidad o baud rate estos bits tardaran mas o menos en enviarse, por ejemplo, para una velocidad de 9600 baudios, un bit tarda 1/9600s, por lo tanto para un byte completo se tardan unos 1.15ms.

También se deben tener en cuenta los tiempos entre caracteres (T15) y entre paquetes (T35). En ModBus estos tiempos son fijos para velocidades superiores a los 19200 baudios y son T15=750us y T35=1.75ms.

Si la velocidad es inferior el tiempo ha de ser calculado. T15 y T35 representan el tiempo en enviar 1.5 caracteres y 3.5 caracteres respectivamente.

Curiosamente el tiempo T15 es muchas veces obviado y muchos programas de PC no lo controlan, aunque nuestro Arduino suele ser más preciso y puede perfectamente controlar esos tiempos.

El circuito no es invención mia, si no que es uno de los circuitos más conocidos y usados en la red, solo hace falta hacer una busqueda en google y vereís que ya hay módulos RS485 que usan dicho circuito.

El "pero" que veo es que he visto muchos circuitos y muchos valores distintos del valor de la resistencia y el condensador. Y no le veo la razón a dichos valores.

Por ejemplo, para una velocidad de 9600 baudios usando 8N2 tenemos que el tiempo será de unos 1.15ms. Si fijamos el valor del condensador a 100nF y aplicamos la formula simple de carga del condensador (T=RC) obtendremos un valor de resistencia de 11k5. Si tomamos en cuenta el tiempo t15 la señal deberá permanecer en LOW al menos 1.725ms, aplicando la formula de nuevo la resistencia será de 17k2. He visto valores de resistencia muy superiores a esos en casi todos los circuitos y no me cuadran para ninguna velocidad.

No sé si es que se me escapa algo del circuito o qué. ¿Vosotros qué opinais?

He intentado hacer una simulación en proteus pero no soy capaz de ver el retraso a no ser que exagere mucho el tiempo.

El análisis del circuito, ni idea, pero el dato que te puede estar faltando es que RS485 es una señal diferencial, no hay un uno lógico por tensión como el RS232. Mide la diferencia de polaridad de cada par trenzado. El uno lógico se obtiene cuando en el conductor + tiene mas de 0.2 V de diferencia con el conductor -, y el cero logico cuando el tension del conductor - es mayor que el conductor + ( o todo al revés, no recuerdo bien cual es cual). La diferencia de voltaje para definir una señal esta entre 0.2 y 7 V (o algo parecido), por eso puedes encontrar mucha diferencia entre resistencias y condensadores, o eso creo.

Hola PeterKantTropus.

El bus rs485 es diferencial, pero el control se hace mediante señales TTL. Quizas me faltó poner el circuito completo para que se entienda:

circuito

Nosotros no manejamos la señal diferencial, sino que controlamos el transceptor con señales TTL. En una conexión normal con Arduino, conectariamos el pin DI a TX, RO a RX y controlamos la señal DE/RE con otro pin del arduino para hacer que el transceptor funcione escribiendo en el bus o leyendo de este.

El circuito del 74xx14 nos evita tener que usar este tercer pin, solo las señales TX y RX.

Haaa, entiendo es un simple filtro pasa bajo de 7 Khz.

Esto no estoy seguro que este bien. En realidad es una duda que tengo hace mucho.
Bits por segundos no siempre es igual a baudios (no se porque en todos los tutoriales de Arduino lo ponen como tal)
Entiendo que uno fija la velocidad en 9600 bits por segundos, que en el caso que los datos no estén agrupados coincide con los baudios.
Cada señal esta distanciada a 1/9600 es decir 104 µs

Baudios y bps es lo mismo en el caso de la comunicación serial de arduino.
Los baudios se miden en paquetes de información por segundo, como el mínimo paquete de información en la comunicación por Serial es un bit, si enviamos 1000 paquetes en 1 segundo (1000 baudios) entonces enviamos 1000 bits en un segundo (1000 bps).

La diferencia entre una cosa y otra se hace evidente si hacemos la conversión de serie a paralelo o viceversa.
Supongamos que enviamos datos en serie hacia un shift register (tipo 74HC595) a una velocidad de 8000 bps (o baudios), en las salidas tendremos disponibles los datos a una velocidad 8 veces menor porque el paquete de datos es de 8 bits (1 byte), entonces la velocidad de salida es de 1000 baudios.

Si luego hacemos la operación contraria, enviaremos esos bytes a 1000 baudios y obtendremos a la salida del registro los bits a 8000 bps.

En resumen, en nuestro "complicador de comunicaciones", movemos los datos en serie a 8000 bps que es lo mismo que 8000 baudios, en este caso, y en paralelo los movemos a 1000 Bps (bytes por segundo) que en este caso son 1000 baudios.

Es una explicación muy superficial pero creo que se entiende, la realidad es un poco más compleja porque además se toman en cuenta los cambios de estado de la señal que definen a la unidad de información.

Un ejemplo que los que estén "entrados en años" (como yo) tal vez recuerden es el de los modem V.90 a 56k baudios, que "haciendo trampa" mediante cambios en la modulación de la señal, lograban "romper" la limitación de 33300 bps que imponían las instalaciones telefónicas con cableados de cobre. Epocas remotas... Jaja
Los más "nuevos" llegan (¿o llegaron?) a modular la señal a 56k baudios pero enviar los datos a 115200 bps, si mal no recuerdo, usando una subportadora. ¡Sorprendente!

Saludos

Haaa, entiendo es un simple filtro pasa bajo de 7 Khz.

Tiene forma de filtro RC, pero estamos en señales digitales, asi que el comportamiento no llega a ser el de un filtro RC.

La forma de onda resultante del circuito debería ser mas o menos esta:

SENALES

Quizás se entienda mejor si llamo al juego de pines DE/RE de la manera en la que los llamamos en los programas de Arduino: TXE (tx enable).

Recordar que en una señal serie TTL la señal TX siempre está a HIGH cuando no estamos enviando. El start bit siempre será un cero y los stop bits siempre será o serán unos.

De la velocidad, como dice @Gatul, cada vez que se me escape baudios no hay que preocuparse serán bits por segundo.

No creo que trabaje de esa forma, el chip entra a enable por cada bit que recibe, no necesita que este enable en todo momento de la transmisión del dato. Al trabajar a dos hilos, y por lo tanto en half duplex, es el protocolo el que se encarga que no haya colisiones utilizando timings. Me parece que el circuito sí cumple la función de filtro pasa bajo

Bueno, ya que a mi no me crees, que solo soy un transceptor de lo que he visto y leido, te paso información sobre el tema:

Analog Devices AN-1458 Isolated RS-485 Repeater with Automatic Direction Control

En esta nota de aplicación no utiliza un 74xx14 para realizar el inversor trigger schmitt utiliza un ADCMP600 que es un amplificador operacional-comparador de voltaje. En la página 7 explica el circuito de retraso y la fórmula para calcularlo usando el comparador.

s there any way to use Half Duplex RS485 without using a dedicated controller pin for RE - DE?

De este artículo expuse la imagen y explica brevemente como funciona, mismo principio de funcionamiento que expuse en el primer post.

Highfield Tales Modbus-RTU added to the Cet Open Toolbox

Buscando la información me tope con esta alternativa aplicada a Arduino, el circuito no es exactamente el mismo, pero también se basa en el mismo principio, de hecho hay una captura muy buena de osciloscopio:

EE-Paper Design of signal isolation and self transmitting circuit based on RS-485 interface

En este explica dos de los tres circuitos que aplican este método para controlar los pines RE/DE. Con un 74xx14 y un 555.

Electronic Exchange - how to wire up gsm modemdce with max485

Mas de lo mismo...

TI Designs - Automatic Direction Control RS-485

Este circuito es diferente pero utiliza el mismo procedimiento. Solo que en vez de una puerta lógica utiliza un 555.

Incluso en este mismo foro he visto el circuito:

TTL signal is weaker when connected from CD4069 to RX

Aunque en este caso se trata de un problema al usar un chip diferente al 74xx14.

El tercer método que no he explicado es usando un 74hct123 que es un multivibrador monoestable que realiza la misma función de retraso.

Como ves no he inventado nada, simplemente estoy analizando el circuito y no logro a entender porque hay valores tan dispares entre tantos esquemas para el valor de RC.

El tiempo que calculaste en el primer momento es el máximo, pero se puede calcular otro tiempo el mínimo.
Tenemos el bit de inicio, que siempre va a cero , y luego los bits de parada van siempre a 5 V
Por lo tanto en el peor de los casos, en que el dato a transmitir sea B11111111
Solo se necesita que el circuito RC mantenga el sistema en
T= 8/9600 que es 0.833 milisegundos
Entonces ya tienes un rango extendido que el circuito funcionaria [0.833, 1.15] ms

Esta tarde veré si me queda algún 74xx14 y puedo montar algo y verlo en el cutre analizador lógico que tengo.

Aun así cuando una mira los valores de los esquemas no le salen las cuentas. Por ejemplo: 1nF/22k son 20uS; 47nF/39k son 1.8ms; 1nF/51k son 0.05ms; 100nF/56k son 5.6ms. Valores todos ellos muy dispares. Eso si en ningún ejemplo hablan de una velocidad exacta.

No creo que en este caso estén intentando hacer un enable de todo el Byte.
Una posible explicacion es que esten intentando un bit control.
En un enlace que pusiste utilizan un bit control

Tanto el max 485 y el 74xxx son lo suficiente rápidos para hacer un enable por cada bit 0 y el bit 1 lo generan deshabilitando el max485, por lo que solo necesitan corregir el bit un poco por los posibles retrasos del max485 y el 74xxx, sobre todo a tasas muy altas de baud rate.

Bueno, después de unos dias liado voy a poner algún resultado.

De momento @PeterKantTropus obviaré el bit control y me centraré en el data control.

He montado el circuito en la protoboard usando un 74hc14N que tenía a mano y un max485 de los que he quitado por que me daba problemas (en la parte diferencial, en la lógica TTL funciona correctamente). He montado el cicuito con unos valores de condensador/resistencia de 100nF/10k. En teoría el retraso debería ser de 1ms aproximadamente.

He probado dos códigos fuente: uno enviando byte a byte y otro enviando los bytes seguidos.

El código byte a byte es este:

// Ejemplo de petición de ModBus.
uint8_t frame[32] = { 0x01, 0x03, 0x00, 0x6B, 0x00, 0x03, 0x76, 0x87 };
uint8_t framesize = 8;
void setup() {
  Serial.begin(9600);
}

void loop() {
  for (int i=0; i<framesize; i++) {
    Serial.write(frame[i]);
    delay(6);
  }  
}

El código para toda la trama completa es este:

// Ejemplo de petición de ModBus.
uint8_t frame[32] = { 0x01, 0x03, 0x00, 0x6B, 0x00, 0x03, 0x76, 0x87 };
uint8_t framesize = 8;
void setup() {
  Serial.begin(9600);
}

void loop() {
  for (int i=0; i<framesize; i++) {
    Serial.write(frame[i]);
  }
  // Este retraso es para poder ver mejor el resultado.
  delay(100);
}

En el caso de byte a byte he obtenido la siguiente señal:

Se aprecia que se produce el retraso de forma correcta, incluido en el peor de los casos (cuando enviamos un 0x00).

La salida de la trama completa es igual, funcionando como debe:

captura02

Hice pruebas con distintos valores de resistencia y medi los tiemos obteniendo el siguiente resultado:

ResistenciaT=RCT obtenido
100nF/10k1ms0.5ms
100nF/12k1.2ms0.91ms
100nF/15k1.5ms1.15ms
100nF/20k2.0ms1.50ms
Durante la medida cometí el error de medir desde que termina el stop bit hasta donde se produce la transición. Luego corregí ese problema ya que el tiempo ocurre desde la última transición bajo alto, es decir, cuando se inicia el stop bit.

Si observais la tabla el valor real y el obtenido no es igual, pero si tienen una relación entre ellos. Si dividis el valor real entre el obtenido sale la misma relación: 1.33.

Aquí pensé que el valor real es inferior debido a las caracteristicas del 74xx14. ¿A que nivel de entrada se produce un cambio en la salida?. Si la entrada vale 0, cuando se produce el cambio en la señal el condensador se carga lentamente. RC es el valor en el cual el condesador se considera cargado, es decir, casi con 5 voltios, pero el cambio se produce antes.

Investigando un poco encontré la siguiente explicación sobre un oscilador basado en el 74xx14:

Simple Schmitt Trigger SN74HC14 Square Wave Generator

En el se especifica que cuando el condensador se está cargando al alcanzar 2/3T se produce el cambio. Recordad T = RC. Si aplicamos esto, obtenemos que el tiempo real será: 0.7*R*C. Que casualmente coincide con la tabla que yo he obtenido en la practica.

Moraleja:

El tiempo de retraso de dicho circuito es de 0.7*R*C.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.