I'm currently using Modbus RTU over an RS-485 line to communicate between multiple devices in a network.
The problem with such a configuration is that the polling-based nature of Modbus RTU leads to noticeable delays in communication once the amount of devices in the network starts increasing. This led me to start thinking about replacing Modbus RTU with some event-driven protocol, but I don't want to lose the use of the RS-485 line due to its robustness in noisy environments.
Does anyone have any recommendations about some event-driven protocol for use over RS-485?
You may use the CAN bus protocol. It's rather complex but designed for supporting event-driven applications. The physical layer of CAN is open - so you could use your RS485 transceivers for implementing the CAN protocol. If your MCU does not natively support CAN you may use a companion chip which does the CAN protocol for you.
This could be a possible alternative. As someone who's only vaguely familiar with CAN, I think that I should start looking over at the CANOpen protocol with regards to a firmware implementation, right?
With regards to the lower layers a CAN controller such as the MCP2515 and a CAN transceiver should suffice.
In general you can (ab)use a normal RS485 transceiver as CAN transceiver, however this may be considered as a hack. Since CAN does not specify the actual physical implementation (in general, you could use a water pipe, if you get the mechanics working :-) ) there should be a wide variety of ready-made CAN transceivers, so you can pick the one which suits you best.
I'm not sure if CANOpen will be the best solution for you. It is my understanding that your application is not too complex, just a few nodes and a few messages. It might be beneficial to skip the CANOpen overhead in such a case. CAN protocol will do the collision detection for you and ensure that the messages are transferred properly, safely and in time. The lyout of the messages (i.e. the payload part of a CAN message) you can specify on your own.
If you are in control of the firmware at both ends, why not implement your own protocol?
Failing that, you could add "concentrator" devices which will poll a sub-set of the total number of devices, and then your master device only needs to poll the concentrators - this would keep the comms delays to a minimum.
Thanks for the response!
I'd rather not implement my own protocol and instead go for something more established.
The problem with such concentrator devices would be that they would require additional device design to take into consideration, and that's something I'd rather not do unless there's no other choice.
I agree that you want to keep using the RS485 bus for its strong noise immunity. I use a protocol I have defined and implemented myself, using the following principles.
> The RS485 bus can listen for collissions on the bus by not disabling the UART RX while transmitting. If you do not receive what you are transmitting, back off, there is an ongoing collission.
> Use a bus access method with strong collission avoidance. One of the following will do. In both cases each unit on the bus is assigned a unit number 1...n that defines how it accesses the bus. Unit number 1 is typically the bus master.
> Define bus access as a TDMA (Time Division, Multiple Access) mechanism. You define a frame with as many time slots as units on the bus. Unit number 1 always does a transmit in slot 1 do define frame start. Every other unit times its own slot with a time delay from slot 1. Bennefit of this mechanism is that all units have the same defined throughput rate. This is limited by the frame length and the slot time. More units on the bus = slower throughput. You only need the bus master in slot 1 to define frame start. All your packets must fit into the defined slot time. Remember to put some time padding in your slot access. I.e. you have 10 units on the bus, slot time is 10ms, meaning frame time is 100ms. When a unit uses its slot it starts transmitting 1ms into its slot and stop at 9ms into its slot. This avoids problems around clock drift between the different units.
> Option 2. For this you do not have to pre-assign node IDs to units connecting on the bus. Unit number 1 becomes a bus master that polls everybody else. Packets are defined by a maximum timeout between bytes of say 800us. Any transmitter must transmit the byte stream in a packet with a max timeout between bytes of max 800us. Put a minimum delay of 2ms between packets. You can use these timings to do packet assembly in your low level interrupt routine. Bus acces is defined in terms of timeout since the last byte of the last packet on the bus. The bus master (node 1) does a frame start packet. Then it stays silent for say 5 ms. Any slave unit on the bus that have not been assigned a node ID, uses random access on this slot right after the frame start packet to self announce to the bus master. The bus master them immediately in the next "slot" send it a node id assignment packet. After this random access "slot" for slave self announcement and slot assingnment, the master polls all of the slave devices that have been assinged a bus ID in sequence. Then it starts the next frame by sending the frame start packet again. Bennefit of this approack is that you can randomly connect new devices to a live bus, you get maximum throughput on the bus based on the number of active slave devices. If a slave does not respond to a poll for the third time, it gets de-ennumerated from the bus.
> In terms of packet definition. Have the following type of packet definition. <frame start><frame length><Source address><destination address><Packet type ID><random length packet data...><CRC><Frame end>
> If your processor supports 9bit mode on the UART, Use 9 bit mode for transmission of <frame start> <Frame End>, use 8 bit mode for all other packet data. Then you can build your interrupt setup to only interrupt on frame start and end on the slaves, unless the slave is addresses by the destination address in "frame start". In other words, the slaves wait in 9bit interrupt mode for a "frame start / destination address", if it is addressed it goes to 8bit interrupt mode and recevies the rest of the packet. If it is not addressed it stays in 9bit interrupt mode and does not generate any interrupts for the packet content. Having all frame starts and frame ends sent with 9bit interrupt mode helps you keep up with packet timeing. But your slaves do not generated data interrupts for the packet contents if it is not addressed.
> Benefit of option 2 is also that there is no constraint on packet length, you can have a mixture of very small and much longer packets with no problem.
> In your interrupt driven packet receive code. Use timeout mechanisms to implement recovery from incomplete packet reception. Use frame addressing 9bit mode and own address to switch to 8bit interrupt mode. Use packet length to know how many bytes make up a packet. Use CRC to check correct packet reception. This way the interrupt code can pass only complete packets up to the main code. Use a state machine to implement these mechanisms.
Hope this helps you with a general top level protocol design with some good design features.
Thanks for the highly detailed response!
I'll be sure to keep this in mind if I opt for my own protocol, although I do wish to look further into more bus access mechanisms.
Hmmm, I suspect a commercially available comm stack would have issues of cost and customization, that's if you find any. I also think any solution will be it's own network with your current devices attached outside them. Given that, you're already well into your own version.
I'm thinking a very terse protocol where all messages are as short as possible, minimizing traffic. Model it after Ethernet, such that a slave node requiring a transfer listens for an idle bus (active carrier across N bit times). On seeing idle, assert carrier and send message. All slaves listen for master messages.
This should work well for low latency until average traffic crosses some threshold. After that, delay to send will increase exponentially. If your traffic estimations are even close, it would be a bad choice. The time slot method described above is a much better fit for known max latency at the price of the equally known min.
Distributing the processing to minimize message length is valid in either case, so maybe start there. Submastering with routing is another way to manage traffic, either protocol is applicable in subnets.
This is a classic discussion of network design: theories behind Ethernet and Token-Ring protocols. I think Ethernet won because transmission speed outpaced the traffic congestion threshold. That, and the fixed slot method latency grows as the number of nodes increases.
Good Hunting, sounds like a fun project. <<<)))
Yeah, this did pass my mind although I'd rather check if some protocol is already in place which meets my requirements.
Thanks for the response!
Just pointing out MODBUS is transmission-agnostic. If you do full-duplex, you can broadcast from the master any updates on info.
You can also broadcast which slave you want to respond (poll), if you don't want to do the 9-bit addressing.
I suspect this problem has been solved many times. Google "modbus rtu over rs485" brings up a variety, including http://www.modbus.org/docs/Modbus_over_serial_line...
Let us know how it turns out1
I'm not sure I understand what you're proposing.
If you're going for 2 daisy chained networks for the master and slaves, you'll still need to implement some carrier sense since multiple masters (which will be slaves on the other network) can start transmitting at once.
Thanks for the response!
You changed the (implied) requirement from a single master + slaves to multiple masters.
I don't know if you read the document via the link. It lays out how to do MODBUS RTU over RS485. It is a polled system, which does not address your desire for an event driven system.
Your fundamental limitation is you need/want/must stick to RS485. This is, by nature, one master + slaves. Is this truly a requirement? The twisted pair I get - you are in a noisy environment. BUT - can you run multiple lines in a "star" pattern (one line per device to a common hub)? If so, you can do RS422. (I would do full-duplex - half-duplex is a short route to giggling in the corner.) Keep in mind you can use CAT5 to get to an area, then branch off from there, because you have multiple twisted pair in the same cable.
If you only want the slaves to send you something upon an event, and the master does not need to talk to the slaves, you can use a single twisted pair per slave. I would suggest the slave have a heartbeat (say every few minutes) so you know if the slave dies.
If you go this way, you will need a bunch of RS422 receivers at the hub. You can get multiple (8) port boards for pretty cheap. Stick them in a cheap tower PC or on a 19-inch rack. Your budget will tell you your options.
Plan for a 15-20% expansion of the number of slaves. Just because.
A google of "modbus rs485 multiple masters" and "modbus master to master communication" brings up a number of solutions.
And - the basic packet protocol of MODBUS is a good, simple one. Don't get hung up on the difference between *when/how* the packets are sent (the polling vs events) and *what* (the packet format) is sent. Do I care my letter/box/package is sent via US Mail or Fedex or UPS? No, other than the cost (for example) of a two-day delivery. The packets are the box. The transport mechanism doesn't care about the contents of the box/packet.
Hope this helps ... bandit
A possibility that I'll look into, although I'm not familiar at all with the protocol.
I am not by any stretch an expert, I have worked with HVAC controls that use the protocol so I have some application knowledge. There is an open source protocol stack available, with ports to several microcontrollers as well as Windows and Linux distros. It can be built with support for MS/TP (master-slave token passing) over RS485. From my limited experience and knowledge, works well with large networks and lots of devices.