Platform Setup

How to get CRUMBS compiling and a first pair of devices talking on each platform. Peripherals run on Arduino (AVR and ESP32 are the tested cores); a controller runs on Arduino or on Linux over i2c-dev.

Arduino IDE

CRUMBS is not in the Library Manager index. Install it as a folder:

git clone https://github.com/feastorg/CRUMBS.git ~/Arduino/libraries/CRUMBS

or Sketch → Include Library → Add .ZIP Library… with a release archive. Restart the IDE; the sketches appear under File → Examples → CRUMBS.

Start with hello_peripheral on one board and hello_controller on another, wired as in Wiring. Both default to address 0x10 (config.h in each sketch); the controller’s serial monitor at 115200 baud shows the exchange.

With arduino-cli, in the form CI uses for the mixed-bus sketches:

arduino-cli compile --fqbn arduino:avr:nano --library "$PWD" examples/core_usage/arduino/hello_peripheral

To change CRUMBS_MAX_HANDLERS for an IDE sketch you must rebuild the library with the same value; a #define in the sketch is not enough (see architecture.md). PlatformIO makes this easy; the IDE does not.

PlatformIO

Depend on the registry package:

[env:nanoatmega328new]
platform = atmelavr
board = nanoatmega328new
framework = arduino
lib_deps = cameronbrooks11/CRUMBS@^0.14.0
build_flags = -DCRUMBS_MAX_HANDLERS=8   ; optional; applies to library and sketch alike

The registry owner is cameronbrooks11 (the publishing account), not the GitHub organisation. To build against a working copy instead, point lib_deps at it: lib_deps = symlink:///path/to/CRUMBS.

The shipped projects under examples/*/platformio/ and examples/families_usage/lhwit_family/ build for nanoatmega328new (default), nanoatmega328old and esp32dev:

pio run -d examples/core_usage/platformio/simple_peripheral -e nanoatmega328new -t upload
pio run -d examples/core_usage/platformio/simple_controller -e nanoatmega328new -t upload
pio device monitor            # monitor_speed = 115200 is set in the project

Their platformio.ini pins the registry version, so they build the published library, not the checkout they sit in.

Linux

The Linux HAL is controller-only and needs linux-wire 0.1.3 or newer.

linux-wire

Build from source on any architecture (the only prebuilt tarball is x86_64):

git clone --branch v0.1.3 https://github.com/feastorg/linux-wire.git
cmake -S linux-wire -B linux-wire/build -DCMAKE_BUILD_TYPE=Release
cmake --build linux-wire/build
sudo cmake --install linux-wire/build                  # to /usr/local

Use --prefix <dir> on the install to keep it local; a linux-wire build tree is not a usable prefix (it exports nothing until installed). linux-wire’s own cmake --preset flow needs ninja-build; the lines above work with the default Makefiles generator.

Build CRUMBS

cmake --preset linux                                   # add -DCMAKE_PREFIX_PATH=<prefix> if not /usr/local
cmake --build --preset linux
ctest --test-dir build-linux

The presets need CMake 3.21; the project itself needs 3.13, so on older CMake:

cmake -S . -B build-linux -DCRUMBS_ENABLE_LINUX_HAL=ON
cmake --build build-linux

Either way the six Linux example programs are in build-linux/. Without CRUMBS_ENABLE_LINUX_HAL=ON (the default preset) the library and tests build but no examples do.

Use CRUMBS from your own CMake project

cmake --install build-linux --prefix ~/crumbs-install
find_package(crumbs CONFIG REQUIRED)        # CMAKE_PREFIX_PATH=~/crumbs-install
target_link_libraries(app PRIVATE crumbs::crumbs)

Headers install to include/crumbs/; include them as <crumbs.h> and <crumbs_linux.h>. The installed package pulls linux-wire in through find_dependency, so the same prefix path (or a system install) must contain it.

The I²C bus

On a Raspberry Pi enable the interface (raspi-config → Interface Options → I2C) and use /dev/i2c-1. Elsewhere load i2c-dev (sudo modprobe i2c-dev) and find the bus with i2cdetect -l. Add your user to the i2c group rather than running as root.

i2cdetect -y 1 shows what ACKs; a CRUMBS peripheral shows up like any other device. Then:

build-linux/crumbs_simple_linux_controller /dev/i2c-1 0x10      # send a test frame, read the reply
build-linux/crumbs_simple_linux_controller scan                 # CRUMBS devices on /dev/i2c-1
build-linux/crumbs_simple_linux_controller scan strict          # read-only probe

Non-strict scanning writes an all-zero frame to addresses that do not answer a read; do not run it on a bus with an EEPROM at an unknown address (protocol.md).

Wiring

SDA to SDA, SCL to SCL, and a common ground; one pair of pull-ups per bus. Default Wire pins: Uno and Nano A4 (SDA) / A5 (SCL); Mega 20 / 21; ESP32 GPIO 21 / 22; Raspberry Pi GPIO 2 / 3 (header pins 3 / 5).

  • Arduino-only buses: 4.7 kΩ from SDA and SCL to the boards’ logic voltage. The AVR Wire core turns on the chip’s internal pull-ups, but those are tens of kΩ and only adequate for two boards on a few centimetres of wire.
  • A Raspberry Pi controller: the Pi already pulls both lines to 3.3 V through its onboard resistors; add nothing, and never pull the bus to 5 V.
  • Every device on one bus must sit at a distinct address. The examples use 0x10; the LHWIT family uses 0x100x40 in steps of 0x10; the address avoid-list is in protocol.md.

Troubleshooting

Symptom Check
Controller sends, peripheral silent Same address in both sketches; SDA/SCL not swapped; common ground; pull-ups present. i2cdetect (Linux) or crumbs_arduino_scan sees the peripheral?
crumbs_controller_read returns -1 Nothing decodable came back: the address did not answer, or the peripheral had nothing staged for the requested opcode — see protocol.md.
-2 (CRC) on most reads from a Pi The Pi’s I²C controller does not honour clock stretching; a peripheral whose interrupt is late returns 0xFFs. Keep handlers short; see protocol.md.
CRUMBS_MAX_HANDLERS mismatch at boot The value was set in the sketch, not as a build flag for the library too.
Could not find a package configuration file provided by "linux_wire" at configure Install linux-wire ≥ 0.1.3 (a build tree is not enough) or pass its install prefix in CMAKE_PREFIX_PATH.
crumbs_linux_scan returns -2 The adapter cannot do an SMBus Quick Write; use strict mode.
lw_open_bus: open: Permission denied Add yourself to the i2c group and log in again.