Detección de dispositivos en bus simple

Actualmente me enfrento al siguiente problema: hay un sistema que consta de un dispositivo maestro y una cantidad de dispositivos esclavos (todos esos dispositivos tienen pequeñas MCU). Se comunican con algún protocolo personalizado basado en un cable serial (se parece bastante a Modbus). Todos los dispositivos esclavos deben tener identificaciones únicas dentro de un bus, de modo que el dispositivo maestro pueda dirigirse a cada uno de esos esclavos. Actualmente me veo obligado a codificar esas identificaciones en cada dispositivo esclavo. Mi objetivo es actualizar todos esos dispositivos con el mismo firmware, por lo que no se deben usar identificaciones codificadas para que esto sea posible. Estoy pensando en el dispositivo maestro, que puede asignar direcciones únicas a todos esos dispositivos, pero no puedo entender cómo hacerlo. ¿Alguien puede darme alguna idea o concepto de cómo extender mi protocolo de comunicación para que esto sea posible? Tal vez alguien me puede dar un ejemplo?

Este es, por supuesto, un problema de diseño muy común. Si existe una solución de "santo grial", no estoy tan seguro de que haya muchos circuitos integrados de identificación únicos en el mercado. Sin embargo, me alegraría ver una solución.
Puede agregar una EEPROM preserializada si tiene una pequeña cantidad de área de PCB disponible y un puerto I2C o SPI. Algo así como un 24AA02E48 .
¿Sus MCU manejan el protocolo ModBus-ish en el software? Si lo hacen, entonces, al encenderlo, no podría usar ModBus hasta que haya pasado por una fase de enumeración de su propio protocolo. Los esclavos necesitan una identificación única, así que coloque un IC de número de serie DS2401 de 48 bits en cada uno. Luego, implementa un protocolo simple con esclavos de drenaje abierto que utilizan lectura fallida (más de 48 lecturas en serie, los esclavos devuelven un 0 como bajo, 1 como hi-Z, luego verifica la línea de lectura y siéntese esta ronda si es diferente a lo que ellos enviaron). Siga leyendo números de 48 bits del bus y asignando direcciones hasta que todo esté listo. Puedo expandir esto, pero primero, ¿su hw/sw lo permitirá?

Respuestas (4)

Para hacer este tipo de direccionamiento dinámico en un bus común, en última instancia, debe tener una de dos cosas:

  • un espacio de direcciones muy pequeño para que pueda buscarlo con fuerza bruta de manera eficiente
  • algún tipo de sistema de gestión/detección de colisiones

Si no tiene ninguna de estas dos cosas, necesitará codificar las direcciones en los dispositivos maestro y esclavo.

La razón de esto es que si tiene un espacio de direcciones (de tamaño N) que es demasiado grande para buscar de manera eficiente recorriendo cada N direcciones, cualquier algoritmo de búsqueda optimizado que pueda encontrar la dirección en menos de N pasos debe incluir la posibilidad de más de un esclavo transmitiendo una respuesta al mismo tiempo. Si la capa física no puede manejar esta situación, lamentablemente no tiene suerte. Si la capa física puede detectar colisiones, entonces hay muchas opciones, como tener un retraso de reintento aleatorio cuando ocurre una colisión (Ethernet), o usar algo como el bus CAN donde las colisiones se gestionan de manera cooperativa.

Las colisiones se detectan mediante la suma de comprobación de cada mensaje. ¿O te refieres a algo como los métodos CSMA?
@vadimchik Siempre que el bus físico (controladores, etc.) pueda manejar las colisiones, entonces podría implementar un sistema como ethernet. Sin embargo, muchos autobuses no están diseñados para manejar colisiones y pueden dañar a los conductores.
físicamente, todos los pines TX esclavos son pines de drenaje abiertos, por lo que las colisiones no deberían dañar el hardware
@Vadimchik El problema con la detección de colisiones para esta técnica es que es posible que no se detecte la colisión. Si ambos esclavos envían el mismo paquete casi al mismo tiempo, lo que sucedería si no tuviera un método decente para crear un paquete aleatorio, se superpondrán en la línea de señal y el maestro no lo notará.
@Vadimchik Y crear diferentes números aleatorios en un conjunto de micros iniciados al mismo tiempo no es un asunto simple.

