This document is part of the MakerBus project.

MakerBus Specifications

Table of Contents:

1.0 Introduction

MakerBus is an inexpensive interprocessor communication bus that uses UART's running at .5MHz running on top of the ISO-11898 electrical standard. While MakerBus was initially designed for robot applications, it has many uses outside of robotics. With MakerBus, it is possible to have multiple coordinated sensors, actuators, computation nodes to solve complex real-time applications.

{Need picture here.}

2.0 Electrical Specification

The minimal electrical requirement for MakerBus module is .5MHz slope controlled ISO-11898. ISO-11809 can be implemented using 3 wires.

The preferred MakerBus electrical cable is a 10 wire ribbon cable where the additional wires are used to supply power and ground

2.1 Minimal Electrical Specification

The absolute minimum electrical requirement for a MakerBus node to implement is ISO-11898. ISO-11898 was primarily designed to provide a very reliable communication layer for the automotive industry. In the automotive industry, the CAN bus protocol is quite prevalent and it exclusively uses ISO-11898. Indeed, the ISO-11898 transceivers are usually marketed as "CAN Transceivers".

ISO-11898 requires 3-wires:

The CANH and CANL wires form a differential pair that can be used to reliably send a 1 or a 0. A differential pair has higher noise immunity than a single wire. The ISO-11898 also requires a common ground wire.

While ISO-11898 can be used to communicate at speeds up to 1MHz, the generated square waves produce a fair amount of radiated electromagnetic interference (EMI.) Alternatively, ISO-11898 can be run at slower speeds in a mode called slope control that results in trapazoidal waves which radiate much less EMI. Most automotive applications run at a slope controlled speed of either .25MHz or .5MHz. MakerBus runs at .5Mhz with in slope control mode. When running at .5Mhz, the bus can be up to 100 meters long.

Both ends of the bus must have a 120 Ohm resister attached across the CANH and CANL wires to eliminate signal reflections.

ISO-11898 provides a half duplex bus. With a half duplex bus whatever is transmitted on the bus is received by all nodes on the bus. This includes the node that is doing the transmitting.

In addition, ISO-11898 allows more than one node to transmit at the same time. The table below shows the behavior:

Transmits All
Receive
Node 1 Node 2 Node 3 ... Node N
1 1 1 ... 1 1
0 x x ... x 0
x 0 x ... x 0
x x 0 ... x 0
...
x x x ... 0 0
A 1 is received only if all bus nodes are transmitting a 1. If any node transmits a 0, all nodes receive a 0.

In short summary, the minimum MakerBus requirement is ISO-11898 running at .5MHz in slope controlled mode. Both ends of the bus must be terminated with a 120 Ohm resistor.

2.2 Full MakerBus Electrical Specification

The full MakerBus has 10 wires organized as three pair groupings:

CANH/CANL are the differential communication pair required by ISO-11898. LPWR/LGND are a logic power and ground pair that is used to provide electrical power for MakerBus Nodes. MPWR/MGND is an electrically isolated power bus that is primarily used to power small motors and servos. The LPWR, LGND, MPWR, and MGND wires have two wires to double current capacity.

The most common MakerBus connector is a polarized shrouded 2 by 5 male pin header with a pin pitch of 2.54mm (i.e. .1 inch). This connector is compatible with a female ribbon cable insulation displacement connector (IDC.) This connector was selected because it is inexpensive, readily available from multiple vendors, and easy to attach to 10 conductor 1.27mm (.05 inch pitch) ribbon cable. The ribbon cable is also relatively inexpensive and is available from multiple vendors.

Since there are other systems that use the 2 by 5 polarized shrouded header (e.g. .NET gadgeteer), the MakerBus connectors should be blue. This is a feeble attempt to discourage people from plugging incompatible buses together.

The connector is connected as follows:

Name Pin Pin Name Notes
LPWR1 1 2 LPWR2 LPWR1/LPWR2 electrically connected
LGND1 3 4 LGND2 LGND1/LGND2 electrically connected
CANH 5 6 CANL
MGND1 7 8 MGND2 MGND1/MGND2 electrically connected
MPWR1 9 10 MPWR2 MPWR1/MPWR2 electrically connected
By assigning 2 ribbon cable conductors to each of LPWR, LGND, MPWR, and MGND, the allowable current is doubled.

