¿Cómo programo 2 nodos CAN para transmitir continuamente en sucesión?

Supongamos que tengo tres nodos CAN: A, B y C. Sabemos que cuando dos nodos transmiten al mismo tiempo, el nodo que tiene menos SID prevalecerá sobre el bus y el otro nodo tendrá que ceder el bus al primero. nodo. Lo que me gustaría hacer es que el nodo B y C envíen continuamente tramas CAN al nodo A en sucesión (por ejemplo, nodo B -> nodo A, nodo C -> nodo A, nodo B -> nodo A). ¿Puedo simplemente asignar un SID más bajo a B que a C y simplemente hacer el siguiente fragmento de código?

Nodo B

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Nodo C

while(1) sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);

Dentro de sendCANmsg, aquí está el fragmento:

TXB0CONbits.TXREQ = 1;  // Request Message Transmission
while (TXB0CONbits.TXREQ); // Wait until message is sent.

Por cierto, estoy usando PIC18F25k80 para implementar esto. Estaba pensando que después de que el nodo B envió el mensaje, cuando el nodo C está a punto de enviar su mensaje. El nodo B volverá a ganar el arbitraje del bus, lo que le dará al nodo C ninguna posibilidad de transmisión. Entonces, el remedio que solo se me ocurre es insertar un pequeño retraso como:

while(1) {
    sendCANmsg(data, NODE_A, sizeof(data), RTR_OFF);
    delay_us(10);
}

¿O estoy equivocado? :)

Respuestas (2)

Dado que este método acerca el bus al 100 % de utilización, supondremos que estos 3 nodos son los únicos en el bus. Según su tiempo de retraso de 10 µs, también asumimos que la velocidad del bus es de 500 kbps (es decir, 5 bits de retraso, o 1 bit menos que la espera posterior al arbitraje entre mensajes).

Que el método funcione o no depende en gran medida de los detalles de implementación de su controlador CAN. Una forma más confiable de lograr esto sería tener el nodo B y C esperando para leer el mensaje del otro antes de enviarlo (con el nodo B transmitiendo inicialmente sin esperar). ES DECIR:

  1. Despertar
  2. El nodo C espera el mensaje B
  3. El nodo B transmite
  4. El nodo B espera el mensaje C
  5. El nodo C transmite
  6. El nodo C espera el mensaje B
  7. Etc.

Para tener en cuenta la desincronización, cada período de espera debe tener un tiempo de espera, después del cual el nodo transmite independientemente de si recibió el mensaje del otro nodo.

Esto equilibrará la utilización del bus y dejará que cada controlador pueda realizar otras tareas mientras espera el mensaje (en lugar de intentar transmitir continuamente en caso de una pérdida de arbitraje).

Tenga en cuenta que este es un uso no convencional de CAN. Es posible que le sirva mejor un protocolo más simple, como SPI (el nodo A tendría que sondear a B y C, pero no tendría que haber arbitraje, y todo podría ser DMA y/o controlado por interrupciones).

