BBR Digital Expander Documentation

Java API summary#

The everyday tier, which is what most teams need. Every method validates its arguments and throws a message that names the fix rather than an array index exception.

Getting the device#

BBRDigitalExpander exp = hardwareMap.get(BBRDigitalExpander.class, "expander");

Encoders#

Method Returns
getEncoderCount(channel) Signed accumulated counts
getEncoderVelocity(channel) Signed counts per second, computed on the board
getPulseWidthUs(channel) Pulse width in µs (PULSE_WIDTH mode only)
resetEncoder(channel)
resetAllEncoders()

Sensors#

Method Returns
isSensorConnected(port) boolean
getSensorType(port) COLOR, DISTANCE, or EMPTY
getColorClass(port) 0 for no match, else the colour slot 17
seesColor(port, classSlot) boolean
getDistanceMm(port) Distance in mm

Teaching and triggers#

All of these save to flash automatically, which is why they are setup calls: run them once, or on a button press, never in a match loop. See Set up once.

Method Effect
teachColor(port, classSlot) Learn the colour currently in view
triggerOnColor(output, port, classSlot) Output high while that colour is seen
triggerWhenNear(output, port, maxMm) Output high while something is within range
triggerWhenEncoderPast(output, channel, counts) Output high past a threshold
triggerWhenFacing(output, headingDeg, toleranceDeg) Output high while facing that heading
clearOutputLatch(output) Un-latch one output
clearAllOutputLatches() Un-latch all four

Heading and pose#

These throw rather than return a heading or pose the board cannot stand behind.

Method Returns
getHeading() Degrees, CCW positive
resetHeading()
calibrateGyro() — (robot must be still, ~1 s)
getPose() Pose2D — mm, radians, +X forward, +Y left
setPose(pose)
waitForLocalizerReady(timeoutMs) boolean
readImu() ImuState

Mounting and direction#

Set once when the board is bolted on; not auto-saved, so follow with saveConfigToFlash().

Method Effect
setEncoderInvertMask(mask) Bit per channel; set inverts that encoder’s direction
getEncoderInvertMask() Current mask
setImuAxisUp(axis) Which board axis points up (BBRRegMap.AXIS_*, flat is AXIS_POS_Z)
getImuAxisUp() Current axis-up setting

Board identity#

Method Returns
getCapabilities() Capability bits
isConfigDirty() Are there unsaved config changes
isDataFresh() Did the last read actually reach the device

Advanced tier#

The full register map is available underneath: configureOutput(), writeColorClass(), writeDistanceClass(), setChannelMode(), setPwmChannelParams(), setLocalizerParams(), readTelemetry(), runCommand().

Nothing in the advanced tier saves automatically. Call saveConfigToFlash(), or the configuration is gone at power-off. isConfigDirty() tells you whether you have unsaved changes.

Behaviour worth knowing#

Init refuses loudly. A wrong device ID or an unsupported protocol version throws at init rather than producing corrupt data later.

One transaction per snapshot. The everyday getters share a snapshot refreshed roughly every 10 ms, so four questions in one loop iteration cost one transaction and the answers are mutually consistent.

Commands are idempotent. Every command carries a token, so an I2C retry cannot execute it twice.

Config writes are verified by readback. The bus layer never NAKs, so an out-of-range value would otherwise be silently ignored.

IMU access throws when the gyro cannot be trusted rather than returning zeros, because a heading of 0.00 that never changes is indistinguishable from working software.

Failed reads serve the last known good value. When a read cannot reach the device the driver returns the previous snapshot and isDataFresh() goes false, rather than throwing. This is what stops a normal OpMode shutdown from detonating your loop. A genuine wiring fault — a long streak of failures — still throws.

BBRTransportException means the read never reached the device, not that anything is broken. The SDK tears the I2C device down when an OpMode stops, so a read already in flight comes back empty. A polling loop should catch it and break.