After
searching high and low for a decent, open RS485 protocol, I finally
gave up and wrote my own. Here are my goals:
Simple
addressing scheme for variables and nodes
All
data is broadcast: any node can listen to any data
Reasonable
data rate >= 38.4K baud
No
PC master required
Power
and RS485 data carried on simple 4 wire wiring: +12V, GND, D+, D-
Simple
termination scheme
I
wanted each sensor to be able to output data if it had it, and every
display to be able to collect that data and display it. In a 'normal'
RS485 network, there is a single PC whose job it is to poll each sensor
or actuator, and perform all data collection and control. I wanted no
PC to be required, with it's complexity and power use. To
coordinate the traffic on the bus, any one node can be designated the
master. All it needs to know is how many nodes are on the network, and
how often to poll the network. and starting at node 0, it asks: "Hey
node N, do you have any data?" If there is a node N, it replies with
its data. Then it goes on to the next node, until they're done. It
times out quickly if a node doesn't respond, so bus bandwidth isn't
wasted waiting. It's an easy job and any one of the nodes on the
network
can do it.
To easily support multiple displays, I eliminated the concept of a
single node doing all the data collection and dissemination. Using the
PC paradigm, each master would need to poll every slave it wants data
from. Then there is the issue from a node: well do you want my most
recent data or some timed sample? It is redndant and uses extra network
bandwidth. Instead, each
sensor simply outputs data if it has any, and each display can listen
to any sensors. If it is a weather display, it listens to weather
sensor
data. I use a simple data dictionary for this. Each variable in the
network is defined so every display understands what thedata type
means, and whetehr it needs it or not.
Each node has a node address. In addition, each data variable has an
identifier that is transmitted transmits along with it's data. A common
data dictionary is used to define what the variables are.
There
are three types of nodes: Master, Slave and Receiver and I/O. The
master simply polls each slave in sequence. Slaves simply output data
if they have it. Receivers look at the data and collect the data that
they want.
So the master needs only to know how many nodes are (or might be) on
the network. And how often to poll the network. Say there are 5 nodes
and it polls the network once per second. It starts with 0 and then
goes on to the next node. After it polls the fifth node, node 4, it
waits until the poll time is up and repeats the process. Forever.
Most nodes are slaves also. When the master polls them, they output
their data. That's it. The receivers always look at the network and
collect data if they need it.
So each slave must know which data they are to transmit. They maintain
a list. For example, weathernode outputs the wind speed, wind
direction, outdoor temperature, and barometric pressure. This is a
simple example where there is typically only one sensor for each type
of data on the network. In the case where there are multiples, each
generated by a different slave, the slave must include it's slave
address along with the data identifier. For example if there were
individual slaves in each room of a house and each could output room
temperature. So there would be multiple temperatures, each identified
by its room. Instead of having the code for each node generate a
random, unique identifier for its temperature, it would need to
assemble an identifier from it's node ID plus a variable identifier. I
haven't worked out all these details yet.
There are a few node configuration values that each node needs. They
currently live in mynode.h
#define
NODEADDR
2 /* My node address */ #define MASTERNODE
1 /* 1 if I'm the master, 0
for all slaves */ #define NUMSEND
3 /* Size
of send data struct */ #define NUMREC
8 /* Size of receive data
struct */
Ultimately there shold probably be a
way to specify a node's configuration at runtime. This would require
some simple user interface, and storing the values in EEPROM. For now I
just recompile the code with these values set for that specific node.
It takes about the same time as it would to run some configuration
program, and this doesn't require writing the program.
Here is a diagram of the communication
responsibilities of each type of node.
If you are interested in the code for
this project, please contact me.