Arduino Yun (Master) RS-485 communication with 2 Arduinos UNO (Slaves)

ShapeShifter:
You might be able to get away without a ground line, but it is a good idea to have it.

Agreed.

I couldn't find the diagram showing how a RS485 system could have a shared ground line without an explicit connection but I thought the text below summed it well (as did your reply).

The connection of ground may happen implicit, because the logic ground of all devices is connected to some global protective ground level. If this is nearly the same on all devices, an extra wire is not required.
If the ground levels are different, without an explicit connection all equalising currents run on the data lines, hence pass the logic circuits for transmit and receive. This can damage the devices, and often does over time.

The above quote is from this page.

I've used ST485 chips in a couple projects. Here's the pinout of the chip.

The RE and DE pins are often connected to a single I/O pin.

Thank you a lot for your help! :slight_smile:

I'm a software guy so everything that requires soldering scares me a bit. I'm afraid to break something.

ShapeShifter:
Do they all have to be connected by the same wire, using one port on the Yun? Or can you use two ports on the Yun, each one connected directly to one Uno?

I can use 2 ports on the Yun to communicate with Unos. And I'm using Ethernet port to connect to the Internet. I was hoping to use one of these modules for RS485:

RS-485 module

Sparkfun USB to RS-485 Converter

With the latter option I think that USB is connected to the Uno and RS485 transceiver connects to the Yun.

And I also assume that there are no problems with getting Arduino data from Linux side.

mityakoval:
I can use 2 ports on the Yun to communicate with Unos.
. . .

RS-485 module

The first link you posted will let you daisy chain the RS485 connections. You wouldn't need two ports to communicate the Unos. You will need a protocol to allow you to identify one of the Unos as the target device.

@DuaneGegn

And what about Sparkfun Converter? Can I connect two of them to Yun with screw terminals, for example, and use USBs to connect to Unos?

mityakoval:
Can I connect two of them to Yun with screw terminals, for example, and use USBs to connect to Unos?

No. That wouldn't work.

Both the Sparkfun board and the Uno are USB slave devices. You can't connect two USB slaves together. You need one to be a host.

mityakoval:
I can use 2 ports on the Yun to communicate with Unos.

Then you don't really need RS-485. While not overly complicated, using RS-485 does introduce some extra work for the hardware and the software. The advantages of RS-485 are:

  • being able to connect several slaves to a single host port
  • being able to send the signals over long wires
  • noise immunity

Since you can use two ports (4 pins) on the Yun, item 1 doesn't apply to you. And since you only need to go 2 to 3 meters, that's not considered a particularly long distance, so item 2 isn't an issue. That only leaves item 3: as long as you are using this in a lab or classroom, and don't need to run it on a factory floor with lots of heavy equipment around, item 3 is likely not an issue.

Given all that, there's really no reason you can't just hook them up directly without any line drivers. The system I mentioned above is hooked up like this: (simple wires between each system, no other chips or interfaces)

  • Yun pin D8 -- slave 1 pin D1 (Yun receive, slave 1 transmit)
  • Yun pin D9 -- slave 1 pin D0 (Yun transmit, slave 1 receive)
  • Yun pin D10 -- slave 2 pin D1 (Yun receive, slave 2 transmit)
  • Yun pin D11 -- slave 2 pin D0 (Yun transmit, slave 2 receive)
  • Grounds on all systems connected together

The only restrictions come from SoftwareSerial: both receive pins must be from the group 8, 9, 10, 11, MISO, MOSI, or SCK (transmit pins can be any pin) and you can't receive from both slaves at the same time (but you wouldn't be able to do that with a shared RS-485 line, either.) So you will need a polling scheme along the times of what I mentioned in my first replay to this thread.

There's nothing wrong with going with RS-485, but it may be overkill for this project, especially when you mention:

mityakoval:
I'm a software guy so everything that requires soldering scares me a bit. I'm afraid to break something.

ShapeShifter:
Then you don't really need RS-485. While not overly complicated, using RS-485 does introduce some extra work for the hardware and the software. The advantages of RS-485 are:

  • being able to connect several slaves to a single host port
  • being able to send the signals over long wires
  • noise immunity

Since you can use two ports (4 pins) on the Yun, item 1 doesn't apply to you. And since you only need to go 2 to 3 meters, that's not considered a particularly long distance, so item 2 isn't an issue. That only leaves item 3: as long as you are using this in a lab or classroom, and don't need to run it on a factory floor with lots of heavy equipment around, item 3 is likely not an issue.