All MakerBus modules are required to accept up to 30V on either LPWR and/or MPWR. 30V was selected to be compatible with 24V battery systems. A fully charged 24V gel battery can sometimes get to a voltage as high 28V.

If the female IDC connector is accidentally attached to the cable with the pins reversed, a MakerBus module that is plugged into the reversed connector will get its logic power from MPWR and MGND. Since both power buses are specified to take up to 30V, the MakerBus module will not suffer any electrical damage. In this situatation, the CANH/CANL pairs will also be reversed which will preclude successful operation. Again, no electrical damage will occur.

3.0 Protocol Specification

The protocol specification is broken into 3 basic levels:

Basic Protocol
The basic protocol is used to select a module, send information to the module, and receive information back from the module.
Discovery Protocol
The discovery protocol identifies each module that is electrically connected to the bus and assigns each module a unique 8-bit module address.
Common Shared Commands
The common shared commands are commands that are implemented across all modules that can be used to query the hardware and firmware versions associated with a module. In addition, firmware can be replaced over the bus using the common shared commands.
Each of these levels is described in the sections that follow below.

3.1 Basic Protocol

The MakerBus protocol uses UART's that are configured transmit frames in 9N1 mode. 9N1 mode frame consists of 1 start bit (a 0), 9 data bits, followed by 1 stop bit (a 1). There is no parity bit. The 9th bit is used to distinguish between an address byte and a data byte. When the 9th bit is a 1, the byte is an address byte and when it is a 0, it is a data byte.

9N1 mode is used because many embedded microcontrollers implement a mode provide a little extra hardware support for the 9N1 mode. In general, the microcontroller can be configured to ignore received data bytes when the microcontroller has not been selected.

When a UART is not transmitting, the transmit line (typically called TxD) idles high. This is compatible with the ISO-11898 electrical specification. When a frame is transmitted, the receiver receives it right back. The microcontroller is programmed to drop this "echoed" frame.

The basic protocol has three phases:

Each module on the bus is assigned a unique address on the bus between 0 and 255. Module selection phase specifies the address of the module to be communicated with. The request packet sends between 1 and 15 command bytes to the selected module. The response packet returns between 0 and 15 response bytes from the selected module. After module is selected, as many request/response packet pairs can be sent to and form the same module without having to resend the module address. When it is time to select another module, the act of selecting the next module causes the currently selected module to be deselected.

The basic three phases of the protocol are summarized in the table below:

Transmit/
Receive
Data Comments Phase
8 7 6 5 4 3 2 1 0
Transmit 1 k a a a a a a a Select module at addresss kaaaaaaa Module Select
Receive 0 0 0 0 0 0 0 0 0 If k=1, return module selection acknowledgement
Transmit 0 n n n n c c c c nnnn=request byte count; cccc=checksum Request Packet
Transmit 0 d d d d d d d d dddddddd=request byte 1
...
Transmit 0 d d d d d d d d dddddddd=request byte n
Receive 0 m m m m c c c c mmmm=response byte count; cccc=checksum Response Packet
Receive 0 d d d d d d d d dddddddd=response byte 1
...
Receive 0 d d d d d d d d dddddddd=response byte m

The address selection phase is done by setting the 9th bit to a one. The address space is split in half. Any module that is assigned an address that is in the lower half (0-127), requires an acknowledgement byte. Any module that is assigned an address that is in the upper half (128-255), does not generate an acknowledgement. The acknowledgement byte is 0x00. The reason why a module might request that it be assigned an address in the lower half is because some microcontrollers need a little more time to switch from address only reception to data and address reception. Some microcontrollers can do the reception switch entirely in hardware; these microcontrollers are assigned addresses in the upper half.

