¿Puede un puerto USB pasivamente 'escuchar solamente'?

Tengo un pequeño controlador dedicado construido alrededor de un Arduino que acepta comandos de una PC a través de USB (serie). La comunicación es unidireccional: el controlador nunca envía datos a la PC.

Ahora necesito extender el controlador para manejar más tareas, pero no hay espacio físico ni programático, así que estoy agregando una segunda caja con otro Arduino que aceptará los comandos extendidos.

No puedo modificar la aplicación de control de la PC ni agregar otro puerto USB a la PC. La aplicación controla el hardware y, a su vez, está controlada por un script. Solo puede hablar con un puerto serie (físico o virtual) a la vez. Podemos modificar el script, pero no el hardware o la aplicación. Así que mi esperanza es que pueda cruzar las líneas D+/- para alimentar el segundo controlador.

Si esto fuera una serie directa, no tendría ningún problema, pero con USB en el medio veo problemas más adelante, porque la PC querrá enumerar ambos Arduino USB, ¿verdad?

¿Hay una solución aquí que estoy pasando por alto? ¿Puedo usar USB de forma pasiva, solo como oyente, con el segundo controlador?

En ese caso, ¿qué tal unir las líneas seriales entre los arduinos? ¿O hacer que uno envíe comandos desconocidos al otro? ¿O comprar uno con más espacio para el programa?
@ pjc50: unir las líneas seriales fue mi segunda opción, principalmente porque los problemas de diseño en la pantalla actual lo hacen incómodo. Pero se está volviendo obvio que podría ser la única solución. El espacio del programa es solo una parte del problema: el espacio físico es más importante.
use alambres delgados. un cable USB y un solo cable delgado ocupan tanto espacio como un cable USB solo, el otro arduino necesita 5 V, conexión a tierra y el solo cable delgado que ocupa menos espacio que un cable USB.
¿Es posible insertar un convertidor USB-Serie entre la PC y el dispositivo? No necesitará un puerto USB adicional. Simplemente interrumpa el cable y coloque un convertidor de este tipo en el medio. Si eso está permitido, hay soluciones alternativas que puedo describir en una respuesta adecuada.
@vsz: me interesaría escuchar lo que propone, siempre que no involucre un segundo puerto serie virtual en la PC. Cualquier esquema que agregue un dispositivo USB parece estar en conflicto con esto. Me comprometo a combinar líneas Rx en este punto, pero tengo curiosidad por escuchar su idea, ya que otros podrían beneficiarse.

Respuestas (4)

La serie USB CDC es un protocolo bastante complicado. Incluso si solo envía comandos en serie de una manera, hay tráfico USB que va y viene todo el tiempo. Incluso cuando el bus serie virtual está en silencio, el host USB pregunta continuamente al dispositivo USB "¿tiene algo para enviar?" y el dispositivo dice "no".

Considere enviar la frase "hola" a un arduino y obtener "hola" de vuelta. En el bus USB, se verá así:

Anfitrión: ¿Tienes un mensaje?
Dispositivo : No.
Anfitrión: Tengo un mensaje para ti
Dispositivo : OK
Anfitrión: hola\n
Dispositivo : OK
Anfitrión: ¿Tienes un mensaje?
Dispositivo : No.
Anfitrión: ¿Tiene un mensaje?
Dispositivo : hel
Host: ¿Tiene un mensaje?
Dispositivo : llo\n
Host: ¿Tiene un mensaje?
Dispositivo : No.
etc. etc.

Estos mensajes también se mezclarán con los mensajes enviados a otros dispositivos en el mismo concentrador (incluso si no tiene un concentrador USB en el sistema, es posible que haya uno dentro de la computadora. Así que podría ver fácilmente los mensajes en su mouse y teclado mezclados).

El protocolo USB es extremadamente complicado, por lo que dividirlo de la manera que mencionas no será práctico. Sin embargo, puedes "olfatearlo". Si conecta las líneas D+ y D-, es posible ver el tráfico en el autobús. Siempre que el sniffer no intente manipular las líneas D+/D-, el bus USB seguirá funcionando. El rastreador necesitaría entonces identificar qué mensajes eran relevantes y decodificarlos. Construir un sniffer a partir de un arduino sería difícil pero probablemente no imposible. Es casi seguro que no es la mejor solución para su problema.

