Skip to content

How your game software should use the EXP connection

The EXP connection will (most likely) be on the second serial port serial port on the Neuron. It uses the same VID/PID (0x2E8A/0x103B) as the NET connection since it's the same USB device. Connect to the EXP port at 921600 baud, 8N1.

The EXP connection is pretty different than the NET connection, so it's worth reading the docs which explain it.

The big difference between the NET and EXP connections, from a protocol perspective, is that the NET connection talks to the single NET processor on the Neuron. The EXP connection talks to multiple EXP processors—one for each Expansion board that's connected. A typical machine will have at least two EXP boards (the one built-in to the Neuron and one for your playfield LEDs), but you could have more too. (Cabinet lighting? Topper?)

Every EXP board and/or EXP breakout board has a unique address, so EXP bus commands need to be addressed to the specific board you want to talk to. You can either (1) embed the address in each command, or (2) send an EA: command to set one address as "active", and then all subsequent commands without addresses specified will be sent to that address.

(Technically every EXP board receives every message. They're just configured to ignore messages that aren't addressed to them.)

Clear out the serial buffer

Once the serial connection is established with the Neuron's EXP serial port, you should send a few bytes of data to clear out any junk that might be in the serial buffers. (This is the similar to the NET connection.)

The EXP bus in general is not as "chatty" as the NET connection. Not every failed command will have a response. We recommend that you send four CRs (0x0D), which might have a response if the hardware was not power cycled and that board is still active, or it might have no response if no board is active. So send four CRs, and be ready to receive up to four XX:F responses, or fewer, or none.

Send an ID: command to each expansion board

Next you can use the ID: command to confirm what's connected to the EXP bus. If you send ID: without specifying an address, in theory the Neuron will respond, but in practice it's not guaranteed since it's possible that the Neuron was not reset since your game software started up, meaning some random board might be active. So it's best to send ID: with an address specified, since you should know which boards are attached.

So, you could first send ID@48: which will query the Neuron's built-in expansion board. Be sure to await the ID: response before sending the next command, otherwise you might not know which response goes with which address.

Once you get the Neuron's EXP ID: back, you can query the next board. (Maybe ID@B4: if you have an FP-EXP-0071 board.)

If you want to write a tool that queries all the boards on the EXP bus, there aren't that many different addresses (maybe 10-15 total?), so you can just send them one by one. Any board that is not attached will not have a response, but the boards that are attached will respond with their ID: quickly (usually under 30ms), so you can timeout quickly and move on.

Sending ID: to breakout boards

Breakout boards will also respond to ID: commands (via the 3-character address which is the Expansion board address plus the breakout value 0-5.) If you want to confirm all hardware, you could send ID: commands to each breakout. Again, ping them one-by-one.

Remember that every expansion board will have a built-in breakout board that's ID 0. So the command ID@48: will get the ID of the built-in expansion board on the Neuron, and then ID@480: will get the ID: response of the built-in breakout board from the built-in expansion board on the Neuron. ID@481: will be a breakout attached to breakout port 1 on the Neuron (the Smart Power Filter Board, for example), etc.

Reset the expansion boards

Once you connect to each expansion board / breakout board, you can send a BR: command to reset the board. This is a 2-char address which applies to the expansion board, which then resets that board and all attached breakout boards, e.g. BR@48: What this does depends on the device type. For example, LEDs will turn off. Servos are powered off. Etc.

In MPF, the machine config files for FAST hardware specify the Expansion boards and breakout boards attached. So MPF is able to know what Expansion (2-character) and Breakout (3-character) addresses are attached. MPF "walks the tree" board-by-board, sending a 2-character ID: command to a board, then 3-char ID: commands to each breakout, and finally a BR: command to the 2-char Expansion board address. Then it repeats this entire process for the next expansion board until it hits them all.

The BR: command will return a BR:P response, which you can process or ignore. (MPF ignores it.) These come back really quick, like within 1-2ms, so "waiting" for them is certainly fine.

Now start doing things!

At this point you should be able to start using the EXP bus to run lights and move servos and stuff.

What exact commands do you use, and how do you do configure things? It depends on the device type. See our specific guides for details:

Example EXP serial protocol command sequence

Here's the serial command log of MPF starting up and connecting to the Neuron and an FP-EXP-0071 expansion board. It configures one servo and then attract mode starts, which in this case has some servo actions and lots of LEDs.

  • >>>> are raw commands from the host PC to the EXP connection
  • <<<< are raw messages from the EXP connection to the host PC
  • Since this log is raw serial chunks, you'll see messages are often received in chunks.
  • Click the (+) for details on a specific line.
