Hi all, I was having a discussion with JackRipper over on Timescapes regarding a unified protocol and bus specification for interconnected, independent and interdependent devices for motion control (Separate from modbus and other fieldbus implementations). It turns out we were both working on the same problem, and both were working with other hardware developers to that end.
We agreed that we should probably unify our efforts for maximum effect, so to that end, I'd like to start gathering requirements for such a specification. We won't get anywhere until we lay out a hard set of requirements which define what we're trying to achieve.
To be effectively and truly compatible, specification should define the following things at a minimum:
- The physical transport layer technology (e.g. RS-232, RS-485, ethernet, SPI, i2c, etc.)
- The characteristics of the physical transport layer (capacitance, power requirements, full or half-duplex, topology, bus length and cabling)
- The relationship and protocol between two types of devices: master and node (masters control nodes, and may include user interfaces, nodes always require a master to perform an activity)
- Protocol should include at a minimum:
- Speed of data transmission over bus
- Protocol data structures: headers, packet format, checksum, etc.
- Minimum required commands for any device (e.g. version, identifier, etc.)
Here are some of my requirements, based on the needs of hardware and devices which we are currently building:
- Support for variable number of devices up to 32
- Ability to vary number of devices on bus without changing bus parameters or configuration
- Support for a bus length of 30m with 32 devices
- 5V bus voltage
- Binary protocol specification***
- Single master, many nodes
- We have no particular requirement for multi-master setups
- Support for parallel buses controlled by a single master (i.e. bus + star topologies combined)
- An address space capable of uniquely identifying > 256 devices across all connected buses
- Independent time-synchronizing mechanisms between nodes without input from master
- Ability to operate nodes without master present on bus (i.e. the specification should only specify that the master configures the nodes, it should not require the master to be present or active after nodes have been configured. It's better to be neutral to this point, but it will be a non-starter for us if the master is required to always be present on the bus by the spec.)
- Ability to transport a minimum of 12V additional power, at a maximum of 1A using the same cabling as bus communication
- Broadcast traffic -must- be supported
*** : The reason for this is quite simple: we are dealing, in many cases, with memory and cpu-limited devices. While "textual commands" are easy to type into a serial terminal, they are extremely limiting for highly complex devices operating on limited platforms. Additionally, converting large numeric values into their ascii equivalents greatly increases the data transmitted, reducing the speed of transmission on most buses. Take, for example, the nanoMoCo firmware will have almost 100, or more, commands it can accept, some of which take five or more long integers as arguments. The use of string literals here will explode the use of memory or flash and slow down data processing incredibly. Additionally, on a bus topology EVERY device has to process every command coming down the line to verify if it is destined for it or not, so the data processed by one device will limit performance of all others if not smartly designed.
Now, it's not really a secret that we already have an early implementation of such a protocol and a specification, including working code and electronic characteristics defined. I do believe, that in lack of any further input regarding requirements, it is based on both industry standards (RS-485 transport) and best practices for software development. We do, in fact, already have hardware in production that will soon be in customers hands using this. When we began on this process, no one else was discussing doing this, so we had to come up with what met our requirements and what would be attractive to other hardware developers. That being said, I am in favor of a community-developed specification, but we need to make sure we go about it in a similar process to other industry specifications where the people with skin in the game (manufacturers, developers, and users) get a chance for meaningful input and discussion. Should that require small changes to the future of our products to meet it, then we will cross that bridge when we get to it.
That being said, here are the core details of the existing MoCoBus specification we've been developing @ DP:
- Transport layer is RS-485, half-duplex
- RS-485 voltage at 5V
- All devices must have fail-safe resistor network to eliminate need for termination
- Resistor spec:
- A->GND 100K
- B->5V 100K
- A->B 100 ohm
- Transmission speed is 57,600 bps
- Cabling is Cat6 standard RJ-45
- Cabling carry:
- RS-485 A
- RS-485 B
- GND
- 12V
- 12V
- Common A
- Common B
- Common C
- All data packets are binary, big-endian format
- Packets begin with a non-repeatable start sequence of bytes, followed by an address, and then a payload data length
- Addresses are 16bits
- Masters are un-addressed (they do not receive commands, only responses)
- Address 0 is reserved for response to masters, address 1 reserved for broadcast traffic, and all remaining may be used for nodes
- Payloads that transmit multiple data values which can result in a sequence of five null bytes in a row followed by a single byte of 0xFF MUST use a byte separator between these values where 1 < v < 255
- See http://openmoco.org/docs/OMLibraries/class_o_m_mo_co_bus.html for more info on the existing implementation
- Inter-node timing synchronization is accomplished using "Common C" bus line
- Common A and Common B are open for specified use by individual nodes, and all nodes must pass these signals through un-altered in a bus
- Low-power devices may tap off the 12V of the bus, as long as the total bus power draw does not exceed 1A
Your feedback and input is greatly appreciated!
!c

I agree that we need some
I agree that we need some sort of "bus" for advanced motion control. This bus should not only support motor control, but also advanced camera c0ntrol (via embedded Linux boards) and studio control. The studio capabilities could control blinds, studio strobes, growth lights etc.
The original OpenMoco time lapse engine supports up to 4 motors, but it was too limited for advanced motor control where several motors are running continuously. A bus opens up the possibilities for advanced motion control with a large number (more than 4) motors that can all move at the same time.
I have been testing the nanoMoco board and the corresponding MocoBus and I am extremely happy with it. The RS-485 bus works perfectly and is very easy to connect to USB via a RS-485 to USB connection cable. I am not in favor of an I2C connection as a transport layer. It is possible to convert I2C to USB, but that needs more hardware than a RS-485 to USB connection. I worked a lot with I2C communication between several Arduino's but I believe RS-485 gives a more stable, easier to implement layer. I2C cabling is more difficult although you could overcome this partly by using an I2C buffer chip. I believe that I2C is meant to connect sensors, and not so much as a communication layer between micro controllers.
The current nanoMoco board and firmware is quite far in its development phase. The small 1.5" x 1.5" board holds everything you need to implement a complex multi motor setup. I hope to show my dolly with integrated pan/tilt head based on the nanoMoco hardware ASAP.
So far, there have been no issues with the MocoBus and the nanoMoco board that shows the need for another hardware/software approach.
One thing I'd like to add in
One thing I'd like to add in there is a minimum response time from nodes to masters, to prevent bus lock-up. That is to say, consider the following situation:
A master is polling > 10 devices, one of the devices takes 5 seconds to respond - the master is held in a timing wait for 5 seconds during this period, and is unable to poll other devices.
The current implementation works around this by timing out (literally, less than 100mS for response or you're considered in a failed state), but this means that the node may push data back onto the bus at some point in the future, prospectively interrupting an ongoing communication. By establishing a maximum response time, we get around some of the ModBus issues (where it is common for devices to spend a minute or more in formulating a response) by simply throttling any device that doesn't respond.
We could still have the "bad data on the bus" issue, but with clear guidelines on timing, we could minimize this and encourage compliance for bad actors on the bus.
I think it's great that you bring up the different kinds of devices which could be on the bus - this is why I really want to stop short of specifying anything that's below the protocol header in the datagram, aside from a few key commands which would be necessary to identify devices on the bus (device identifier and device version). It is important that the spec does strongly indicate these command so that any master or software designer is able to effectively determine if the device he is speaking with speaks a language he understands.
One of the areas I'm still wondering about is broadcast traffic:
!c
I would think of a family of
I would think of a family of devices. Relay boards that control blinds or lights definitely have other parameters than boards that control motors or camera's. Maybe we can add a group number to the address of the board? That way we can have more fine grained control over broadcasts?
With regards to broadcast responses or responses from devices in general. This sounds like we need a more complex serial protocol with a header that holds more information? That way we can implement the correlation of a response to the request. I do agree with your comments that his makes the protocol more complex, but maybe there is just no other way? This leads to a major concern that I am beginning to have though; and I know you will not agree :-). Will the 328 chip be big enough in the future when more functionality is added to the firmware? The current firmware is over 15k already. I would love, for example, to add my ramping stuff to it. But then we are really pushing the limits of the 32k.
Creating families of devices
Creating families of devices should be no big deal, the harder part is making a registry of them and keeping it up to date =)
If we look at the current packet format (very much simplified here):
break header | target address | code | dlenWe can augment it as follows for command packets:
break header | pkt type | target address | target family | code | dlenand, for response packets:
break header | pkt type | target address | src address | code | dlenWith pkt type, we don't need a lot of values, so we could use the first 4 bits for packet type, and the last four for flags, should they be needed (like 'do not respond' =) -- we don't need a source address on command packets unless we loosen up to allow more than one master on the bus (but it's really no big deal for masters to discard responses to commands they didn't initiate - this is basic programming activity, and the model libraries would take care of this already).
The resolving of order of response is trickier, but if we had some ARP ability, the master could indicate in the target address field (since the pkt code would already indicate 'broadcast') which device address is the highest it is speaking to... Then, the remainder of devices could use a timeout queue - if you see a higher address than you respond in 1mS, wait 500uS, otherwise go ahead and respond. This still gets tricky and still requires some ARP-like ability. I almost hesitate to say there shouldn't be a broadcast response, but that makes life a lot more difficult. I'm not sure this is a problem we have today, but it would make network discovery in the client I'm working on a LOT easier. (Vs. polling and timing out ~65k addresses, which takes about 650 seconds if we allow a 10mS timeout waiting for responses, or 65 seconds with a 1ms timeout.)
Life would be great if we pulled address space back to 8-bits. That means complete network polling could be done in 1/4 of a second per link in the star. We'd likely have network address crossover, which isn't as big of a deal as it sounds in star topologies. (The current client libraries I've written identify devices by their network port AND their address.) Cutting it back to 8-bits would also mean that the new response format would only add one byte to the existing packet length vs. three.
Now, as for capabilities of the atmeg328p - it all depends on what one is doing, and how one is doing it. =) There's a heck of a lot going on in that 15k (and only 500 bytes of pre-allocated memory!), it could've been done using all of the 32k, but with prudence and optimization, we can always do more than we imagined. Of course, some devices will obviously require more oomph, but I think a single camera/motor axis is well-served with a 328p, until one wants to go really high speed and needs more CPU time to exceed the steps-per-second bottleneck. (Assuming one wants to run high voltage, high current =) As they say, "if we put more space, people will just use it." *grin*
In the near horizon, there're 16- and 32-bit processors worth considering, which each provide more memory and more cpu time (in addition to faster arithmetic). But, I don't think it's a today problem =)
!c
I am going to self moderate
I am going to self moderate this comment, after reflection there was some poor wording chosen and could easily have been taken out of context, I accept that there is some fault on my side with this, and will re-try this.
1) Exactly who are you planning to cater to with the standard you are developing? Im a big DIY'er, when i was first looking at a standard i was looking for something that would simply allow people to synch up for SMS shooting. Will this remain something the DIY crowd can sink thier teeth into? For me that is sort of a big one.
2) What level of networking knowledge will somebody have to have in order to implement this?
3) what hardware requirements will there be?
4) How compatible would we expect this to be with existing systems? will it require large code overhauls and retrofits? Or just a new jack and a software package running in the background?
Dont get me wrong i think what you guys are doing here is incredible, and i dont want to take anything away from that, im just concerned the adoption of such a standard will set it outside the level of DIY'ers, which was my main intended target.
- Also Chris.
Chris, 1) My goal is to
Chris,
1) My goal is to target a standard which hardware developers will be happy to include in their products such that DIY users can then have a consistent interface with which to interact with these products when creating their own systems.
2) Hopefully very little via the abstraction layer
3) An RS-485 bus and something that can read data off of it
4) Backwards-compatibility is desired, but if the device lacked some hardware to speak to other devices in a multi-node bus, then it would be very difficult to support it in the same standard.
I don't think most users would think anything more of the standard than the standard they use to communicate between an arduino and a PC for example. One really doesn't consider what it takes to send a proper signal down to the USB port, and then how to properly time the signals between sending and receiving to transmit the right data in the right way, most of the time.
!c
@Jack: I don't see why you
@Jack:
I don't see why you suddenly need a lot of equipment when you are discussing a motion control device network standard. The standard is meant to control a network of loosely coupled devices with different functions. That doesn't mean additional hardware, just a good thought about what you send over the wire and when.
Compatibility with existing systems should not block the development of new ideas. Sure it's great when existing stuff can integrate with this unified standard and why can't this be realized in the future. Have a look at the fantastic stuff that Shutterdrone wrote for the nanoMoco board. Check out the libraries as see for yourself that the abstraction layer is already in the making. I have tested the new firmware and nanoMoco board a lot and I can say that for me that is the way to go. I hope to connect three boards together after Chrismas so that I can hopefully contribute myself.
The standard should be extensible; that is very important. We not only need MoCo stuff that controls motors, but we also need stuff for studio's. I have started to work on a big project that will all be done indoors. A simple solution based on triggers won't do it in that case.
@Shutterdrone:
About the ARP ability. Why don't we send an unique identifier with each request? Clients could put that on a stack and check if a result was given by other clients? That way you can implement some sort of functionality that checks the order or replies? Or is this oversimplified? Sure a stack costs memory and would only work with a limited number of commands within a time frame.
Addressing a couple of points
Addressing a couple of points brought up:
--- Why the need for replies?
Replies serve several functions, the first is an assurance of receipt. In the most simple of systems, one can operate generally by "sending and forgetting," and certainly for some devices the users' end result may be met even if a device loses one or two commands, but a failure to receive a move command on an axis that is expected to position the camera in relation to another axis can result in destruction of property - if the user expected the camera to be clear of an obstacle. A failure to receive a change of direction, or a stop command can result in damage as well. A well-designed system would have a feature to put the entire setup into a safe mode should a critical action not be taken.
A second key function is to query devices about information which they may best be aware of. Take, for example, I ask something to move 5,000 steps - as a remote observer, I can call up the other and ask "have you taken all of those steps yet? no? I'll come back later." without this ability, I can only presume that my instructions were dutifully followed. One presumes that everything is working fine, until it's evident that it isn't. Over time, the amount of data that must remain in one device's "head" to recall what the possible state is of a network performing a complex activity will quickly saturate its capacity unless it has quite a bit of memory. By spreading that memory through the network, rather than centralizing it we could effectively use less-expensive devices. Additionally, there are many use-cases for software to poll a series of devices and inquire about their current state for display to the user.
Having support for this feature will allow us to enable people to build well-designed systems for a wide variety of use-cases, and this is why I suggest it be part of this standard.
--- Why the complicated packet structure?
It's not a question of "if," but "when" a byte is read out of sequence. A device starts running while another device is receiving a command. One of the arguments to the other device's command has the same value as a command for this device. The newly-started device has no way of determining whether or not that really is a command intended for it.
Consider also, that a multi-byte command is sent, and the command value byte is lost in transmission - the argument now becomes the command.
The proposed break header seeks to resolve this by indicating a sequence of bytes, which shall be defined as illegal in any other use of this protocol*. In such a manner, any device waiting a command may know within 5 bytes of data, at a maximum whether or not they are at the start, or in the middle of a command and this ambiguity is cleared.
Having cleared this ambiguity, we can move on to another aspect of this packet structure: addressing. Once we know that a device address is at a specific location in the packet, and we know for sure that we're at this location, we can now disambiguate the target of a command reliably, and easily ignore things that aren't meant for us - even if we don't know the language that is being spoken to the other device.
The data length is important, as data can be missed from the middle or end of the chain of bytes as well. You'll find a data length of some sort in pretty much every algorithm ever written to take data from one source to the next. (Even if hidden from you in higher-level languages.) Without knowing the expected length of a record of data, we have no way of knowing when to stop - except to get a flow sequence that would inform us. But, such flow sequences do not tell us whether we missed data we should have been expecting. In this manner, any device may know for certain whether or not all expected bytes were received.
Of course, we can't know for sure that we received each byte as it was expected to be received, but we at least know whether or not data was left on the floor.
* - that's why the whole thing about breaking up 4byte values with a break character, to ensure that 0|0|0|0|0|255 is not a valid sequence otherwise.
--- How can this be made easy enough to use?
In general, this is easily abstracted from any consumer. A simple object-oriented interface can be provided to do things as simply as asking simple questions "send a command," "did I receive a command recently?"
If you'd like to talk about interaction models, I'd love to.
!c
Ok, i see your point. thank
Ok, i see your point. thank you for the well thought out reply.
One thing I'd like to cover
One thing I'd like to cover as well, is about the reference implementation (i.e. the libraries), and how they can encourage vendors to produce devices which any DIY person or hacker can ensure that they know how to speak to, while still having the ability to add mocobus control to an existing proprietary application without fear of having to share code for an existing commercial application that is not open-source. I.e., encouraging adoption of the mocobus standard to software developers that currently sell proprietary products.
We can, through a simple licensing scheme, enforce openness for devices on the bus, while allowing proprietary control interfaces running on a PC, etc. Here's my thought on it:
- Device-level libraries released under GPLv3 terms
- Client-level libraries released under LGPLv3 terms, with shared library targets
This would mean that anyone who embeds the device-level C++ libraries, or any derivative of them, into a device must share the code for their device, if the device uses a single memory space for its code. If it supports the concept of multiple distinct memory spaces for running programs (such as an embedded linux device), the vendor only must share the part which embeds the device-level libraries, such as the bus communication elements. This ensures that anyone receiving such a device may know the protocol it speaks.
The client-level libraries being LGPL, however, would mean the only thing that has to be shared is any change to the client libraries, allowing existing software vendors to quickly add support for mocobus devices without fear of having to open-source their entire application.
My take on it is that without some license-level enforcement on the device end, if the mocobus were to become popular, we would see a plethora of devices which are completely closed being sold to live on these buses, which completely eliminates the value of this standard for the DIY/hacker crowd. However, any requirement to fully open-source a client application when you use the client libraries would mean most software vendors would not add support via the client libraries - and since rolling one's own re-implementation of these libraries would be cumbersome, it would reduce adoption amongst software vendors, thereby reducing the number of devices developed.
Thoughts?
!c