En realidad, construir un sniffer a partir de un Arduino sería imposible en este caso . Los hacks USB programáticos de ATmega son USB de baja velocidad y dependen de que parte de la especificación USB no se aplique literalmente para funcionar. Pero la implementación de USB CDC existente será USB de máxima velocidad , y por lo tanto demasiado rápida para olfatear de esta manera. Posiblemente, en el extremo de cargar un firmware personalizado en el 16u2 existente (si el Arduino existente es un verdadero Uno), uno podría hacer que funcione en un modo de baja velocidad semi-compatible y, por lo tanto, sea detectable, pero su última declaración es la clave: " no es la mejor solución para su problema".
Gracias por el tutorial. Se ha dejado muy claro que no hay forma de que un puente simple funcione, así que me voy al plan B.
@ChrisStratton Estaba pensando en abusar seriamente del hardware USB en un Leonardo. Nunca uso los que tienen un 16U2 separado como un convertidor usb/serie, y había olvidado que la mayoría de ellos eran así. Creo que sería posible abrir el hardware USB en un 32U4 de tal manera que no manipulara el bus pero aún escuchara. Sin embargo, no miré la hoja de datos para verificar.
@JimMack Me alegro de que haya sido útil.
@JackB: no, eso no funcionaría. Para olfatear, necesitaría algo donde pueda poner sus dedos en la implementación de la función USB de grano fino, no un bloque periférico de función fija. Y, de manera realista, en ese punto, sería mejor que tomara un STM32F4 de doble USB y creara algo que tomara lo que quisiera y pasara el resto del flujo de carga útil en serie virtual al Arduino colgando de su puerto OTG. Pero luego das un paso atrás y te das cuenta de que solo debes reemplazar el Arduino con algo que haga todo lo que OP necesita, o agregar software para hablar con un segundo dispositivo.
Estoy razonablemente seguro de que todos los mensajes del host van a todos los dispositivos, y también estoy bastante seguro de que he visto mensajes dirigidos a otros dispositivos al rastrear el tráfico USB en un dispositivo. Creo que entró un enrutamiento más específico para USB 3.0.
@JackB: No, eso nunca ha sido cierto. Los dispositivos USB se direccionan por su posición física en el árbol de conexiones, por lo que los concentradores solo enrutan los mensajes al puerto al que están destinados.
@DaveTweed Esto ha atraído suficientes votos a favor que quiero asegurarme de que sea correcto en cuanto al enrutamiento de paquetes. Cuando lo miro, encuentro artículos como este que dicen que el punto a punto es nuevo en USB3.0. ¿Puede proporcionar una fuente autorizada que diga que también está disponible en versiones anteriores?
Me llevará un tiempo desenterrar una referencia, pero mientras tanto, solo piénsalo. Si un concentrador necesitara transmitir todos los mensajes a todos los puertos, toda la red estaría limitada a la velocidad del dispositivo más lento. Además, no se requiere que los dispositivos tengan identificadores únicos, por lo que no hay forma de que funcione un sistema de transmisión. ¿Cómo ordenarían dos dispositivos idénticos el tráfico destinado a ellos?
IIRC cada dispositivo entra en la red con una dirección de cero. Se le asigna una dirección 1-127 durante la enumeración. Luego descarta todos los paquetes que no tienen la dirección correcta en el encabezado. Para USB 1.1 de velocidad baja y completa, el bus cambia de un lado a otro paquete por paquete, los dispositivos descartan los paquetes que son demasiado rápidos para ellos. Super Speed ​​usa cables separados para un tráfico más rápido, en paralelo con el autobús más lento. No estoy seguro de cómo funciona una velocidad baja/completa y alta combinada, creo que podría ser un caso inusual en el que el concentrador almacena en búfer y retransmite mensajes.
@DaveTweed, en USB 2.0, el tráfico se transmite a todos los puertos de bajada. Si un dispositivo es LS o FS, es una historia diferente: se manejan desde dentro del concentrador utilizando búferes locales y traductores de transacciones, que están controlados por mensajes HS llamados "transacciones divididas". Todos los concentradores y dispositivos HS reciben estos mensajes, pero los descartan si la dirección del paquete no encaja.
El bus USB 2.0 no "cambia de un lado a otro por paquete", examine el concepto de TT: traductores de transacciones en la arquitectura USB 2.0.
@Ale..chenski No dije que sí. USB 2.0 es de alta velocidad. El cambio de ida y vuelta ocurre con dispositivos de baja y máxima velocidad (es decir, USB 1) en una red USB 1.1.

No, no puede dividir USB, pero ¿qué le impide conectar los pines de recepción UART de dos Arduinos juntos para que ambos reciban los mismos datos UART, o hacer que el primer Arduino envíe comandos que no entiende al otro Arduino?

Ambos son posibles y probablemente uniré las líneas Rx al final, pero esperaba una solución simple que no requiera ninguna modificación en el controlador existente.

¿Puedo usar USB de forma pasiva, solo como oyente, con el segundo controlador?

Técnicamente sí, puede construir un dispositivo que mire pasivamente el tráfico USB y pueda obtener información de él y tomar cualquier acción. De hecho, dispositivos como ese existen. Se denominan "Analizadores de protocolo USB".

La arquitectura típica de tales dispositivos consiste en un sniffer no invasivo en líneas D+/D- (divisor de voltaje de alta impedancia más amplificador de banda ancha con compensación de ganancia), que alimentan un PHY USB estándar (autónomo). La interfaz de salida en serie-paralelo del PHY (ULPI, UTMI o PIPE3) luego es observada/registrada por un FPGA de gran tamaño que tiene herramientas de decodificación y puede desencadenar eventos de protocolo USB. Ejemplos: Teledyne-LeCroy , Ellisys .

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Para que pueda ver el tráfico USB y obtener datos. Para obtenerlos en tiempo real, deberá programar FPGA y ejecutarlo a una frecuencia de reloj suficiente para implementar la mayoría de los elementos del motor de interfaz serie USB (excepto la formación de respuestas ACK/NAK).

Una solución podría ser implementar esencialmente una topología en serie local encadenada de Arduinos. Uno de estos en el 'frente' de la cadena expondría su interfaz USB CDC. Luego, conectaría un par de pines configurados para SoftwareSerial a los pines Serial del siguiente Arduino (D0/D1) y así sucesivamente. Luego, podría repetir el tráfico en serie recibido hacia arriba y hacia abajo de la cadena según sea necesario, con cada miembro de la cadena decidiendo si debe responder según corresponda.

Solo lea los comentarios, y lo que propongo aquí es bastante similar a lo que @ pjc50 estaba buscando.
Gracias, he decidido que el único método práctico es unir las dos líneas Rx. Significa modificar físicamente el controlador original, pero eso parece inevitable.