BrickPi3 Communication Protocol Details
Overview
The Raspberry Pi and BrickPi3 communicate using SPI. The Raspberry Pi acts as the master, writing to and reading from the BrickPi3. The BrickPi3 acts as the slave, receiving from and replying to the Raspberry Pi.
The SPI bus can run at up to 500kbps.
For values over 8-bits, the bytes are sent most significant first.
Updated 2017/04/03 for firmware version 1.4.0
Every message starts with a 2-byte header:
Byte 1 is the BrickPi3 SPI address (default address is 1, but it can be changed to anything from 1 through 255).
Byte 2 is the message type.
To write to the BrickPi (e.g. control a motor or configure a sensor), the RPi sends the header followed by the following data:
SET_LED:
An 8-bit signed value of -1 (FW controls the LED) or 0 through 100 (LED brightness percentage).
SET_SENSOR_TYPE:
An 8-bit bit-field to specify the sensor port(s). PORT_1, PORT_2, PORT_3, and/or PORT_4.
An 8-bit value to specify type.
If type is CUSTOM:
A 16-bit value with the configuration flags.
If type is I2C:
An 8-bit value to specify type.
An 8-bit value to specify I2C settings.
An 8-bit value to specify I2C speed. Minimum time in microseconds between each I2C signal transition. 0 sets the speed to 100kbps.
If the I2C settings SAME bit is set:
A 32-bit value to specify how many US should be between each message.
An 8-bit value to specify the I2C address of the slave.
An 8-bit value to specify how many I2C bytes to read.
An 8-bit value to specify how many I2C bytes to write.
For each I2C byte to write:
An 8-bit I2C byte to write.
SET_MOTOR_POWER:
An 8-bit bit-field to specify the sensor port(s). PORT_A, PORT_B, PORT_C, and/or PORT_D.
An 8-bit signed value to specify motor power. -100 to 100 for reverse full to forward full, or greater than 100 for float.
SET_MOTOR_POSITION:
An 8-bit bit-field to specify the sensor port(s). PORT_A, PORT_B, PORT_C, and/or PORT_D.
A 32-bit signed value to specify motor target position in degrees. -2,147,483,648 to 2,147,483,647.
OFFSET_MOTOR_ENCODER:
An 8-bit bit-field to specify the sensor port(s). PORT_A, PORT_B, PORT_C, and/or PORT_D.
A 32-bit signed value to specify motor encoder offset in degrees. -2,147,483,648 to 2,147,483,647. To zero the encoder, write the current position as the offset.
To read from the BrickPi (e.g. read a sensor, or check the battery voltage), the RPi sends the header plus 2 bytes plus enough bytes to read the message from the BrickPi3:
Byte 4 (including the header and extra two bytes) should read 0xA5, otherwise something went wrong.
READ_MANUFACTURER:
A 20 char string - the manufacturer name
READ_NAME:
A 20 char string - the board name
READ_HARDWARE_VERSION:
A 32-bit value - the hardware version. 3 sets of up to 3 digits, e.g. 3002001 would be V3.2.1
READ_FIRMWARE_VERSION:
A 32-bit value - the firmware version.
READ_ID:
A 128-bit value - the serial number unique to each BrickPi3.
READ_VOLTAGE_3V3:
READ_VOLTAGE_5V:
READ_VOLTAGE_9V:
READ_VOLTAGE_VCC:
A 16-bit value - The voltage (in millivolts) for the specified circuit.
GET_SENSOR_1:
GET_SENSOR_2:
GET_SENSOR_3:
GET_SENSOR_4:
An 8-bit value - The configured sensor type
An 8-bit value - The sensor status
CUSTOM:
A 32-bit value - The ADC and digital readings of the sensor port:
Bit 1 - Pin 5 state
Bit 2 - Pin 6 state
Bits 3-8 unused
Bits 9-20 - Pin 6 ADC
Bits 21-32 - Pin 1 ADC
I2C:
For each I2C byte read:
An 8-bit byte.
TOUCH:
NXT_TOUCH:
EV3_TOUCH:
NXT_ULTRASONIC:
EV3_COLOR_REFLECTED:
EV3_COLOR_AMBIENT:
EV3_COLOR_COLOR:
EV3_ULTRASONIC_LISTEN:
EV3_INFRARED_PROXIMITY:
An 8-bit value.
NXT_LIGHT_ON:
NXT_LIGHT_OFF:
NXT_COLOR_RED:
NXT_COLOR_GREEN:
NXT_COLOR_BLUE:
NXT_COLOR_OFF:
EV3_GYRO_ABS:
EV3_GYRO_DPS:
EV3_ULTRASONIC_CM:
EV3_ULTRASONIC_INCHES:
A 16-bit value (signed for the GYRO, and in 10ths of units for ULTRASONIC)
EV3_COLOR_RAW_REFLECTED:
EV3_GYRO_ABS_DPS:
Two 16-bit values (For GYRO, absolute position and rotation speed, for COLOR, reflected light and raw value(?))
EV3_COLOR_COLOR_COMPONENTS:
Four 16-bit values (red reflected, green reflected, blue reflected, raw value(?))
EV3_INFRARED_SEEK:
Eight 8-bit signed values (For each of the four channels, heading and distance)
EV3_INFRARED_REMOTE:
Four 8-bit values (For each of the four channels, a byte representing which buttons are being pressed)
Write examples (with header):
Setting motor C power to reverse 50% would be this four byte write [ADDRESS, WRITE_MOTOR_POWER, PORT_C, -50]
Configuring sensor 1 to NXT Light On would be this four byte write [ADDRESS, SET_SENSOR_TYPE, PORT_1, NXT_LIGHT_ON]
Read examples (with header):
Read battery voltage. Write array [ADDRESS, READ_VOLTAGE_VCC, 0, 0, 0, 0]. The read array will be [0, 0, 0, 0xA5, (highest 8 bits of the voltage in millivolts), (lowest 8 bits of the voltage in millivolts)]
Read sensor 1 (configured as NXT Light On). Write array [ADDRESS, GET_SENSOR_1, 0, 0, 0, 0]. The read array will be [0, 0, 0, 0xA5, (highest 8 bits of sensor value), (lowest 8 bits of sensor value)]