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?