Master/slaves network protocol

I have a "smart device" SD that is the master on a RS485 master/slaves half-duplex network. The user interact with a "dumb device" DD (slave) and he should have the illusion to interact directly with the SD.

All the relevant (for the user) info (status and settings) about the SD must be spread among the DDs, through a suitable protocol on the RS485 network. Some variables are read-only: they changes autonomously over time and can't be changed by the user (for example, a temperature). Other variables are read-write and can be changed only by the user (they don't change autonomously).

One simple strategy is to send all the current status and settings to all the slaves every 1 second. If the data to be spread are big, the number of slaves is high and most of the data changes slowly (as it happens in my application), a lot of network bandwith will be wasted to send always the same data. I could alleviate this problem by sending data through a broadcast message on the network, but I don't like it. The master should be sure if a slave is present and has well received the status, such that it could generate an alarm if a slave is failed and can't communicate on the network. So the master must poll each slave and waits for an answer from it (this can't be done with broadcast messages).

Another strategy is to send by difference: only if one piece of info (a variable, a byte or a group of variables) changes, the master sends all the data to each slave. The problem with this technique is the amount of memory needed in the master (it could be a small 8-bit microcontroller with modest size of RAM). It should allocate a data buffer for *each* slave with the last values sent to it over the network. Every 1 second, a function compare the actual values against the last sent values for each slave and send new values if they differ. If the data is 100 bytes and slaves are 10, the master needs 1KB of RAM only for that. This strategy could be changed to decrease the network bandwith needed to refresh the new status. If only one variable is changed, only that (or some other related variables) can be sent over the network.

Another strategy is similar to the previous, but saves a lot of memory: the master set only a flag that triggers a status refresh to all the slaves. The network protocol task routine checks for this flag and if it is set, sends current values to all the slaves. The problem with this strategy is in the "core" code that manages the status variables. Every time in the code a variable is written in the RAM, a comparison with the old value must be made and, if there's a difference, the refresh flag must be set. I could try to change the "core" code in order to manage the refresh flag for the network, but I don't like it for several reasons. The "core" code is already written and tested. In the future, I'm sure I'll forget to correctly manage the refresh flag. The "core" code would be strongly coupled with other completely different modules (network protocol). The "core" code would be more dirty with network refresh flag management: every time I have to set a variable

status.temperature = sensor_read_temperature();

I need to make a comparison with the old value:

new_temperature = sensor_read_temperature(); if (new_temperature != status.temperature) { status.temperature = new_temperature; network.refresh_flag = 1; }

One possibility to alleviate those problems is to create an intermediate module that manages the status. This module provides getter and setter functions.

status_temperature_set(sensor_read_temperature());

void status_temperature_set(int new_temperature) { if (status.temperature != new_temperature) { status.temperature = new_temperature; network.refresh_flag = 1; } }

Even this strategy has some inefficiencies. The module should manage the status that is relevant for the slaves (and for the protocol). The "core" code should call status module setters for some variables and should use normal assignment for other variables (that aren't related to network protocol). In this case too, the "core" code is coupled with another, completely logically different, module.

Do you have other better strategies to propose?

Reply to
pozz
Loading thread data ...

There are plenty of strategies but which will be most suitable for you rather depends on the end use of your system. Is this a commercial product or just something you are playing with?

There are things you could do to help yourself, without busting your available memory or comms bandwidth budget, but end use of the information is something I would want to know before I suggest anything as there may be Safety Integrity Implications that you have not yet stated anything about. To make assumptions otherwise would be wrong.

--
******************************************************************** 
Paul E. Bennett IEng MIET..... 
 Click to see the full signature
Reply to
Paul E Bennett

In any half duplex network, the relative throughput at higher speeds drops quite rapidly due to latencies at both, including software delays as well as transceivers turn around times. So even if you can run RS-485 at 115k2 to 1000 m or Profibus-DP at 12 Mbit/s for 100 m, the actual throughput might not be what you expected.

Using long message frames and avoiding too much pol/ack sequences will help.

So you must poll each DD to check if it has something to send.

If the same data needs to be sent to all slaves, broadcast would be the natural solution. Also sending a few small different values to all slaves could be done with a broadcast message, just locate the value for a specific slave at a predefined location in the frame.

The broadcast frame should also contain a common revision number.

Since you are going to poll the slaves anyway for input data, include the most recent successfully received broadcast frame revision number in the poll response, thus the master will know if there are old data in some slaves and repeat the broadcast. This should quite quickly remove any transient errors and all slaves will return the most recent broadcast frame revision number and there should not be a need to repeat the periodic updates, until some data on the master side has changed and a new revision number assigned.

Of course, if the slave has some real data to send, the poll response should contain the broadcast frame revision number as well as the data to be sent to the master, thus minimizing the unproductive message exchanges. Such practices have been used at least since the HDLC days.

Reply to
upsidedown

You're reinventing MODBUS RTU. It kinda sucks. You can make it work if you have a low enough number of "registers" on a small enough set of "nodes". You trade for latency and the only noise management strategy is retransmission of requests by the master node.

--
Les Cargill
Reply to
Les Cargill

I'm just playing with this gadget at the moment, but I hope to sell some piece. Anyway I try to use "professional" methods even in projects I develop during spare time for hobby.

It's not a critical application (such as aerospace, avionics, medical or safety). This is for sure.

Reply to
pozzugno

This is an interesting comment. I tend to use lower bitrate, in the range 9600-57600bps, even if the distance is small (maximum 100 meters).

I agree with you about the delay that is introduced by software, mainly the delay for the slave to answer to the master (1ms delay corresponds to about 4 bytes at 38400bps), but the transceivers turn around time is very small at those speeds and can be safely ignored.

Yes, it is what I'm doing.

I don't think there's a great difference between (M=Master, S=Slave):

M: Hey all, this is message number 13 and my current state is this M: Hey Slave 1, nothing to say? S1: Last frame received from you is 13 and nothing to say. M: Hey Slave 2, nothing to say? S2: Last frame received from you is 12(!!!?) and nothing to say

and

M: Hey Slave 1, this is my current state. Nothing to say? S1: Ok, nothing to say M: Hey Salve 2, this is my current state. Nothing to say? S2: Ok, the user wants to switch off garden lamp ...

Indeed my protocol (at the link level) is inspired to HDLC. The master manages a session for each slave and, for each session, there are two numbers: the sequence number of last frame send and the sequence number of last frame received. This is a good approach to identify failed slaves and failed transmissions to avoid retransmissions with side effetcs.

But this is at the link level. I was discussing about the protol at the application level on top of link level.

Reply to
pozzugno

Il 30/11/2014 19:14, Les Cargill ha scritto: > [...]

I know the MODBUS RTU, but I don't know how it is the answer to my question.

Should the Master (implementing Modbus protocol) sends all the registers values every 1 second, even if they don't change, or should it send only values that change? What is the approach in Modbus network?

Reply to
pozzugno

It's an attempt to name a very similar protocol which might trigger some strategies to cope amongst the participants.

I think the comparison to RTU it does help. You're bandwidth constrained and will have to trade latency for bandwidth.

I am very sure that this varies. I can't give you "should"; I don't have enough information. But there's usually no reason to send information you don't have to over a bandwidth constrained network. Usually. The ugly part of MODBUS RTU is having to poll everything for state changes.

Since you're half duplex, I doubt you can have asynchronous events fired from edge nodes. You'd have to poll for them.

--
Les Cargill
Reply to
Les Cargill

OK.

Does a slave node need information generated by another slave in order to operate sensibly? This could complicate matters slightly. However, there are schemes and I have seen others mention RTU's which is where this need seemd like it could find a solution.

You should probably form a definite pattern for sending and receiving data that includes the slave node addresses. Whether such addresses are provided as hard-wired switches or are part of a discovery scheme is something you may need to think about. In the end, all your slaves will need a unique node address. There are schemes like CEC (part of the HDMI specification and used for consumer device control). Some standards exist like ModBus, IEC60870, DNP3 and IEC61850. The HDMI CEC bit is in .

You should probably keep all communicable data in specific memory blocks to aid easy transfer (one for TX and one for RX). Keep the size of these blocks small and include some form of communications heartbeat function within the protocol you select (this should be regular enough and distinct enough to know the link status in both directions).

The master station should always be the commanding node and slaves should obey. You can include acknowledgements so that the master knows that the commands are received and acted upon. Regular status enquiries could collect the receivable data in response or just a status byte that states the slave is healthy and there is data to transfer (something you will have to decide)

Keep the protocol you select as simple as will suit your needs as possible.

--
******************************************************************** 
Paul E. Bennett IEng MIET..... 
 Click to see the full signature
Reply to
Paul E Bennett

Il 01/12/2014 13:56, Paul E Bennett ha scritto: >

No, it's not important.

Of course, I already developed a discovery mechanism that is based on a unique 32-bit serial number hard-wired in each slave. During discovery phase, the master assign a 8-bit addres to each slave. This 8-bit address is used during normal communications.

The link level of the protocol is inspired to HDLC. Now I have to develop the application-level protocol.

Everything you have written is already implemented in the link-layer of the protocol.

Reply to
pozzugno

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.