Both the request packet and response packet start with an 8-bit length/checksum byte that contains 4-bits of length information and 4-bits of checksum. For the request packet, the length must be between 1 and 15, inclusive. For the response packet, the length can be between 0 and 15, inclusive. The checksum is computed by added up all the data bytes (excluding the length/checksum byte.) This value is shifted 4-bits to the right and added to itself.

    temp = byte1 + ... + byteN;
    checksum = (temp + (temp >> 4)) & 15;
								

3.2 Discovery Protocol

{This section is still quite rough...}

The purpose of the MakerBus discovery protocol is allow a MakerBus master module to discover each module that is electrically connected to the bus and assign each module a bus unique address between 0 and 254.

In order to support the MakerBus discovery protocol, each MakerBus module is assigned a world global unique identifier that is 96-bits long. This unique identifier is broken into three 32-bit fields of 1) vendor identifier, 2) product identifier, and 3) product serial number. A vendor obtains a vendor identifier from a central organization that is responsible for dispensing vendor identifiers. (There will probably be a nominal charge to prevent somebody from trying to exhaust the vendor identifiers as a prank.) After a vendor has obtained a vendor identifier, they are responsible for allocating product identifier and serial number.

The MakerBus discovery protocol is used to determine the 96-bit global unique identifier for each module electrically attached to the bus. As each global unique identifier is discovered, it is assigned a unique 8-bit module address. While the 96-bit global unique identifier never changes, the 8-bit address assigned to a module can change over time.

The module address of 255 (=0xff) is set aside exclusively for the discovery protocol. The address 255 is the factory default address that means the module does not have an assigned address yet. After discovery, none of the modules on the bus will have an assigned address of 255.

In relatively rare situation it is accidentally possible to have more than one module on the bus that have the same bus address between 0 and 254. This can occur when a module is grabbed from another project and transferred onto the bus for the first time. Obviously, there is no way to reliably communicate with two modules that have the same address. After the discovery protocol, any modules that have conflicting address will be assigned new addresses that no longer conflict.

The Discovery protocol occurs in two phases -- discovery initiation and discovery probe. The discovery initiation phase informs all of the modules on the bus that the discovery protocol is about to start and causes all of the modules to listen for address 255. The discovery probe mode is used to find the each module global unique identifier and actually assign the module a unique 8-bit address.

3.2.1 Discovery Initiation Phase

The first phase of the discovery protocol is called discovery protocol initiation. The purpose of initiation is to let all modules on the bus know that discovery is about to commence. This is done by attempting to select modules at all possible addresses from 0 to 254 and sending a command to the module that says "enable discovery mode". While this portion of the protocol takes very little time compared to the discovery probe phase, there are a number of issues that must be covered.

The sequence to inform a module that discovery mode is to be initiate is:

  1. Master sends address select
  2. Slave optionally responds with 0x00
  3. Master sends 0x1E.
  4. Master sends 0xFF.
The address select is an address between 0-254 with the 9th bit set. If the address is a lower half address (0-127), the slave will respond with a 0x00 acknowledge byte. The 0x1E is a valid request header of length 1 and checksum of 0xE. The 0xFF is command that says "enter discovery mode". The 4-bit checksum of 0xFF is 0xE. There is no response packet for this command.

A module with a lower half address (0-127) is required to respond with a 0x00 byte immediately after receiving the address. The discovery protocol master must deal with three conditions -- 0, 1, or more modules at the address.

The bus protocol master must deal with receiving a clean 0x00 byte, a byte with a framing error, or a break frame.

{A diagram would really help to visualize what is happening.}

Since MakerBus is a half duplex bus, a slave module with a lower half address that transmits the acknowledge byte of 0x00 after an address select, will also *receive* that acknowledge byte. In the situation immediately above where there two modules at the same lower half address, the slave module must also be prepared to receive either a 0x00 byte, a byte with a framing error, or a break frame. This frame is thrown away.

The modules with upper half addresses do not send acknowledge bytes after an module select, so they do not have worry about the multiple acknowledge issue.

3.2.2 Discovery Probe Phase

All modules have a three 13 byte registers (104 total bits per register). The three registers are called the identifier (I), probe (P), and mask (M) registers, respectively.

