9
\$\begingroup\$

I would like to develop a master/slave network that consists of:

  • 1 Arduino master that reads sensors and generates velocity ramp profiles based on the sensor signals and then sends those ramps to slaves

  • 3 (or more) Arduino slaves that control the velocity of 12V servo motors following the ramps sent by the master

What is a good communication protocol to achieve this? Serial (SPI)? I2C? Something else? If it is serial, is the new Arduino Leonardo a good choice? What issues should I be considering in selecting a protocol?

I'm imagining something like:

Master:

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

Slave 1:

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

And serial communication in which RX/TX from the master is sent to all slaves.

Does this seem like a reasonable solution?

\$\endgroup\$
4
  • \$\begingroup\$ You just want to send exactly the same info to all slaves? Do the slaves need to respond at all? \$\endgroup\$
    – Oli Glaser
    Aug 2, 2012 at 23:54
  • \$\begingroup\$ no they doesn't need to respond! \$\endgroup\$
    – nkint
    Aug 3, 2012 at 7:14
  • \$\begingroup\$ how far away will the slaves be? \$\endgroup\$ Aug 5, 2012 at 8:16
  • \$\begingroup\$ i think no more then 15 meters \$\endgroup\$
    – nkint
    Aug 5, 2012 at 19:34

5 Answers 5

12
\$\begingroup\$

As I understand it you want to send different data to each of the slaves, but the slaves don't have to send data back.

I2C is an addressed bus, so if you assign a different I2C address to each of the slaves you'll need only two wires to send the data. If needed you can ask data back as well. The Arduino's AVRs have an I2C compatible serial bus. And you can extend to more than 3 slaves without extra hardware, up to a maximum of 127.

UARTs don't have addressing, so you would need either 3 UARTs (which the AVR doesn't have), or add external logic to switch between UART lines (which costs money). Each additional slave means extra cost. Not recommended.
edit
Like Chris says you can use UART to create a multidrop bus. And then you'll have to add addressing, which makes your UART work a bit like I2C, but then asynchronous, and without address matching hardware like the I2C has. So still not really an advantage. end of edit

SPI also uses shared lines for data: a single MOSI, and the MISO lines connected. To address each slave individually you'll need one SS (Slave Select) line per slave. So that's at least 5 I/Os: MOSI, SCK, 3 \$\times\$ SS, and MISO if you also want to read data from the slaves. Each additional slave adds 1 I/O pin on the master.

enter image description here

I think the I2C is the best solution, requiring the least number of wires. The protocol is a bit more complex than UART or SPI, but since the AVR has the hardware for it, it should be easy to use.

\$\endgroup\$
12
  • 2
    \$\begingroup\$ The claim that multiple UARTs or external logic would be required is not accurate. Bussed UART communication is done all the time, using software addressing. With shared transmit and receive, this requires no more pins than I2C. \$\endgroup\$ Aug 3, 2012 at 14:13
  • \$\begingroup\$ @Chris - Good point, I'll update my answer. \$\endgroup\$
    – stevenvh
    Aug 3, 2012 at 14:15
  • 1
    \$\begingroup\$ @capcom - I added a block diagram for the SPI. MOSI is output for the master, and input for the slaves. MISO is output for the slaves and input for the master. Yes, you make the SS low for the slave you want to send data to. The SS not only serves to indicate start and end of communication, but also a not-selected slave should make its MISO high-impedance to about bus conflicts. \$\endgroup\$
    – stevenvh
    Aug 3, 2012 at 14:27
  • 2
    \$\begingroup\$ @nkint - 8 m will have a capacitance around 800 pF, and I2C only allows 400 pF to get the required edge speed. You'll have to use a bus extender like the P82B715, which will drive the bus on up to 50 m of cable. \$\endgroup\$
    – stevenvh
    Oct 6, 2012 at 8:55
  • 1
    \$\begingroup\$ @stevenvh the P82B715 works great and it is really easy to plug! \$\endgroup\$
    – nkint
    Dec 2, 2012 at 8:03
5
\$\begingroup\$

I'm assuming by serial you mean UART? Note that UART, SPI, I2C are all serial protocols.

SPI or I2C would be fine for this as they both use the master/slave architecture.
Not including ground, for 3 slaves, SPI would require 6 pins (MOSI, MISO, CLK + 3 SS pins) and I2C just two (SDA and SCK)
I'd probably pick I2C, assuming you don't need very high data transfer rates (<400kHz)

The more slaves you add, the less convenient SPI is, as you need another SS (slave select) for each new slave. With I2C, this isn't a problem as the addressing is part of the protocol, so you still only need the 2 lines (plus ground).

For Arduino, there should be a whole host of tutorials with I2C/SPI libraries and example code out there for both of the above, which should make it pretty painless to get up and running.

\$\endgroup\$
1
  • \$\begingroup\$ You're right, the data is different for each slave. I was misled by the name of the "send_to_all" function, but it seems to use a different ramp for each (they're indexed). I deleted my first answer. \$\endgroup\$
    – stevenvh
    Aug 3, 2012 at 7:23
2
\$\begingroup\$

Shared asynchronous signalling schemes similar to RS485 should also be possible.

If you are not using line drivers/receivers (just the bare ATMEGA pins) you have to make the UART TX an input when it's not your turn to talk. If you are using line drivers, you need to use an additional pin to control the tristate enable on the line driver when it is not your turn to talk.

Also beware that you cannot just tristate the transmitter when the last byte is accepted into the transmit register (the point when you could send another character), instead, you have to make sure to keep the transmitter or line driver enabled until the word has been fully shifted out.

In the schemes where you transmit and receive on the same wire (or differential pair) take into account that you will hear your own transmissions.

\$\endgroup\$
2
\$\begingroup\$

On the special case you want to connect via UART, you can use the UART RS485 MODBUS. This is a communication protocol with software addresses, function, checksum.

I THINK : It is more reliable than I²C or SPI due to RS-485 and uses less wires than SPI.

NOTE : It can be implemented as the standard, with some libraries but it can be expensive as you need an RS485 module for every slave and one for the master, BUT it is compatible with an existing network. But you can do it less expensive by using legacy components and making your own device. The MAX 485 could be the base component to make an Hardware 485 bus or by using a software RS485

\$\endgroup\$
0
\$\begingroup\$

The simplest solution to the specific requirements would be a RS-422 transmitter on a TX line on the master (Bus Controller) This would fan-out to the multiple receivers (Remote Terminals).

All RTs would hear the broadcast messages but would only authenticate & execute those commands directed to it via the RT address.

If a bus protocol similar to 1553 was used it would be easy to implement.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.