Communication between a number of Arduino's?

Hi everyone,

I've undertaken a project that requires me to light up 5 or more LED's on a sign, with 5 signs.

Quick diagram to help explain:

Sign ------- Sign -------- Sign -------------------- Controller --------------------------------------Sign ------- Sign

|-----3m-----|-----3m----|------------7m-------------|--------------------10m--------------------|----3m-----|

Basically, each "sign" entails 3 led strips. There is also 2 LED's, and a buzzer. Each sign will only have one LED strip on at a time. The banks of lights are split physically by a divider, so I'm addressing these as 'left bank' and 'right bank' of lights.

My problem is, there are TOO MANY communication options. What I had in mind was either a barebones Arduino (RBBB or a Diavolino or similar) at each sign, and then an Uno at the "controller". I've got 6 core alarm cable running in a chain from the leftmost sign to the rightmost sign, however 4 of those cables I'd like to use for power. I can run more cable if need be.

I'm not looking for super-high data speeds either, just ideally if someone flicks a switch on the controller, the lights are updated within the second.

My question is, what is the best way to control all these?
-SPI communication? The master outputs a long serial string for each bank. Each sign then extracts the information it requires and then sends serial to the next ardiuno.

-I2C? I'm not sure on the hardware limits (i.e. bus length) of this protocol, but I've got 2 data lines plus a ground line already wired. It can't be too hard to bit bang commands out.

-ShiftOut/ShiftIn? I've contemplated just shifting out a long string of data every second or so, and having each device extract it's info and pass it onto the next device. If this is the case, do I even need Arduino's?

-OneWire? Someone mentioned this might be a possibility, but it isn't easy to implement.

(edit)
-RS485? I've also heard good things about this protocol, such as it's reliability.
(/edit)

Can any kings (and queens!) of Arduino shed some light and wisdom of the optimal communications protocol I should be using? As long as it's fairly reliable (the occasional flicker is acceptable, it's not exactly mission-critical), I'm not too fussed.

Thanks in advance!

SPI and shiftOut are essentially the same thing. You could use them and have shift regs at each sign. This will need 3 wires + GND/PWR.

I2C is not really designed for these lengths although there are extender chips. 2 wires + GND/PWR.

1-wire can be used here I think as long as you don't use parasitic power, I don't know much about it though. You would need some 1W port expander chips if that exist (I'm sure they do). 1 wire + GND/PWR.

You didn't mention async serial. 1 wire + GND/PWR.

RS-485 is not a "protocol", it's a spec for the physical interface. It is specifically designed for such projects. You could use it with SPI for example or with async serial.

So, if you are happy to have a RBBB at each sign I'd use RS-485 with async serial and multi-drop all the displays off the one line. 2 wires + GND/PWR.

That's my preferrence but an I2C or 1W guru will probably have different ideas :slight_smile:


Rob

Fudge:
My question is, what is the best way to control all these?
-SPI communication? The master outputs a long serial string for each bank. Each sign then extracts the information it requires and then sends serial to the next ardiuno.

SPI could work but you'll need to drop the speed way down because of the long wires.

Fudge:
-ShiftOut/ShiftIn? I've contemplated just shifting out a long string of data every second or so, and having each device extract it's info and pass it onto the next device. If this is the case, do I even need Arduino's?

If it was me I'd do it this way. Using the Arduino as an SPI slave is tricky. It's also easy to set the size of the word transmitted.

You'll need three wires. One to mark the start of a transmission (eg. when it goes low, that's the start), another one for clock and another one for data. After that it's mostly just a case of fiddling to find a clock speed that works reliably. You probably don't need to get each Arduino to pass the message along, just get them all to listen to the master directly. You probably ought to add transistors to the master Arduino's output pins to pull the lines low more reliably (depending on your cable).

One good thing about using shiftOut() is that you don't even need Arduinos at the signs, just shift registers.


Rob

Having those distances I would definitly go for RS485.

Take a look here:

Fudge:
As long as it's fairly reliable (the occasional flicker is acceptable, it's not exactly mission-critical), I'm not too fussed.

Async serial should do fine. You only need 2 wires (Tx from the controller to Rx on each slave) plus Gnd. In other words, all slaves will "listen" and the controller will "talk". You then just send something like "slave 3, show xyz".

A low baud rate will compensate for any capacitance on the line, and probably a RS485 driver chip at each end will help with the long distances.

Thanks for all the help everyone. I'm tossing up between serial and shiftout. Shifting bits would be easier and cheaper as I don't need more Arduino's, but I think serial is the way to go. In the future, if the signs ever get upgraded (LED Matrix anyone?), it would be nice to be able to send more than on/off signals. Plus, I won't have to run more cables that way :smiley:

(edit)

Forgot to ask, are 485 driver chips a necessity? I imagine I only need one per serial "string", correct?

Try it and see. I am guessing that after a few (tens of) meters the 5V signal might degrade (due to resistance) too low to register. But depending on the cables it might work. In which case serial and shifting would be the same cost.