{Need a picture here.}

The I, P, and M registers are described below:

Identifier (I) Register
The I register contains 96-bits of global unique identifier followed by 8-bits of bus address as shown in the table below:
Bit(s) Byte(s) Access Description
0 - 31 0 - 3 Read-only Vendor Identifier
32 - 63 4 - 7 Read-only Product Identifier
64 - 95 8 - 11 Read-only Product Serial Number
96 12 Read-only Upper/lower module address select
97 - 103 12 Read-write Remaining 7 bits of module address
The first 12 bytes of the I register are allocated in 4 byte chunks for vendor identifier, product identifier, and product serial number respectively. These values are assigned by the vendor when the module is manufacturer and can not be changed. The last byte corresponds the current module address. Bit 96 is read only and specifies whether the module is to have a lower half address (bit 96=0) or an upper half address (bit 96=1). The remaining 7 address bits can be changed as part of the discovery protocol.
Probe (P) Register
The P register is written 1 bit at a time byte the probe command.
Mask (M) Register
The M register contains a mask value that is always a continuous sequence of 1's followed by a continuous sequence of 0's.
A match occurs when:
(I ∧ M) = (P ∧ M)
In words, a match occurs when the values of I masked by M and P masked by M are equal.

The discovery probe phase is entered by sending an address select to 255. All modules have been previously informed via the discovery initiate phase that they need to listen for the address 255.

After the 255 address has been received, the protocol repeatably sends out probe commands. All modules that match the probe command respond by sending a 0x00 byte. If no modules match a probe command, no response is generated whicht the discovery protocol master detects this condition using a timeout. The probing continues until all modules have been identified and have been assigned bus unique addresses.

The format of the probe command is:

Transmit/
Receive
Data Comments
8 7 6 5 4 3 2 1 0
Transmit 0 b p p p p p p p P[ppppppp] ← b; M ← (see below)
Receive 0 0 0 0 0 0 0 0 0 match; timeout=no match
The probe command will set the ppppppp'th bit of P to b. In addition, all bits from 0 to ppppppp in the M register are set to 1 and the rest are set to 0; this ensures that mask matches up to the ppppppp'th bit in P and I. All modules that that match (I∧M = P∧M), respond by sending a 0x00 byte.

As with the discovery initiate phase, multiple modules can respond to the same probe command with a 0x00 byte. If the 0x00 byte start bits start at the same time, the discovery master and all slave modules with receive a 0x00 byte. If there is any skew, master and all slaves will receive a frame with either a framing, overrun, or break error. The discovery master and all slaves must deal with error condition and clear it.

The discovery algorithm is pretty straight forward. The P register is treated as a 104 bit stack. The algorithm consists three phases that are repeatably cycled through:

Stack Advance
The stack advance phase starts by pushing 0's onto the stack one bit at a time. As long as there is a match, 0's keep being pushed onto the stack. The first time there is no match, the current 0 on the stack top is toggled to a 1. If there is a match (and there will be), the algorithm resumes pushing 0's onto the stack until there is another no match occurs. Again, the top bit is toggled to a 1. The pushing of 0's and toggling to 1 keeps occurring until the entire contents of one module's global unique identifier has be determined.
Address Assignment
For address assignment, the last 7-bit of the P register are set to the desired address. (The 8th bit is read-only and can not be changed.) After all bits have been set, a command to set the 105'th bit is sent. This causes the selected module to set its bus address to the new value by transfering the 7 address bits of the P register into the corresponding 7 bits of the I register.
Stack Retreat
The stack retreat phase starts by popping 1's off the P "stack" until a 0 is found. The 0 is toggled to a 1 and the bus is probed. As long as there is no match, the 1's keep getting popped off the stack until a 0 is encountered, which again gets toggled. This process continues until either match occurs after a toggle or the entire stack is popped off.

