Comunicación Arduino múltiple (1 maestro, n esclavos)

Me gustaría desarrollar una red maestro/esclavo que consista en:

  • 1 maestro Arduino que lee sensores y genera perfiles de rampa de velocidad basados ​​en las señales del sensor y luego envía esas rampas a los esclavos

  • 3 (o más) esclavos Arduino que controlan la velocidad de servomotores de 12V siguiendo las rampas enviadas por el maestro

¿Cuál es un buen protocolo de comunicación para lograr esto? Serie (SPI)? ¿I2C? ¿Algo más? Si es de serie, ¿el nuevo Arduino Leonardo es una buena elección? ¿Qué aspectos debo tener en cuenta al seleccionar un protocolo?

Me estoy imaginando algo como:

Maestro:

void loop() {
    update_ramps()
    for(int i=0; i< num_slaves; i++) {
        send_to_all(i, ramps[i]);
    }
}

Esclavo 1:

const int id = 1;
int recived_id, recived_value;
void loop() {
    read_data();
    if(recived_id == id) { 
        do_motor_step(recived_value);
    }
}

Y comunicación serie en la que RX/TX del maestro se envía a todos los esclavos.

¿Parece una solución razonable?

¿Solo quieres enviar exactamente la misma información a todos los esclavos? ¿Los esclavos necesitan responder en absoluto?
¡No, no es necesario que respondan!
¿A qué distancia estarán los esclavos?
creo que no mas de 15 metros

Respuestas (5)

Según tengo entendido, desea enviar datos diferentes a cada uno de los esclavos, pero los esclavos no tienen que devolver los datos.

I2C es un bus direccionado, por lo que si asigna una dirección I2C diferente a cada uno de los esclavos, solo necesitará dos cables para enviar los datos. Si es necesario, también puede solicitar la devolución de datos. Los AVR de Arduino tienen un bus serie compatible con I2C. Y puede ampliar a más de 3 esclavos sin hardware adicional, hasta un máximo de 127.

Los UART no tienen direccionamiento, por lo que necesitaría 3 UART (que el AVR no tiene) o agregar una lógica externa para cambiar entre líneas UART (que cuesta dinero). Cada esclavo adicional significa un costo adicional. No recomendado.
editar
Como dice Chris, puedes usar UART para crear un bus multipunto. Y luego tendrá que agregar direccionamiento, lo que hace que su UART funcione un poco como I2C, pero asíncrono y sin hardware de coincidencia de direcciones como el que tiene I2C. Así que todavía no es realmente una ventaja. fin de edición

SPI también usa líneas compartidas para datos: un solo MOSI y las líneas MISO conectadas. Para dirigirse a cada esclavo individualmente, necesitará una línea SS (Slave Select) por esclavo. Eso es al menos 5 E/S: MOSI, SCK, 3 × SS y MISO si también desea leer datos de los esclavos. Cada esclavo adicional agrega 1 pin de E/S en el maestro.

ingrese la descripción de la imagen aquí

Creo que el I2C es la mejor solución, ya que requiere la menor cantidad de cables. El protocolo es un poco más complejo que UART o SPI, pero dado que el AVR tiene el hardware necesario, debería ser fácil de usar.

