Skip to content

Photon Protocol

The Photon Protocol is designed to facilitate two different types of addressing. In Photon, you can address a feeder using both its UUID (the hard-coded name of that unique device) and its slot (the physical location on the machine). This is so that we can:

  • keep track of what part is loaded into a feeder even when it's moved to a different location
  • find a feeder regardless of where it's loaded on the machine
  • easily discover new feeders when they're loaded onto the machine

Only the host may initiate communication. Every Photon interaction is comprised of two packets: one packet from the host with a command and optional payload, and a response from a feeder with a status and optional payload of information.

The following is the basic Photon packet structure.

The packet is made up of two parts: the header and the payload. The header contains exactly five bytes: "to" address, "from" address, packet ID, payload length, and the CRC. The payload always has at least one byte, either a command ID or a status. The payload can have optional further bytes.

The host can send either broadcast and unicast commands. Unicast commands are meant for only the device in a certain slot. Broadcast commands are effectively speaking to the whole bus, and are instead addressing based on UUID, initialization status, or potentially other factors.

Example Feeder Init and Feed

sequenceDiagram
    participant H as Host
    participant F as Slot 5
    H->>F: Hey, is a feeder at slot 5? (Command ID: 0x01)
    activate F
    F->>H: Yes, my name is {UUID}
    deactivate F
    H->>F: Cool, please initalize. (Command ID: 0x02)
    activate F
    F->>H: I am initialized.
    deactivate F
    H->>F: Please feed 4mm. (Command ID: 0x04)
    activate F
    F->>H: On it!
    H->>F: Are you done yet? (Command ID: 0x06)
    Note right of H: Delay
    H->>F: Are you done yet? (Command ID: 0x06)
    Note right of H: Delay
    H->>F: Are you done yet? (Command ID: 0x06)
    F->>H: I'm done, and I fed successfully.
    deactivate F

Example Bus Scan

sequenceDiagram
    participant H as Host
    participant F as Slot N
    loop
        H->>F: Hey, is a feeder at slot N? (Command ID: 0x01)
        F->>H: Yes, my name is {UUID}
        H->>F: Cool, please initalize (Command ID: 0x02)
        activate F
        F->>H: I am initialized.
        deactivate F
        Note right of H: N++
    end

Header Bytes

To Address

This byte indicates which address the packet is intended for. This address value is equivalent to the slot addresses.

Valid values are anywhere between 0x00 and 0xFF. Address 0x00 is reserved for the host, and address 0xFF is reserved for broadcast commands.

From Address

This byte indicates which address the packet is coming from. This address value is equivalent to the slot addresses.

Valid values are anywhere between 0x00 and 0xFF. Address 0x00 is reserved for the host, and 0xFF should not be used.

Packet ID

The Packet ID is an identifying byte that allows the devices on the bus to keep track of requests. When a feeder responds to a command, it includes the Packet ID of the initiating packet. This allows the host to determine which packet the feeder is responding to.

This byte is a value between 0x00 and 0xFF. The host should increment this value for every command sent, and roll back to 0x00 once it reaches 0xFF.

Payload Length

The payload length is the number of bytes contained in the payload. This number will always be at least 0x01, as each packet has at least a Command ID or Status.

CRC

The CRC byte is a checksum calculated on the entire packet sans the checksum byte. The checksum can be calculated as shown below:

JavaScript

calcCRC(data){
    let crc = 0;
    for(var i = 0; i<data.length; i++){
        crc = crc ^ (data[i] << 8);
        for(let j = 0; j < 8; j++){
            if ((crc & 0x8000) != 0) {
            crc = crc ^ (0x1070 << 3);
            }
            crc <<= 1;
        }
    }
    return (crc >> 8) & 0xFF;
}

C

uint8_t crc8(uint8_t data, size_t len) {
    uint32_t crc = 0;

    for (size_t i = 0; i < len; i++) {
        crc ^= (data << 8);
        for (size_t bit_n = 0; bit_n < 8; bit_n++) {
            if (crc & 0x8000) {
                crc ^= (0x1070 << 3);
            }
            crc <<= 1;
        }
    }

    return (uint8_t)(crc >> 8);
}

Once the CRC is calculated, it should be spliced into the packet in the appropriate location. The CRC should be recalculated and compared with the received CRC for every received packet to confirm data integrity.

Payload

The first byte of the payload is always a Command ID when coming from the host, and always a Status when coming as a response from a feeder. The Command ID tells the feeder what action to perform or what information to send. The Status tells the host the status of the command.