Given all that, there's really no reason you can't just hook them up directly without any line drivers. The system I mentioned above is hooked up like this: (simple wires between each system, no other chips or interfaces)

  • Yun pin D8 -- slave 1 pin D1 (Yun receive, slave 1 transmit)
  • Yun pin D9 -- slave 1 pin D0 (Yun transmit, slave 1 receive)
  • Yun pin D10 -- slave 2 pin D1 (Yun receive, slave 2 transmit)
  • Yun pin D11 -- slave 2 pin D0 (Yun transmit, slave 2 receive)
  • Grounds on all systems connected together

The only restrictions come from SoftwareSerial: both receive pins must be from the group 8, 9, 10, 11, MISO, MOSI, or SCK (transmit pins can be any pin) and you can't receive from both slaves at the same time (but you wouldn't be able to do that with a shared RS-485 line, either.) So you will need a polling scheme along the times of what I mentioned in my first replay to this thread.

There's nothing wrong with going with RS-485, but it may be overkill for this project, especially when you mention:

Thank you, that's really helpful! So what you're saying is that I can use I2C and simple hook-up wires to set up communication between Arduinos?
This system will be placed in an office close to 2 computers. If I understand right the noise you are talking about is electro-magnetic field that can disturb the signal. I don't think there's a really strong one.
The length of the cables will be 3-3.5 meters max.

mityakoval:
Thank you, that's really helpful! So what you're saying is that I can use I2C and simple hook-up wires to set up communication between Arduinos?

NO, that's far too long a distance for unbuffered I2C. I'm talking about using two instances of SoftwareSerial on the master Yun, talking to the hardware serial ports on the remote slaves. The length (and quality) of the wires may affect the maximum speed you can use - if you run into transmission problems, slow it down some.

I have successfully used 19200 baud with 5 meter Cat5 cables (my first post said 15 meter, that was a typo) and I have had zero transmission errors. I used 19200 to be conservative - I haven't yet tested how fast I can go, primarily because the final hardware isn't built yet (my breadboard setup is somewhat fragile) and because I don't really need to go faster than that.