Mind you, for 13m, it might just work "raw".

Yes they are necessary if you are using RS485.

You need one transmitter for the master and a receiver for each slave. As they don't sell transmitters and receivers separately that means one "transceiver" for every Arduino (node).

If you use shift regs that will be 3 transceivers for every node.


Rob

This could be a job for "BreakWire LAN"!

... a simple "LAN" where just two wires go from machine to machine to machine, and the "LAN interface" is just two opto-isolators at each machine. Actually, for your app, you'd only need one opto isolator.

That's the good news.

The bad news is that "BreakWire LAN" is nothing more than a discussion paper, so far. But for your app, it would give you LOTS of what you need.

PS- sorry about the typo that was in the URL until a moment ago, and, in light of a comment below, which is quite right!, I should stress that this is a very, very simple "LAN". It won't do to run the Toyota assembly line, but it might give a hobbyist some fun! It may be that going with the RS-485 interface discussed below has advantages over what I have suggested.... I'm not sure if it allows the sort of things that "BreakWire" allows... i.e. just two wires between nodes, peer-to-peer, and no (fatal) problems in the event of two clients trying to transmit at the same time.

"BreakWire LAN"

Interesting, a lot of limitations but has potential for a simple network. I like that the nodes are isolated.


Rob

As a proof of concept I wired together two Arduinos using RS485 transceivers (LTC1480CN) which cost me around $6 each.

Assuming for the moment that I had one transmitter and multiple receivers I set up the receivers for “receive only” (by grounding the DE pin).

Master (controller) sketch was:

#include <NewSoftSerial.h>

NewSoftSerial rs485 (2, 3);  // receive pin, transmit pin

void setup()
{
  rs485.begin(28800);
  pinMode (4, OUTPUT);  // driver output enable
  digitalWrite (4, HIGH);  // enable sending
}

long counter;

void loop()
{
  rs485.print (++counter, DEC);
  rs485.println (" - hello world.");
  delay (500);
}  // end of loop

Receiving end:

#include <NewSoftSerial.h>

NewSoftSerial rs485 (2, 3);  // receive pin, transmit pin

void setup()
{
  Serial.begin (115200);
  rs485.begin(28800);
}

void loop()
{
 if (rs485.available ())
   Serial.print ((char) rs485.read ());
}  // end of loop

That appeared to work fine at 28800 baud, which should be fine for sending messages to signs. I had 20m of cable (just ordinary speaker cable, not twisted, not shielded) in the middle, which is well over what the OP wanted between controller and slave.

My only slight doubt is that the transceiver was supposed to work on 3.3V, with an absolute maximum rating of 7V VCC, and I was putting 5V into it.

If you needed to get responses back it would be a bit more complex, but you could address each slave and do something like “slave 3, what is the temperature?” and then turn off output enable at the master end, and turn on output enable at the slave end, for the duration of the response.

Further tests reveal that with the 20 m cable, I could crank the baud rate up to 57600, seemingly without error. Of course, a noisy path might influence that a bit.

Also it's worth noting that you connect A to A, and B to B (pins 6 and 7) together when wiring the transceivers up. You don't swap them over like you do with Rx and Tx.

In you should be able to do 10Mbps with a short cable like this (even up to 35Mbps according to what you read and what drivers you use) and 100kbps for lengths up to 1.2k. So it's the Arduino that will struggle, not the drivers although the cable presumably makes a difference as well.


Rob

Well even normal serial maxed out to 115200 baud is only 115.2 Kbps, well short of 10 Mbps.

I've been asked a few questions privately which I will respond to here, as they are interesting:

a) Can you hang multiple devices on the two wires between, on your drawing, the master and slave? (As envisioned for the "BreakWire LAN")

Yes, absolutely. Although I haven't tested it this Wikipedia page makes it clear that this is an intended use:

What I haven't done, and I wondered about that, was put in some sort of bias resistors (pull-up/pull-down) to make sure that the network has a known state if no device is addressing it. That is probably very sensible. See the diagram on the Wikipedia page.

b) Can you have a "masterless" net, if you overcome all that must be overcome in software? In other words, do you NEED a "master" somewhere, because of some hardware issue? (I do understand that having a master would make the software side much, much easier.)

I see no hardware reason not to. The point of having a master is to solve contention, so that the master is "in charge". But until the master decides to do something effectively electrically they are all equal.

c) Will the circuits be damaged if two devices try to transmit at the same time?

According to the datasheet for the LTC1480 they anticipate that this might happen, and the device is designed to handle it (that is, not fail).

d) Can the interface chip simultaneously send data and monitor what is appearing on the data lines, i.e. the lines connected to pins 6 and 7?

Not the chip, I suppose you could connect the output of it back into the Arduino's digital inputs. I'm not sure what you would gain, as timing would be critical. I think the I2C hardware has some provision for that, that is "is what I am setting the lines to actually what they are doing?".

