Install the library#
The Arduino library drives the whole board — encoders, colour, distance, digital outputs, IMU and the localizer — over Wire. It depends on nothing but Wire, does not allocate, and does not use exceptions, so it runs on an Uno as well as it runs on an ESP32.
Get it#
Arduino IDE — Sketch → Include Library → Add .ZIP Library, and pick the downloaded archive. Or copy the library folder into ~/Documents/Arduino/libraries/BBRDigitalExpander/ by hand.
PlatformIO — add it to platformio.ini:
lib_deps = https://github.com/BuildingBlockRobotics/DigitalExpander-Arduino.git
Do not edit BBRRegMap.h. It is generated from the register map specification, and any change you make will be overwritten the next time it is regenerated.
Wire it up#
| Expander | Your board |
|---|---|
| SDA | SDA |
| SCL | SCL |
| GND | GND |
| Power | 3.3 V, about 55 mA |
Two things a Control Hub does for the board that your Arduino does not, so you have to. Both are covered in full on Wiring it up; the short version is:
Fit your own bus pull-ups. The Expander deliberately carries none on the host-facing bus — a Control Hub provides 2.49 kΩ, and doubling up would only raise sink current. On any other host there are no pull-ups at all unless you fit them: 2.2 kΩ to 4.7 kΩ from SDA and SCL to 3.3 V. Your microcontroller’s weak internal pull-ups are not a substitute at 400 kHz.
Check your board’s logic level. The Expander’s I2C lines are 3.3 V and are not 5 V tolerant. A 5 V Arduino — Uno, Nano, Mega, Leonardo — needs a level shifter on SDA and SCL, with the pull-ups on the 3.3 V side. A 3.3 V board (ESP32, RP2040, SAMD, STM32, Teensy 3.x and later) connects directly.
The board is bus-powered and has no regulator of its own, so it needs a clean 3.3 V supply — not 5 V, and not a 3.3 V rail that can only spare a few milliamps. An Uno’s onboard 3.3 V pin is marginal for this; power the board from a separate 3.3 V regulator if the sensors misbehave under load.
Address#
The board answers at 7-bit address 0x38 by default, and the address jumpers move it to 0x39, 0x3A or 0x3B. That is how you put more than one Expander on the same bus:
BBRDigitalExpander first; // 0x38
BBRDigitalExpander second(0x39); // jumpered
If your board has more than one I2C bus, pass it as the second argument:
BBRDigitalExpander expander(BBR_I2C_ADDR_DEFAULT, Wire1);
Start it#
#include <BBRDigitalExpander.h>
#include <Wire.h>
BBRDigitalExpander expander;
void setup() {
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000); // 100000 works too
if (!expander.begin()) {
Serial.println(expander.lastErrorText());
while (true) { delay(1000); }
}
}
begin() reads the board’s identity block and checks three things: that the device ID is really an Expander, that the protocol version is one the library speaks, and that the hardware variant is one it recognises. Any of those failing returns false rather than carrying on — a clear stop at setup beats corrupt data an hour later.
Stopping the sketch on that failure, as above, is worth doing. A library that could not start will answer every later call with a failure too, and a loop that ignores them prints plausible-looking zeros forever.
Check it before writing anything else#
Run the DeviceInfo example. It prints the firmware version, the hardware variant, the capability bits, the status flags and what is plugged into each sensor port. If that report appears, your wiring, your pull-ups, your logic levels and your address jumpers are all correct, and everything else on this site will work.
If it does not appear, fix that first — see Troubleshooting.