The rest of the payload is used for any other information that needs to be sent, depending on the situation.

Command Code Name
0x01 GET_FEEDER_ID
0x02 INITIALIZE_FEEDER
0x03 GET_VERSION
0x04 MOVE_FEED_FORWARD
0x05 MOVE_FEED_BACKWARD
0x06 MOVE_FEED_STATUS
0xbf VENDOR_OPTIONS
0xc0 GET_FEEDER_ADDRESS
0xc1 IDENTIFY_FEEDER
0xc2 PROGRAM_FEEDER_FLOOR
0xc3 UNINITIALIZED_FEEDERS_RESPOND
Status Code Name
0x00 OK
0x01 WRONG_FEEDER_ID
0x02 COULDNT_REACH
0x03 UNINITIALIZED_FEEDER
0x04 FEEDING_IN_PROGRESS
0x05 FAIL
0xFE TIMEOUT
0xFF UNKNOWN

Unicast Commands

GET_FEEDER_ID 0x01

Send
Requires Initialized NO
Addressing UNICAST
Payload NONE
Receive Value Position
Status OK 0
Payload 12 Byte UUID 1-13

GET_ID is used to get a feeder's UUID knowing only it's slot address. GET_ID is used mainly to scan the bus address space and see if a feeder is present in a slot, and get its UUID for initilizing.

Example

Send:

[02] [00] [07] [01] [C0] [01]
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0x01 means GET_ID
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Receive:

[00] [02] [07] [0D] [D7] [00] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   12 Byte UUID
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 13
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

INITIALIZE_FEEDER 0x02

Send
Requires Initialized NO
Addressing UNICAST
Payload 12 Byte UUID
Receive Value Position
Status OK (0x00), WRONG_FEEDER_ID (0x01) 0
Payload 12 Byte UUID 1-13

INITIALIZE_FEEDER is used to initialize a feeder and allow it to perform other functions.

Example

Send:

[02] [00] [07] [0D] [C0] [02] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   12 Byte Feeder UUID
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0x02 means INITIALIZE
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 13
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Receive:

[00] [02] [07] [0D] [D7] [00] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   12 Byte Feeder UUID
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 13
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

GET_VERSION 0x03

Send
Requires Initialized YES
Addressing UNICAST
Payload None
Receive Value Position
Status OK 0
Payload Version 1

GET_VERSION is used to get the version of the protocol used by a specific feeder.

Example

Send:

[02] [00] [07] [01] [C0] [03]
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0x02 means GET_VERSION
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Receive:

[00] [02] [07] [02] [D7] [00] [01]
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   Protocol Version
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 2
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

MOVE_FEED_FORWARD 0x04

Send
Requires Initialized YES
Addressing UNICAST
Payload Distance to move (in tenths of a mm)
Receive Value Position
Status OK 0
Payload Expected Feed Time in milliseconds 1-2 (Big Endian)

MOVE_FEED_FORWARD is used to command a feeder to feed a certain distance forward. It returns the expected amount of time it will take to perform the feed.

Example

Send:

[02] [00] [07] [02] [C0] [04] [28]
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   Distance (in tenths of a mm)
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0x04 means MOVE_FEED_FORWARD
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 2
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Receive:

[00] [02] [07] [03] [D7] [00] [02] [48]
 |    |    |    |    |    |    |____|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   2 Byte Expected Time to Feed
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 3
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

MOVE_FEED_BACKWARD 0x05

Send
Requires Initialized YES
Addressing UNICAST
Payload Distance to move (in tenths of a mm)
Receive Value Position
Status OK 0
Payload Expected Feed Time in milliseconds 1-2 (Big Endian)

MOVE_FEED_BACKWARD is used to command a feeder to feed a certain distance backwards. It returns the expected amount of time it will take to perform the feed.

Example

Send:

[02] [00] [07] [02] [C0] [05] [28]
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   Distance (in tenths of a mm)
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0x05 means MOVE_FEED_BACKWARD
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 2
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Receive:

[00] [02] [07] [0D] [D7] [00] [02] [48]
 |    |    |    |    |    |    |____|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   2 Byte Expected Time to Feed
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 3
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

MOVE_FEED_STATUS 0x06

Send
Requires Initialized YES
Addressing UNICAST
Payload None
Receive Value Position
Status OK (0x00), COULDNT_REACH (0x01) 0
Payload None

MOVE_FEED_STATUS is used to determine if a feeder has finished a feed command, and get the status of the last feed. Feeding is blocking, so this command is intended to be used to probe a feeder until a response is received with the last feed's status.