Diseñé un sistema para esto hace varios años.

Funcionó como el siguiente esquema. Se estableció un anillo de comunicación común.

Cada esclavo tiene un circuito de interruptor lógico que inicialmente, o en el reinicio del sistema, bloquea el anillo.

esquemático

simular este circuito : esquema creado con CircuitLab

Al iniciarse, el dispositivo maestro, en la parte superior, envía un comando "Quién_está_ahí".

Estructura de comando [CÓDIGO][(ID1,ID1)][FIN]

Debido a que los interruptores están inicialmente abiertos, solo el primer esclavo recibió ese comando.

El esclavo copia el paquete de comando y agrega la ID de su tipo de función a la lista y luego envía el comando. El esclavo recuerda el índice de la ubicación en la que agregó su identificación de tipo como su dirección de anillo. Una vez enviado, el esclavo cierra su interruptor de anillo. Luego ignora cualquier otro comando "Quién_está_ahí" hasta el próximo reinicio.

El siguiente esclavo en secuencia hace lo mismo... y sigue hacia abajo en la cadena.

Finalmente, el maestro recibe el comando con una lista de tipos de dispositivos en el orden en que se encontraron en el anillo, por lo que conoce la ID de cada esclavo.

Después de eso, el maestro solo dirige los paquetes al esclavo apropiado. Dado que todos los interruptores están cerrados en ese punto. Todos escuchan el comando, pero solo responde el destinatario.

Además: en mi aplicación particular, el sistema estaba basado en un plano posterior, donde las placas pueden o no estar pobladas para una configuración de producto en particular. Como tal, los elementos de conmutación se diseñaron en el plano posterior para que la ranura se omitiera si el dispositivo no estaba ocupado.

Una alternativa es pasar cada comando a través de cada micro, sin embargo, eso introduce una latencia significativa y un poco de sobrecarga para cada micro.

Solución interesante, pero desafortunadamente no hay posibilidad de cambiar el esquema de conexión de bus para esos dispositivos.
@Vadimchik, sí, entiendo, es algo que uno tiene que diseñar desde el principio. Agregué más esta respuesta como un indicador para aquellos que comienzan.

Si, en lugar de un verdadero bus, tuviera un arreglo en cadena, entonces podría hacer que el maestro hablara con el esclavo, le asignara una dirección y luego le enviara un comando para habilitar el puerto de salida al siguiente esclavo. Repita hasta que todos los esclavos tengan direcciones. Básicamente, así es como funciona la enumeración USB con concentradores apilados.

Además, ¿qué tipo de disposición de hardware está utilizando? ¿Las placas esclavas que están conectadas a un backplane? Si es así, podría agregar pines adicionales en el conector con diferentes arreglos de pines conectados a tierra en cada ranura para actuar como una identificación, leída por GPIO en el esclavo, para generar la dirección del esclavo.

Mi hardware está conectado con un cable de 4 hilos: gnd, vcc y dos cables que actúan como miso y mosi. No hay forma de apagar los esclavos en consecuencia: en cada momento pueden estar o encendidos o apagados.

Si no tiene una identificación fija y no puede cambiar el hardware para romper las conexiones, entonces necesita un generador de números aleatorios.

El siguiente sistema puede hacer lo que desee si tiene una forma de generar un número aleatorio en cada micro independientemente uno del otro.

ingrese la descripción de la imagen aquí

Sin embargo, generar la parte del número aleatorio es casi tan difícil como encontrar la parte de su ID si los micros no están conectados a algún tipo de señal analógica que pueda usar para sembrar su generador de números aleatorios.