RS485: 1 master, 4 slave

good day folks !

I’m working on an application, where I would have 1 master, asking each slave one after another, for a byte of information, over RS485, using some MAX485.

I have seen that a few libraries can be used: SimpleModbus, ModbusRTU, Library by Rob Tillaart, Nick Gammon, etc….

I’m confused….

As I said, master will ask each slave, a byte of data, let say every 250 mSec.

Which library/method would you recommend and why ?

TIA

Perhaps @robtillaart has information for you... (making a call with the "@" sign)

Are you sending a particular message that tells one slave to reply?

I have started to “play” around, writing my own code. it works, but has some glitch every once in a while.

that’s why I’m leaning toward an existing library, with solid error checking.

@robtillaart

Hi !

would your library be a good match for what I'm trying to do ?

Slaves need to have some sort of unique address so they can identify when they are being asked to reply. The address should be part of the message the master sends.

So you need to design your own ‘protocol’

For example

<1byte address of slave>, <1byte type of the question>, <1or 2 bytes ERC>

ERC= Optional Error detection codes, so you know that what has been received is legit.

the reply should be something similar.

As @Watcher pointed out you need to send a number of bytes (packet) including an addressing scheme, and probably a bit more.

The master is putting a packet on the RS485 lines and you want only one slave to react.

First thing the slave needs to do is to detect the start of a packet, so it know when to start to listen.

Second there should be a recipient address, so the slave knows the packet is addressed to him or not. If not that slave can start waiting for the start of packet again.
It is very well possible that one slave can react on multiple addresses, where each address has a different function. Also consider a broadcast address that addresses all slaves. This latter is typical used for commands like reset or shutDown etc

Third (optional) you can add a sender address which allows the slave to verify who send the message. Typical this is only used in a multi-master environment.

Fourth there should be a command byte, so the slave knows what he is expected to do. If a slave only has one action the command can be optional.

Fifth the command could have parameters. These are typical formatted as a length and followed by that number of bytes. This allows arbitrary length parameters to be send. If the command only has a fixed set of parameters, the length is optional as the slave knows e.g. this command is followed by N bytes.

Then as @Watcher pointed out a checksum to verify the integrity of the packet, detect errors can be added. This is optional but it prevents the slave doing the wrong thing, or the right action with the wrong parameters. Typical checksums are CRC, Adler, Fletcher or the simplest a sum (mod 255) of all bytes in the packet (except the checksum itself).

Finally, and optional one can add a end of packet byte


How to apply

The layout of a packet can be simple to complex.

If you have 4 slaves that only make e.g. and ADC measurement and send it back the protocol could look like

<START><ADDRESS SLAVE>

Not even a command needed as the slave can only do one thing. The answer of the slave could be something like

<START><ADDRESS MASTER><ADDRESS SLAVE><LENGTH><DATA>...<DATA><CRC><END>

The address of the master is mandatory (typical 0) as you do not want to have other slaves react on accidental byte patterns that look like a command. The slave address is optional, but it helps to ensure that the master knows which slave responded. The CRC is to check for errors.

If a slave can do many things like e.g. it has 6 ADC’s and 10 IO lines, EEPROM etc. You get a more complex packet

<START><ADDRESS SLAVE><ADDRESS MASTER><COMMAND><LENGTH><DATA>...<DATA><CRC><END>
(think store these X bytes in EEPROM at location Y)

Depending on the COMMAND the slave can react differently (or not at all) or asks for a resend of the command as the CRC failed.


Advice is to start simple 1 master 1 slave and if that works add more nodes to the system.

Looking at the ASCII table (google), it already includes several usable bytes for building a packet like STX, ETX, and more.


There are many ways to extend protocols to do very fancy things. Multiple commands in one packet, address multiple slaves with same command in one packet, broadcasting, multipacket answers, error correction strategies, time outs, time to live, timed commands, encryption and way more.

Some thoughts about protocol (small), see the file MESSAGES.MD in my RS485 repo.

(have to rework the layout as its crap)


started with the rework of the messages.md file (develop branch)

One error not mentioned is failure of a slave to reply. Your master will wait forever for a reply if a time-out is not programmed for.

The right solution depends on how robust this thing needs to be, and how much development time you’re willing to put into it, and your skill level. If it’s just a quick little thing that you don’t need to use for long, then you can go with a really minimal design that’ll be “good enough”.

For instance, you could have a protocol where everything travels over the network in the form of printable ASCII characters, and there’s no error checking . A packet from the master starts with a newline character, and contains 2 characters showing the address of a slave as a hex byte. If a slave recognizes its address, it responds with its own start-of-packet character, which is a ASCII space, and then 2 more characters representing the single byte of data that’s been requested. That’s all you need to do.

Of course with RS485, any unit that transmits has to control the line driver, very likely a MAX485 or a similar component. It has to enable the TX function, send what it needs to, and then wait until the final character finishes before disabling TX. You can easily do this with the Arduino serial protocol by sending everything, then executing a Serial.flush() command, then disabling TX. That’s assuming that you can afford to wait while the entire message is sent, so that’s another design issue–can you delay the processor? But most likely, if you’re just sending a single byte there isn’t much computing to be done.

The reason for using ASCII characters is that you can plug USB in to the master, run the Arduino monitor and see what the master is sending. If you also make the master send out everything that it receives when it’s not transmitting, your monitor could show on successive lines the address of each slave that gets called on, a space, and the returned data byte.

Good point about putting in a timeout to deal with an unresponsive node!