Using a Python like syntax, the discovery alogrithm is as follows:

    def discovery(self):
	""" Run the bus discovery protocol. """

	# Initialize everything:
	self.read_only_maximum = 96
	self.read_write_maximum = 103
	self.stack = [0] * (self.read_write_maximum + 2)
	self.low_address = 0
	self.high_address = 8
	self.top = -1

	# Repeat the three discovery phases until done:
	while True:
	    self.stack_advance()
	    self.address_assign()
	    self.stack_retreat()
	    if self.discovery_done():
		break						
The stack advance phase looks as follows:
    
    def stack_advance(self):
	""" Perform stack advance phase of the discovery protocol. """

	# Keep adding 0's and 1's to stack until we have a complte match:
	read_write_maximum = self.read_write_maximum
	top = self.top
	while top < read_write_maximum:
	    top += 1
	    if not self.probe(top, 0):
		# Not a 0, must be a 1:
		self.probe(top, 1)
	self.top = top						
The address assign phase looks as follows:
    def address_assign(self):
	""" Preform address assign phase of discovery protocol. """

	# Grab some values from self:
	stack = self.stack
	read_only_maximum = self.read_only_maximum
	read_write_maximum = self.read_write_maximum
	results = self.results

	# Depending upon high order bit of address, assign either an upper
	# half address or a lower half address:
	if stack[self.read_only_maximum] == 1:
	    # Assign an upper half address:
	    address = self.high_address
	    self.high_address = address + 1
	else:
	    # Assign a lower half address:
	    address = self.low_address
            self.low_address = address + 1

	# Set all of the address bits:
	read_write_address_bits = read_write_maximum - read_only_maximum
	for index in range(0, read_write_address_bits):
            bit = (address >> (read_write_address_bits + 1 - index)) & 1
	    self.probe(read_only_maximum + 1 + index, bit)

	# Cause the module to change its address:
	self.probe(read_write_maximum + 1, 1)			
The stack retreat phase looks as follows:
    def stack_retreat(self):
	""" Perform the stack retreat phase of discovery protocol. """

	# Back up over 1's, and toggle 0's to 1 until a successful probe:
	stack = self.stack
	top = self.read_only_maximum - 1
	while top >= 0:
	    if stack[top] == 1:
		# Back up over a 1:
		top -= 1
            elif self.probe(top, 1):
		# Toggle to 1; if matched stack retreat is done:
		break
	self.top = top
								

3.2.3 Discovery Protocol Example

A worked example should help to clarify the algorithm. In this example the 104 bit I register has been reduced down to 16-bits — 4-bits of vendor id, product id, serial number, and address respectively. For this example there are 4 modules on the bus with the following I register values:

Vendor ID Product ID Serial No. Address
0010000000100111
0010000010010010
0100001000111101
1001100001001000
when this example is done, the I register values for the modules will have updated address values that look as follows:
Vendor ID Product ID Serial No. Address
0010000000100000
0010000010010001
0100001000111000
1001100001001001
The example is broken down into 4 tables that correspond to matching each of the modules:
Match module 1: 0010 0000 0010 0111
CommandMatchesStackComment
0030Stack Advance
01200
020000
822001
0320010
0420010 0
0520010 00
0620010 000
0720010 0000
0810010 0000 0
0910010 0000 00
0a00010 0000 000
8a10010 0000 001
0b10010 0000 0010
0c10010 0000 0010 0
0d00010 0000 0010 00
8d10010 0000 0010 01
0e00010 0000 0010 010
8e10010 0000 0010 011
0f00010 0000 0010 0110
8f10010 0000 0010 0111 Match: 0010 0000 0010 0111
0d00010 0000 0010 00Address Assign
0e00010 0000 0010 000
0f00010 0000 0010 0000
9010010 0000 0010 0000 1
8b00010 0000 0011 Stack Retreat
8900010 0000 01
8810010 0000 1
Match module 2: 0010 0000 1001 0010
CommandMatchesStackComment
0910010 0000 10Stack Advance
0a10010 0000 100
0b00010 0000 1000
8b10010 0000 1001
0c10010 0000 1001 0
0d10010 0000 1001 00
0e00010 0000 1001 000
8e10010 0000 1001 001
0f10010 0000 1001 0010 Match: 0010 0000 1001 0010
0d10010 0000 1001 00Address Assign
0e00010 0000 1001 000
0f00010 0000 1001 0000
9010010 0000 1001 0000 1
8a00010 0000 101Stack Retreat
8900010 0000 11
8700010 0001
8600010 001
8500010 01
8400010 1
8300011
81101
Match module 3: 0100 0010 0011 1101
CommandMatchesStackComment
021010Stack Advance
0310100
0410100 0
0510100 00
0600100 000
8610100 001
0710100 0010
0810100 0010 0
0910100 0010 00
0a00100 0010 000
8a10100 0010 001
0b00100 0010 0010
8b10100 0010 0011
0c00100 0010 0011 0
8c10100 0010 0011 1
0d00100 0010 0011 10
8d10100 0010 0011 11
0e10100 0010 0011 110
0f00100 0010 0011 1100
8f10100 0010 0011 1101 Match: 0100 0010 0011 1101
0d00100 0010 0011 10Address Assign
8e00100 0010 0011 101
0f00100 0010 0011 1010
9010100 0010 0011 1010 1
8900100 0010 01Stack Retreat
8800100 0010 1
8700100 0011
8500100 01
8400100 1
8300101
820011
8011
Match module 4: 1001 1000 0100 1000
CommandMatchesStackComment
01110Stack Advance
021100
0301000
8311001
0401001 0
8411001 1
0511001 10
0611001 100
0711001 1000
0811001 1000 0
0901001 1000 00
8911001 1000 01
0a11001 1000 010
0b11001 1000 0100
0c01001 1000 0100 0
8c11001 1000 0100 1
0d11001 1000 0100 10
0e11001 1000 0100 100
0f11001 1000 0100 1000 Match: 1001 1000 0100 1000
0d11001 1000 0100 10Address Assign
8e01001 1000 0100 101
0f01001 1000 0100 1010
9011001 1000 0100 1010 1
8b01001 1000 0101 Stack Retreat
8a01001 1000 011
8801001 1000 1
8701001 1001
8601001 101
8501001 11
820101
81011

3.3 Common Shared Commands

{Common commands go here}

3.3.1 Upload Protocol

The upload protocol is:

    ULong address_get(void);
    void address_set(ULong address);
    ULong memory_get(void);
    UByte memory_set(UShort mask, ULong value);
    void execute();
								

4.0 Mechanical Specification

All MakerBus modules All MakerBus modules are designed such that their mounting holes align with backing plate that has a grid of 10mm by 10mm holes in the X and Y direction. Each hole is 3.2mm in diameter.

The backing plate is compatible with any modules that have holes aligned on 10mm by 10mm holes. A partial list of modules that use such a hole alignment is:

SeeedStudio Grove System
The SeeedStudio Grove system is a system of modules based on a 4-wire cable where each module has at least 2 holes that are 20mm apart.
.NET Gadgeteer
The .NET Gadgeteer modules are required to have holes that are separated by increments of 5mm. Many of the modules have holes separated by 10mm. Most modules are made by GHI Electronics.
Demand Peripherals
Most of the modules from Demand peripherals have holes separated by 40mm by 40mm.
There are probably some others (Arduino TinkerKit?, others?) smARtDUIO is close, but not quite.

The preferred board size for MakerBus modules is in increments of approximately 25mm by 25mm. The following tables summarize common sizes.

X Length Y Width X Hole Pitch Y Hole Pitch Description
49mm 49mm 40mm 40mm Regular board
49mm 99mm 40mm 90mm Double board
99mm 99mm 90mm 90mm Quad board
The mounting holes are 3.2mm in diameter with minimum keep-out diameter of 6.0mm. 3.2mm holes are compatible with both metric M3.0 screws and imperial #4 (0.125 hole diameter) screws. If the boards have a rounded corners, they should be have a radius of 4.5mm centered on the mounting hole centers. Rounded corners are not required. Boards with square corners can be manufactured with the popular scored V-groove and snap PCB technology.


Copyright © 2011-2013 by Wayne C. Gramlich.