Re-read my first post to this thread (reply #4.) There are more details of this scheme there.

This system will be placed in an office close to 2 computers. If I understand right the noise you are talking about is electro-magnetic field that can disturb the signal. I don't think there's a really strong one.

No, you shouldn't be bad in a situation like that. The worst case is if you had old CRT monitors connected to those computers, that might be the biggest EMI you would find in that environment. I'm talking more about the situation where you're using it on a factory floor and running next to machines with large (tens of horsepower) motors and actuators.

It doesn't hurt anything to try: hook them up with the long lengths of wire and see if you can get them to talk. If it doesn't work well for you, you can always add the RS-485 interfaces - most of the code will be the same in either case. You will still need code on the Yun to poll over the SoftwareSerial port, and code on the remote nodes to listen for poll requests and send/receive data. If it should turn out you need the RS-485 interfaces, you will just remove one SoftwareSerial interface and add the code to manage the transmit/receive direction control lines, but the polling code will stay the same.

Thank you! You've helped me a lot! :slight_smile:

I'm ordering them now. A small question regarding cables:

I need 2 twisted pairs - one cable from pair transmits, the other one – receives. And cables to connect grounds of all boards what makes three of them.

For RS-485, you need a twisted pair for communications, and a ground conductor (and it doesn't hurt to also have a shield that is connected at only one end (you don't want to introduce a ground loop, nor use the shield as a conductor.)

For straight serial data, you need three conductors: transmit, receive, and a common ground. As you propose, it doesn't hurt to use twisted pairs there: Tx/ground in one pair, and Rx/ground in the other. The grounds of the two pairs would be connected together to ground on each end. You shouldn't need an additional ground wire over and above the grounds in the twisted pairs - you could get away with Cat3 cable or regular telephone cable. However, if you use standard network cables (Cat5, Cat5e, Cat6, etc.) you will have four twisted pairs, and it doesn't hurt to use additional pairs as extra grounds.

In my system, I'm using Cat5 cables and RJ-45 connectors, and I'm even going so far as to power the remote nodes through the cables (my remote node power requirements are low, if you need a lot of power at the remote end then powering them through the cable is not a good idea.) The pinout I'm using is one pair for Rx/TX, one pair for a reset signal and ground, one pair for power ground, and another pair for power. So I end up with two wires for power, three for ground, and three signal lines.

The attached shows a highly condensed schematic of what I've done. It's divided into three sections:

  • the Yun Master which uses two Software Serial ports, each going to its own RJ-45 connector (not shown is the power supply where 9V VIN is brought in and converted to 5V for the Yun)
  • the Remote Slave which connects the RJ-45 to the hardware serial pins
  • a Programming Adapter for a remote slave which allows uploading sketches using an FTDI adapter cable. This is the only one that uses the DTR line to reset the remote slave while uploading from the IDE. This lets me program the unit as if I had plugged the FTDI cable directly into it, but it doesn't require me to open up the remote slave's case. This is, of course, completely optional if you have other means of loading code - I'm actually using an Arduino Pro Mini here that does not have a USB interface.

I'm not suggesting that you have to follow this exactly, I'm just giving you an example of a working setup. It's not applicable to all uses and environments, but it should work for your needs. I'm using RJ-45 connectors and Ethernet cables just because they are easy to work with, and relatively inexpensive. There's no reason you couldn't use other types of cables and hard-wire them. I used these breakout boards and connectors when breadboarding the system.

DuaneDegn:
@sonnyyu, where did you find that diagram?
...

http://www.bb-elec.com/Learning-Center/All-White-Papers/Serial/RS-485-Connections-FAQ.aspx

Last time I used RS-422/RS-485 extensively is about 30 years ago, Apple localtalk which allow me connects Macintosh SE and Apple Laserwriter.

ShapeShifter:
For RS-485, you need a twisted pair for communications, and a ground conductor (and it doesn't hurt to also have a shield that is connected at only one end (you don't want to introduce a ground loop, nor use the shield as a conductor.)

For straight serial data, you need three conductors: transmit, receive, and a common ground. As you propose, it doesn't hurt to use twisted pairs there: Tx/ground in one pair, and Rx/ground in the other. The grounds of the two pairs would be connected together to ground on each end. You shouldn't need an additional ground wire over and above the grounds in the twisted pairs - you could get away with Cat3 cable or regular telephone cable. However, if you use standard network cables (Cat5, Cat5e, Cat6, etc.) you will have four twisted pairs, and it doesn't hurt to use additional pairs as extra grounds.

In my system, I'm using Cat5 cables and RJ-45 connectors, and I'm even going so far as to power the remote nodes through the cables (my remote node power requirements are low, if you need a lot of power at the remote end then powering them through the cable is not a good idea.) The pinout I'm using is one pair for Rx/TX, one pair for a reset signal and ground, one pair for power ground, and another pair for power. So I end up with two wires for power, three for ground, and three signal lines.

The attached shows a highly condensed schematic of what I've done. It's divided into three sections:

  • the Yun Master which uses two Software Serial ports, each going to its own RJ-45 connector (not shown is the power supply where 9V VIN is brought in and converted to 5V for the Yun)
  • the Remote Slave which connects the RJ-45 to the hardware serial pins
  • a Programming Adapter for a remote slave which allows uploading sketches using an FTDI adapter cable. This is the only one that uses the DTR line to reset the remote slave while uploading from the IDE. This lets me program the unit as if I had plugged the FTDI cable directly into it, but it doesn't require me to open up the remote slave's case. This is, of course, completely optional if you have other means of loading code - I'm actually using an Arduino Pro Mini here that does not have a USB interface.

I'm not suggesting that you have to follow this exactly, I'm just giving you an example of a working setup. It's not applicable to all uses and environments, but it should work for your needs. I'm using RJ-45 connectors and Ethernet cables just because they are easy to work with, and relatively inexpensive. There's no reason you couldn't use other types of cables and hard-wire them. I used these breakout boards and connectors when breadboarding the system.

Thank you very much! You really helped me a lot! I will try it as soon as I get everything from Sparkfun. :slight_smile:

Just a fair warning, whatever communications method you use: RJ-45 connectors and Cat5 cables are cheap and easy. But make sure you don't get confused and cross-connect one of these RJ-45 connectors with an actual Ethernet network port - especially if you are sending power down the line. :o It's quite likely that neither side (the Yun software serial port, or the network adapter port) are going to enjoy the connection!

Hello! I have finally received the Arduinos and connected them.

Thank you a lot for your previous help.

I have a problem with two instances of SoftwareSerial.

When I declare both of them and set them to listen to the ports they don't work. But as soon as I remove one another one works. So both slaves send data and Master is able of receiving from both of them.

I attach code for Master Node and both of the slaves.

MasterNode.ino (1.19 KB)

SlaveNode1.ino (537 Bytes)

SlaveNode2.ino (495 Bytes)

mityakoval:
When I declare both of them and set them to listen to the ports they don't work.

Correct. The master code you have won't work. The current SoftwareSerial library is the NewSoftSerial library, which has some additional documentation here: NewSoftSerial

That page has a discussion about using two software serial ports, make sure you read it and understand it. For example, it clearly states this method won't work:

void loop()
{
  device1.listen();
  if (device1.available() > 0)
  {
    int c = device1.read();
    ...
  }
  device2.listen();
  if (device2.available() > 0)
  {
    int c = device2.read();
    ...
  }
}

That's pretty much what your code does.

It's important to understand that when you call .listen() on one of the software serial ports, it throws away any data and resets the software serial logic to start listening to data coming in on that port. The way you have the code, you are calling .listen() on one port, which resets things, and then immediately checking if there is data. That check will happen so quickly that there is absolutely no chance that any data could be received in that time. So you move on and do the same thing with the next serial port. You are spending all of your time resetting things and selecting ports, and never giving it a chance to receive anything.

You can't listen on two ports at the same time, you can only talk to one at a time. Once you call .listen() on one of the ports, you need to give it some time to actually receive some data. I described the way I did it earlier in this thread:

ShapeShifter:
There are some restrictions when using two SoftwareSerial ports - they cannot both listen at the same time. I came up with a simple polling protocol where the Yun is the master, and the slaves don't talk unless spoken to. The code sets one SoftwareSerial to listen, and sends a poll request. After getting a response or a timeout, it sets the other SoftwareSerial to listen, and sends a poll request to that unit. After a response or timeout, it's back to the first.

You have part of this scheme in your code: SlaveNode1 only talks after receiving a 'g' character. The MasterNode has some logic to send the poll character, but it doesn't wait for a response, it just goes immediately to the listen/check code that can't work.

What you need to do is before sending the poll character to a particular slave, you should first .listen() to that slave. Then you can send the poll character, and after that you should only be checking for data available from that slave that you last polled. Once you've received a complete message from that slave, or you timed out and waited long enough with no response, you can then .listen() to the other slave and send the poll request and wait for a response.

Basically, the sequence is listen to A, send a poll to A, and wait for a response from A. Then listen to B, send a poll to B, and wait for a response from B. Then go back to A.

The official TwoPortReceive Tutorial is seriously flawed. The general structure is very much like your code, but the only reason it might work at all is because there is a long message printed to the Serial port after the .listen() call and before the .available() call. Since the Serial port and both SoftwareSerial ports are running at the same 9600 speed, that Serial.println() call gives a delay of 20 character times where data can actually be received. So there is a chance it might actually receive something in that time period. In your code, there is nothing between the .listen() and .available() calls so you have no chance to receive anything. It's very unfortunate that the official example is so poorly designed and documented. It doesn't mention the simultaneous port limitations of the SoftwareSerial port, and it doesn't explain that there must be some time after the .listen() call to actually let some data come in. I think it's just sheer dumb luck that they happened to put the Serial.println() call after the .listen() call. Had they put the println() call before the .listen() (or not put it in at all) then it wouldn't work at all. Personally, I don't think sample code should be so fragile, and if it must be fragile like that, it should explain the consequences of doing something that seems so innocent as removing a println() call - it would be very easy to assume that such a call is merely for debugging, and is not the main key to getting it to work!

@ShapeShifter, Thank you! It helped a lot and I have set it up. Just in case somebody needs the code I attach it to the post

MasterNode.ino (1.67 KB)

SlaveNode1.ino (495 Bytes)

SlaveNode2.ino (495 Bytes)

Why use two ports when rs485 allows you to use just one?

mart256:
Why use two ports when rs485 allows you to use just one?

I'm not using rs-485. Instead I'm using two instances of SoftwareSerial.

@ShapeShifter, is there a way to poll for data from linux side? Say, I will remotely execute a cgi python script on Yun that will collect data from slaves and master and send it back to the remote server?