Gracias por su respuesta. :) Me acabo de dar cuenta de que puedo usar los filtros de aceptación solo para esa implementación (por ejemplo, detectar si el otro nodo ha enviado un mensaje CAN). Sin embargo, solo hay 6 filtros de aceptación en PICf25k80 y 2 máscaras de aceptación. Si la red CAN se vuelve más grande, en algún lugar menor pero cercano a 2^11 - 1, ¿serán suficientes los filtros y las máscaras de aceptación? Me gustaría escuchar el uso convencional de CAN. :)
No estoy seguro de lo que quieres decir cuando dices "menos que pero cerca de 2^11-1". Existe un límite práctico en la cantidad de nodos que se pueden conectar a un solo bus CAN debido a la carga capacitiva; por lo general, es un poco más de 100 nodos. Un uso más convencional de CAN sería un entorno controlado por eventos (con opciones de sondeo y algunos mensajes poco frecuentes de tipo latido). La idea es mantener la utilización del bus lo más baja posible, aunque eso se vuelve más difícil a medida que se agregan más nodos al bus. Su escenario es más como una bebida de la manguera contra incendios, con actualizaciones continuas ametralladoras.
Culpa mía. Debería haber dicho en algún lugar entre 0 y 2^11-1. Debido a que el SID tiene una longitud de 11 bits, creo que el límite de la red CAN es 2^11-1. Gracias por señalarlo. Solo quiero saber qué pasaría si se disparara continuamente. Mi implementación real es que tengo 6 nodos, pero solo un nodo recopila los datos de los otros 5 nodos. Así que mi plan es que los otros 5 nodos se envíen sucesivamente al nodo colector cada n milisegundos. ¿Qué opinas? ¿Es RTR una mejor opción?
La pregunta es realmente si necesita actualizaciones con tanta frecuencia. En el caso de que el "maestro" (nodo de recopilación de datos) solo necesite actualizaciones esporádicas y un pequeño retraso sea aceptable, RTR tiene sentido. Si el maestro necesita acceso inmediato al valor actual, pero los valores cambian lentamente, entonces los otros nodos podrían simplemente enviar mensajes cada vez que haya un cambio. Si los valores cambian lo suficientemente rápido, aumentarán la utilización del bus y puede ser valioso que envíen el estilo de todos contra todos, como ha sugerido. Solo tenga en cuenta que el round-robin no es el escenario para el que se diseñó CAN.
Tiene perfecto sentido ahora. Olvidé que cada nodo tiene diferentes procesos antes de transmitir sus datos al nodo colector. Tiene sentido transmitir solo cuando hay un cambio. Gracias Señor :)

Primero, los nodos no tienen ID, los mensajes sí.

Esto es complicado y no es para lo que se diseñó CAN. Debería funcionar si cada nodo se retrasa deliberadamente un poco después de cada transmisión exitosa. No recuerdo si el hardware PIC 18F25K80 le permite saber cuándo se envía realmente un marco, pero probablemente lo haga. El otro nodo solo necesita una pequeña ventana para ver el final del cuadro y comenzar a transmitir. Una vez que este segundo nodo comience a transmitir, el primero retrasará su mensaje hasta el próximo final del marco automáticamente de todos modos.

Sin embargo, esto suena como un abuso del bus CAN, y una mejor respuesta podría ser repensar la arquitectura general.

Gracias por su respuesta. Estoy corregido. Cometí un error al afirmar que los nodos tienen ID. Lo lamento. De todos modos, ¿cuál sería esa arquitectura? :)
Por cierto, con respecto a lo que dijiste, debería funcionar si cada nodo se retrasa deliberadamente un poco después de cada transmisión exitosa y una vez que este segundo nodo comience a transmitir, el primero retrasará su mensaje hasta el próximo final del marco automáticamente de todos modos. ¿Significa que funcionaría si solo insertara un pequeño retraso en el Nodo B solamente, ya que después de transmitir el mensaje CAN desde el Nodo C, el nodo B ganará el arbitraje de todos modos?
@Xegara: Sí, no es necesario que se demore al intentar enviar el mensaje de menor prioridad.
Oh, es bueno. Usted mencionó que este tipo de implementación no es para la que CAN fue diseñado. Me gustaría saber más sobre la correcta implementación de CAN. ¿Dónde empiezo? :)
CAN está bien diseñado para varios nodos, cada uno con requisitos de ancho de banda relativamente bajos (en comparación con Ethernet, por ejemplo). Pueden volar muchos mensajes, y cada nodo escucha solo lo que le importa. Parece que tiene un controlador y dos nodos de datos dedicados. Esto podría funcionar mejor con algo como SPI, donde el maestro controla directamente cuándo cada nodo envía datos. ¿Por qué cree que CAN es apropiado para su caso?
Acabo de citar un escenario para atender a mi pregunta. Mi implementación real es que tengo 6 nodos, pero solo un nodo recopila los datos de los otros 5 nodos. Así que mi plan es que los otros 5 nodos se envíen sucesivamente al nodo colector cada n milisegundos. Además, la característica de CAN es que puedo simplemente agregar otro nodo sin reprogramar el CAN de los otros nodos, lo que lo hace muy flexible. ¿Qué opinas?