11:38:49,289 : [EXP] : Connecting to /dev/tty.usbmodem11103 at 921600bps
11:38:49,293 : [EXP] : >>>> '\r\r\r\r' # (1)!
11:38:49,295 : [EXP] : <<<< 'XX:F\rXX:F\rXX:F' # (2)!
11:38:49,295 : [EXP] : <<<< '\rXX:F\r'
11:38:49,296 : [EXP] : >>>> 'ID@B4:\r' # (3)!
11:38:49,296 : [EXP] : <<<< 'ID'
11:38:49,296 : [EXP] : <<<< ':EXP FP-EXP-0071  0.7\r'
11:38:49,297 : [EXP] : >>>> 'ID@B40:\r' # (4)!
11:38:49,298 : [EXP] : <<<< 'I'
11:38:49,298 : [EXP] : <<<< 'D:BRK FP-EXP-0071'
11:38:49,298 : [EXP] : <<<< '  0.0\r'
11:38:49,299 : [EXP] : >>>> 'BR@B4:\r' # (5)!
11:38:49,299 : [EXP] : <<<< ''
11:38:49,299 : [EXP] : <<<< 'R:P\r'
11:38:49,301 : [EXP] : >>>> 'ID@48:\r' # (6)!
11:38:49,301 : [EXP] : <<<< 'I'
11:38:49,302 : [EXP] : <<<< 'D:EXP FP-EXP-2000  0.8\r'
11:38:49,302 : [EXP] : >>>> 'ID@480:\r'
11:38:49,303 : [EXP] : <<<< 'I'
11:38:49,303 : [EXP] : <<<< 'D:LED FP'
11:38:49,303 : [EXP] : <<<< '-BRK-0001  0.'
11:38:49,303 : [EXP] : <<<< '8\r'
11:38:49,304 : [EXP] : >>>> 'BR@48:\r'
11:38:49,304 : [EXP] : <<<< ''
11:38:49,304 : [EXP] : <<<< 'R:P\r'
11:38:49,431 : [EXP] : >>>> 'EM@B40:0,1,BB8,1F4,9C4,5DC\r' # (7)!
11:38:49,435 : [EXP] : <<<< 'EM:P\r'
11:38:49,524 : [EXP] : >>>> 'MP@B40:0,7F,BB8\r' # (8)!
11:38:49,524 : [EXP] : >>>> 'MP@B40:0,FF,BB8\r' # (9)!
11:38:49,547 : [EXP] : >>>> 'EA:B40\r' # (10)!
11:38:49,547 : [EXP] : >>>> 'RD:X\x02\xff\x00\x00\x03\xcc\x00\xcc\x04\x00\x00 \x05\x00 \x00\x06"@@\x07\x00\x00 \x08"@@\t"@@\n\x00\x00\x00\x0c"@@\r\x00\x00\xff\x0e\xaa\x00\xff\x13\xff\xcc\x00\x14\xaa\x00\xff\x15\xff\x00\x00\x16\x00\x80\x00\x17\x00\x00\xff\x18\xff\x00\x00\x19\x00\x80\x00\x1c"@@\x1d"@@\x1e"@@\x1f\x00\x00  \x00 \x00!\x00\x00 ""@@#\xff\x00\x00\'"@@("@@)"@@*\x00\x00 +\xcc\x00\xcc,"@@."@@/"@@1"@@2"@@4"@@5"@@6"@@7"@@8\xcc\x00\xcc9\xff\x00\x00:\xff\x00\x00;\x00 \x00<\x00\x00 =\xff\x00\xff@\x00\x00 A\xcc\xff\x00B\xff\x00\x00C\x00 \x00D"@@E"@@F\xff\x00\x00G\x00 \x00J\x00\xff\x00M\x00\x00\xffN\x00\x00 R\x00\x00S\xcc\x00\xccT\xff\x00\x00U\xff\x00\x00V\xaa\x00\xffW\x00\x00\xffX\x00\x80\x00Z\xff\x00\x00\\"@@]"@@^"@@_"@@`\xcc\x00\xcca\x00\x00 b\xff\xff\x00e\xff\x00\x00f\x00 \x00g"@@h"@@j"@@k"@@l"@@m"@@n"@@o"@@p"@@q\xff\xa5\x00r"@@s"@@t\x00\x00 '
# (11)!
  1. Initial four CRs sent
  2. 4 expected XX:F since CRs are not real commands. Note these are split across two chunks, but the \r is used to assemble chunks back into complete messages.
  3. Getting the ID of the Neuron's Expansion board.
  4. Get the ID of the Neuron's Breakout board. (This is the built-in breakout, so it's not strictly necessary, but MPF just treats it like any other breakout.)
  5. Got the IDs back for everything on the Neuron Expansion board, so now reset it
  6. Do the same process for the FP-EXP-0071 board.
  7. Now that the boards are all set, we configure the servo. BTW, note the timestamps: the entire process of walking, IDing, and resetting, and configuring was under 0.2 secs.
  8. This command is sent by MPF to return the servo to its home position. (This is a home position set by MPF which is why it's sent as a regular MP: command and not some of the custom servo commands.)
  9. Sets the servo to its max position, which is specified from this machine's attract show.
  10. Sets the active board to the FP-EXP-0071 board. MPF sets the active board, then sends LED updates for that board. This will soon be changed to just embed the board address into the RD: command which will reduce the overall number of bytes sent.
  11. This is what a binary RD: LED update command looks like. It's nonsense when rendered into text, but it's a binary command that sets the dirty LEDs on that breakout to their next colors.

N or > jump the next page, P or < for previous, search with S or ?