La afirmación de que se requerirían múltiples UART o lógica externa no es precisa. La comunicación UART en bus se realiza todo el tiempo, utilizando direccionamiento de software. Con transmisión y recepción compartidas, esto no requiere más pines que I2C.
@Chris: buen punto, actualizaré mi respuesta.
Todavía estoy aprendiendo cómo funcionan estas cosas y tengo curiosidad acerca de SPI. Cuando dijiste que solo necesita un pin MOSI y uno MISO para conectar tres esclavos, me confundí un poco. Para cada Arduino esclavo, ¿se conectarían sus pines MOSI y MISO al Arduino maestro? Entonces, ¿el Arduino maestro tendría tres cables saliendo de su pin MOSI y tres entrando en su pin MISO? Y con el pin SS, simplemente elige a qué esclavo desea enviar datos. Gracias.
@capcom: agregué un diagrama de bloques para el SPI. MOSI es salida para el maestro y entrada para los esclavos. MISO es salida para los esclavos y entrada para el maestro. Sí, hace que el SS sea bajo para el esclavo al que desea enviar datos. El SS no solo sirve para indicar el inicio y el final de la comunicación, sino que también un esclavo no seleccionado debe hacer que su MISO sea de alta impedancia para evitar conflictos de bus.
gracias por la respuesta precisa y clara, como siempre, steve. no ha mencionado el software en serie, creo que debería ser una opción ... ¿qué opina? y: tengo que impulsar motores en los esclavos, por lo que cualquier retraso puede variar la velocidad de los motores (y esto es malo). ¿Algún problema de retraso al usar uno de esos protocolos?
Todavía confundido en el UART. No se necesita hardware externo para el transporte, ya que el pin UART TX se puede probar en el software. En general, la señalización de tipo UART a través de una red en bus se consideraría ventajosa cuando se comunica entre chasis separados; a diferencia de I2C, está diseñado para tal propósito y se usa de manera estándar allí. Si agrega controladores/receptores de línea, puede manejar tramos de cable bastante largos.
@Chris - Correcto otra vez. No sé qué estaba fumando cuando escribí eso, ¡lo he hecho a menudo! :-(
lo siento, una cosa más: tengo que enchufar el esclavo a una distancia de 8 m... ¿alguna recomendación para esta distancia? tengo problemas con i2c
@nkint: 8 m tendrán una capacitancia de alrededor de 800 pF, e I2C solo permite 400 pF para obtener la velocidad de borde requerida. Tendrá que usar un extensor de bus como el P82B715 , que conducirá el bus en hasta 50 m de cable.
como se sugiere en otra pregunta, he intentado reducir la velocidad en baudios de i2c cambiando alguna línea de la biblioteca que estoy usando con Arduino (Wire). parece funcionar... ¿Quizás con otros protocolos no tengo el mismo problema?
@stevenvh, el P82B715 funciona muy bien y es realmente fácil de enchufar.

¿Supongo que por serie te refieres a UART? Tenga en cuenta que UART, SPI, I2C son todos protocolos en serie.

SPI o I2C estarían bien para esto, ya que ambos usan la arquitectura maestro/esclavo.
Sin incluir tierra, para 3 esclavos, SPI requeriría 6 pines (MOSI, MISO, CLK + 3 pines SS) e I2C solo dos (SDA y SCK)
Probablemente elegiría I2C, asumiendo que no necesita una transferencia de datos muy alta tasas (<400kHz)

Cuantos más esclavos agregue, menos conveniente es SPI, ya que necesita otro SS (selección de esclavo) para cada nuevo esclavo. Con I2C, esto no es un problema ya que el direccionamiento es parte del protocolo, por lo que solo necesita las 2 líneas (más tierra).

Para Arduino, debería haber una gran cantidad de tutoriales con bibliotecas I2C/SPI y código de ejemplo para los dos anteriores, lo que debería hacer que sea bastante fácil de poner en marcha.

Tienes razón, los datos son diferentes para cada esclavo. Me engañó el nombre de la función "send_to_all", pero parece usar una rampa diferente para cada uno (están indexados). Borré mi primera respuesta.

También deberían ser posibles esquemas de señalización asíncrona compartida similares a RS485.

Si no está utilizando controladores/receptores de línea (solo los pines ATMEGA desnudos), debe convertir el UART TX en una entrada cuando no sea su turno de hablar. Si está utilizando controladores de línea, necesita usar un pin adicional para controlar la habilitación de tres estados en el controlador de línea cuando no es su turno de hablar.

También tenga en cuenta que no puede simplemente probar el transmisor cuando se acepta el último byte en el registro de transmisión (el punto en el que podría enviar otro carácter); en su lugar, debe asegurarse de mantener el transmisor o el controlador de línea habilitado hasta que se haya completado la palabra. desplazado por completo.

En los esquemas donde transmites y recibes por el mismo cable (o par diferencial) ten en cuenta que escucharás tus propias transmisiones.

En el caso especial que desee conectarse a través de UART , puede utilizar UART RS485 MODBUS . Este es un protocolo de comunicación con direcciones de software, función, suma de verificación.

PIENSO : es más confiable que I²C o SPI debido a RS-485 y usa menos cables que SPI.

NOTA: Puede implementarse como estándar, con algunas bibliotecas , pero puede ser costoso ya que necesita un módulo RS485 para cada esclavo y uno para el maestro, PERO es compatible con una red existente. Pero puede hacerlo menos costoso utilizando componentes heredados y fabricando su propio dispositivo. El MAX 485 podría ser el componente base para hacer un bus Hardware 485 o usando un software RS485

La solución más simple para los requisitos específicos sería un transmisor RS-422 en una línea TX en el maestro (controlador de bus). Esto se extendería a múltiples receptores (terminales remotas).

Todos los RT escucharían los mensajes de transmisión, pero solo autenticarían y ejecutarían los comandos dirigidos a él a través de la dirección RT.

Si se usara un protocolo de bus similar al 1553, sería fácil de implementar.