Example

Send:

[02] [00] [07] [01] [C0] [06]
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0x06 means MOVE_FEED_STATUS
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Receive:

[00] [02] [07] [01] [D7] [00]
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

VENDOR_OPTIONS 0xBF

Send
Requires Initialized YES
Addressing UNICAST
Payload Implementation Dependent
Receive Value Position
Status Implementation Dependent 0
Payload Implementation Dependent

VENDOR_OPTIONS is a section used to add vendor-specific commands behind a dedicated command ID. The specifics of this command depend on your implementation.

Example

Send:

[02] [00] [07] [0D] [C0] [BF] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   Vendor-Specific Payload
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0xBF means VENDOR_OPTIONS
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length is dependent on implementation
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Receive:

[00] [02] [07] [0D] [D7] [3F] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   Vendor-Specific Payload
 |    |    |    |    |    |
 |    |    |    |    |   Vendor-Specific Status
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length dependent on implementation
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

Broadcast Commands

GET_FEEDER_ADDRESS 0xC0

Send
Requires Initialized NO
Addressing BROADCAST
Payload 12 Byte UUID
Receive Value Position
Status OK 0
Payload None

GET_FEEDER_ADDRESS is used to get the slot address of a feeder based on its UUID. If a feeder's UUID matches the one sent in the payload, it will respond with status OK (0x00) with a "From" address that indicates its slot.

Example

Send:

[FF] [00] [07] [0D] [C0] [C0] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   12 Byte Feeder UUID
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0xC0 means GET_FEEDER_ADDRESS
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 13
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
Broadcast Address

Receive:

[00] [02] [07] [01] [D7] [00]
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

IDENTIFY_FEEDER 0xC1

Send
Requires Initialized NO
Addressing BROADCAST
Payload 12 Byte UUID
Receive Value Position
Status OK 0
Payload None

IDENTIFY_FEEDER is used to cause the feeder to do some action that makes it identifiable by a user. For example, the LumenPnP feeders flash their main indicator light when they receive this command.

Example

Send:

[FF] [00] [07] [0D] [C0] [C1] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   12 Byte Feeder UUID
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0xC1 means IDENTIFY_FEEDER
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 13
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
Broadcast Address

Receive:

[00] [02] [07] [01] [D7] [00]
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address

PROGRAM_FEEDER_FLOOR 0xC2

Send
Requires Initialized NO
Addressing BROADCAST
Payload 12 Byte UUID
Address to Program
Receive Value Position
Status OK 0
Payload None

PROGRAM_FEEDER_FLOOR is used to program an address into a slot. This should only need to be done once per slot.

Example

Send:

[FF] [00] [07] [0E] [C0] [C2] [02] [48] ..... [37] [30] [05]
 |    |    |    |    |    |    |_____________________|   |
 |    |    |    |    |    |    |                         |
 |    |    |    |    |    |    |                         |
 |    |    |    |    |    |    |                        Address to program
 |    |    |    |    |    |    |
 |    |    |    |    |    |   12 Byte Feeder UUID
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0xC2 means PROGRAM_FEEDER_FLOOR
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 14
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
Broadcast Address

Receive:

[00] [05] [07] [01] [D7] [00]
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address (which was just programmed)
 |
To Address

UNINITIALIZED_FEEDERS_RESPOND 0xC3

Send
Requires Initialized NO
Addressing BROADCAST
Payload None
Receive Value Position
Status OK 0
Payload 12 Byte UUID 1-12

UNINITIALIZED_FEEDERS_RESPOND causes all feeders on the bus that are not initialized to respond. This command should only be used when it's known that there's only one uninitialized feeder on the bus. This command is mainly used for helping in slot programming utilies.

Example

Send:

[FF] [00] [07] [0E] [C0] [C3]
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |    |
 |    |    |    |    |   Sending Command 0xC3 means UNINITIALIZED_FEEDERS_RESPOND
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 1
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
Broadcast Address

Receive:

[00] [02] [07] [0D] [D7] [00] [02] [48] ..... [37] [30]
 |    |    |    |    |    |    |_____________________|
 |    |    |    |    |    |    |
 |    |    |    |    |    |    |
 |    |    |    |    |    |   12 Byte Feeder UUID
 |    |    |    |    |    |
 |    |    |    |    |   Status 0x00 means OK
 |    |    |    |    |
 |    |    |    |   Checksum
 |    |    |    |
 |    |    |   Payload Length of 13
 |    |    |
 |    |   Packet ID
 |    |
 |   From Address
 |
To Address