I would keep things simple if possible, and have a master, even if the master "chooses itself" at runtime. That is, when a device powers up, if it doesn't "hear" anything for a second it could assume that it is the first one, and try to become the master.

No doubt there are ways, but for the simple application of something like a home security system, or driving some signs from a central point, there is probably not much point to it.

(Oops! this crossed the ABOVE post "in the mail"... that is, they were both being typed at the same time... this paragraph added later.)

====
Thank you, Nick, for the work on the RS-485. (And for the reply to my offline message!)

A few questions arise... I've given them letter IDs to make (I hope) further discussion easier....

You've drawn what I'm hoping is just an example.... a "master" and a single "slave".

Having one participant in the LAN as "master" makes a whole bunch of things easier, but, in hardware, is the "master" "special" in any way? (That was question "A") Could we, for the sake of an example, have two peers interconnected (Q.B), say one at my house and one at my neighbors. And if EITHER detected something amiss... e.g. an intruder into an "empty" house... it would send a message onto the LAN saying "Help, help! Ring the bells"?

And, assuming that much is okay, could there be three peers on the LAN, not just two? (Q.C)

===
Another area of concern....

Suppose it is okay to have three devices on the LAN. And suppose, by bad luck, two of them begin to send data onto the LAN at the same time? Is it able to endure such an event without problems? Without harm to the electronics? (Q.D) "Obviously" (to everyone, I imagine), if two devices are both trying to send, the signal in the LAN will be gibberish. Is there a way for each of the sending devices to "watch" the LAN, as it tries to send? A way for it to see that its message is clashing with another message? (Q.E) What the programmer sets the system up to DO about a collision is a different question, for another day. My question today is: Can the sending device "see" that a collision is taking place? (Q. E re-iterated.)

Thanks! RS-485 might be just the wheel that I don't need to re-invent!

is the "master" "special" in any way?

No, except that some sort of pull-up/pull-down resistors should probably be on the network somewhere.

Could we, for the sake of an example, have two peers interconnected (Q.B), say one at my house and one at my neighbors. And if EITHER detected something amiss...

Well, you could. In other words, everyone listens, and sometimes somebody talks. In this example, it would be unlikely burglars would break into two houses at the same millisecond.

could there be three peers on the LAN, not just two

Lots of them, I imagine.

Is it able to endure such an event without problems? Without harm to the electronics?

According to the datasheet, yes.

Can the sending device "see" that a collision is taking place?

I'm not sure about that. But what I would do is send a message, and await some sort of response. If you don't get a response, re-send it. Then I would add a randomizing interval (like TCP/IP does I think) so that both ends don't try to resend at the same moment.

But I don't see any real reason why you couldn't have a master/slave arrangement. Then the master controls who talks when (like a teacher in a classroom). That way everyone doesn't talk at once.

Plus, the master could query (eg. every 1/10 of a second) each slave: "is everything OK?". So the slave could reply "burglars!".

This is safer really anyway, because if the burglars cut the wire (or turned off the power) and you are relying upon the slave initiating the conversation, you can't tell the difference between silence (because the power or wire is cut) and silence because nothing is wrong.

I think Nick covered just about everything but I'll add a bit.

RS485 is restricted to 32 Unit Loads (ULs) and at first that meant 32 devices. These days however transceivers can be found that are 1/4 or even 1/8th UL, so you can have up to 256 devices on an RS485 line.

In a master/slave setup there is no physical difference between the two, well I suppose there can be but there doesn't have to be.

Reliable collision detection is difficult. The common way to do it is have every node read what it's writing (just leave the receiver enabled), this will probably allow the two offending nodes to detect each other but other nodes might have trouble. If the two nodes are transmitting say 50% out of phase the waveform will be severely deformed and other nodes won't know so they may receive crap.

Therefore you need a good protocol to deal with this.

Also, Nick has drawn the standard configuration, I don't know how that works with clash detection as I think the levels will be undefined and anyway it can't be good to have conflicting voltages being driven onto the wire. The transceivers probably handle that but it's not good practice IMO to design a system that expects this contention.

There is a different way of wiring the transmitter that gets around this problem but all in all this is a multi-master issue and master/slave is much easier.

Having said that I'm working on a multi master network at present

http://busnet.robgray.com/index.php

This originally had all the clash detection etc but it got too complicated so I've simplified it. Rather than a bus topology I have a ring topology. This is potentially more reliable (a cut cable has no affect on the network). This is a multi-master network, any node can transmit at any time and there are no clash issues etc. Also, when finished there will be no special code required on the host device (say the Arduino), just read and write from/to the I2C port. At least that's the theory :slight_smile:

RS-485 might be just the wheel that I don't need to re-invent!

All the above is not just an RS485 issue, the same applies to any transmission media so you can't get away from it :slight_smile: That BreakWire will have the same problem and many others that RS485 has dealt with.


Rob

Thank you all… lots of good stuff!

However, as for…

Then the master controls who talks when (like a teacher in a classroom).

You were never a teacher, were you? At least not of secondary or elementary school classes. <^_^>