Platform Setup

This guide covers installation, configuration, and first-run setup for CRUMBS on all supported platforms: Arduino, PlatformIO, and Linux.

Quick Start

Platform: PlatformIO (recommended), Arduino IDE (simple projects), or Linux (Raspberry Pi/PC)

Hardware: 4.7kΞ© pull-ups on SDA/SCL, common ground. Level shifter for 5V↔3.3V.


Arduino Setup

Installation

  1. Open Arduino IDE
  2. Go to Sketch β†’ Include Library β†’ Manage Libraries
  3. Search for β€œCRUMBS”
  4. Click Install

Method 2: Manual Installation

  1. Download or clone the CRUMBS repository
  2. Place the CRUMBS folder in your Arduino libraries directory
    • Windows: Documents\Arduino\libraries\
    • macOS: ~/Documents/Arduino/libraries/
    • Linux: ~/Arduino/libraries/
  3. Restart Arduino IDE

First Program (Peripheral)

Create a new sketch:

#include <crumbs_arduino.h>

#define I2C_ADDRESS 0x08

crumbs_context_t ctx;

void on_message(crumbs_context_t *ctx, const crumbs_message_t *msg) {
    if (msg->data_len >= 1) {
        digitalWrite(LED_BUILTIN, msg->data[0] ? HIGH : LOW);
    }
}

void on_request(crumbs_context_t *ctx, crumbs_message_t *reply) {
    reply->type_id = 1;
    reply->opcode = 0;
    reply->data_len = 1;
    reply->data[0] = digitalRead(LED_BUILTIN);
}

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    crumbs_arduino_init_peripheral(&ctx, I2C_ADDRESS);
    crumbs_set_callbacks(&ctx, on_message, on_request, NULL);
}

void loop() {
    // Wire callbacks handle everything
}

Upload: Select board/port, upload, wire IΒ²C + GND + pull-ups.

Always delay 10ms between send/read:

crumbs_controller_send(&ctx, 0x08, &msg, crumbs_arduino_wire_write, NULL);
delay(10);
crumbs_arduino_read(NULL, 0x08, buf, sizeof(buf), 5000);

First Program (Controller)

#include <crumbs_arduino.h>
#include <crumbs_message_helpers.h>

crumbs_context_t ctx;

void setup() {
    Serial.begin(9600);
    crumbs_arduino_init_controller(&ctx);

    // Send LED ON command to peripheral at 0x08
    crumbs_message_t msg;
    crumbs_msg_init(&msg, 0x01, 0x01);  // type=1, opcode=1
    crumbs_msg_add_u8(&msg, 1);         // payload: LED ON

    int rc = crumbs_controller_send(&ctx, 0x08, &msg,
                                    crumbs_arduino_wire_write, NULL);

    Serial.print("Send result: ");
    Serial.println(rc);  // 0 = success
}

void loop() {
    delay(1000);
}

Troubleshooting (Arduino)

Issue Solution
Compile error: β€œcrumbs.h not found” Verify library in libraries/ folder, restart IDE
No response from peripheral Check wiring, verify addresses, measure 3.3V on SDA/SCL with pull-ups
Data corruption Add Wire.setClock(100000) to slow clock, add delays between messages
Multiple definitions error Include CRUMBS headers in only one file, or use header guards

Hardware Notes

IΒ²C pins by board

  • Arduino Uno/Nano: A4 (SDA), A5 (SCL)
  • Arduino Mega: 20 (SDA), 21 (SCL)
  • Arduino Due: 20 (SDA), 21 (SCL) β€” 3.3V logic
  • ESP32: GPIO 21 (SDA), GPIO 22 (SCL) β€” configurable
  • ESP8266: GPIO 4 (SDA), GPIO 5 (SCL)

Pull-up resistors

  • Required on SDA and SCL lines
  • Typical value: 4.7kΞ© to Vcc (3.3V or 5V depending on board)
  • Many boards have built-in pull-ups (may need external ones for longer wires)

PlatformIO Setup

Installation (PlatformIO)

PlatformIO can automatically fetch CRUMBS as a library dependency.

Example platformio.ini:

[env:uno]
platform = atmelavr
board = uno
framework = arduino

lib_deps =
    CRUMBS

build_flags =
    -DCRUMBS_MAX_HANDLERS=8  # Optional: reduce handler table size

To install and build:

pio lib install
pio run

First Program

Create src/main.cpp with the same Arduino code shown above. PlatformIO will automatically:

  • Download CRUMBS library
  • Compile with correct build flags
  • Link everything together

Advanced Configuration

To adjust handler memory usage:

build_flags =
    -DCRUMBS_MAX_HANDLERS=4  # Reduce from default 16

For multiple environments:

[env:controller]
board = uno
build_flags =
    -DROLE_CONTROLLER

[env:peripheral]
board = nano
build_flags =
    -DROLE_PERIPHERAL
    -DI2C_ADDRESS=0x08

Troubleshooting (PlatformIO)

Issue Solution
Library not found Run pio lib install, check internet connection
Handler table full Set -DCRUMBS_MAX_HANDLERS=<smaller number>
ABI mismatch error Ensure CRUMBS_MAX_HANDLERS set in build_flags, not in code
Upload fails Check USB port permissions, verify board selection

Linux Setup

Note: Linux HAL supports controller mode only. Peripheral mode (IΒ²C target) is not implemented. For peripheral devices, use Arduino or other microcontroller.

Prerequisites

# Ubuntu/Debian
sudo apt-get install build-essential cmake git

# Raspberry Pi OS
sudo apt-get install cmake git

# Fedora/RHEL
sudo dnf install cmake gcc git

Install linux-wire Dependency

CRUMBS Linux HAL requires the linux-wire library for IΒ²C bus access.

# Clone linux-wire
git clone https://github.com/FEASTorg/linux-wire.git
cd linux-wire

# Build and install
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
sudo cmake --install build --prefix /usr/local

To verify installation:

cmake --find-package -DNAME=linux_wire -DCOMPILER_ID=GNU \
      -DLANGUAGE=C -DMODE=EXIST
# Should print: "linux_wire found."

Local build (development)

For development without system install:

# Build linux-wire locally
cd linux-wire
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel

# Point CRUMBS at local build
cd ../CRUMBS
cmake -S . -B build -DCRUMBS_ENABLE_LINUX_HAL=ON \
      -DCMAKE_PREFIX_PATH=$HOME/linux-wire/build
cmake --build build --parallel

Install CRUMBS

# Clone CRUMBS
git clone https://github.com/FEASTorg/CRUMBS.git
cd CRUMBS

# Configure with Linux HAL
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
      -DCRUMBS_ENABLE_LINUX_HAL=ON \
      -DCRUMBS_BUILD_EXAMPLES=ON

# Build
cmake --build build --parallel

# Optional: System-wide install
sudo cmake --install build --prefix /usr/local

IΒ²C Device Permissions

Linux IΒ²C devices (/dev/i2c-*) typically require root access or group membership.

Option 1: Add user to i2c group

sudo usermod -a -G i2c $USER
# Log out and back in for changes to take effect

Option 2: Use sudo

sudo ./build/crumbs_simple_linux_controller

Option 3: udev rule (advanced)

Create /etc/udev/rules.d/99-i2c.rules:

KERNEL=="i2c-[0-9]*", GROUP="i2c", MODE="0660"

Then reload rules:

sudo udevadm control --reload-rules
sudo udevadm trigger

Enable IΒ²C on Raspberry Pi

# Enable IΒ²C interface
sudo raspi-config
# Navigate to: Interfacing Options β†’ I2C β†’ Enable

# Verify IΒ²C device exists
ls -l /dev/i2c-*
# Should show /dev/i2c-1 (or /dev/i2c-0 on older models)

# Load kernel module (if needed)
sudo modprobe i2c-dev

First Program (Linux Controller)

The example programs are built automatically when CRUMBS_BUILD_EXAMPLES=ON.

Run simple controller:

sudo ./build/crumbs_simple_linux_controller /dev/i2c-1 0x08

Scan for CRUMBS devices:

# Non-strict mode (attempt reads, send probe if needed)
sudo ./build/crumbs_simple_linux_controller scan

# Strict mode (read-only checks, safer for sensitive devices)
sudo ./build/crumbs_simple_linux_controller scan strict

Write Your Own Linux Controller

Example CMake project structure:

my_project/
β”œβ”€β”€ CMakeLists.txt
└── src/
    └── main.c

CMakeLists.txt:

cmake_minimum_required(VERSION 3.13)
project(my_controller C)

find_package(crumbs CONFIG REQUIRED)

add_executable(my_controller src/main.c)
target_link_libraries(my_controller PRIVATE crumbs::crumbs)

src/main.c:

#include "crumbs.h"
#include "crumbs_linux.h"
#include "crumbs_message_helpers.h"
#include <stdio.h>

int main() {
    crumbs_context_t ctx;
    crumbs_linux_i2c_t bus;

    // Open IΒ²C bus
    int rc = crumbs_linux_init_controller(&ctx, &bus, "/dev/i2c-1", 10000);
    if (rc != 0) {
        fprintf(stderr, "Failed to open I2C bus: %d\n", rc);
        return 1;
    }

    // Send message
    crumbs_message_t msg;
    crumbs_msg_init(&msg, 0x01, 0x01);
    crumbs_msg_add_u8(&msg, 1);  // LED ON

    rc = crumbs_controller_send(&ctx, 0x08, &msg,
                                crumbs_linux_i2c_write, &bus);

    printf("Send result: %d\n", rc);

    crumbs_linux_close(&bus);
    return 0;
}

Build:

cmake -S . -B build
cmake --build build
./build/my_controller

Troubleshooting (Linux)

Issue Solution
linux_wire not found Install linux-wire (see above), or use -DCMAKE_PREFIX_PATH
/dev/i2c-1 not found Enable IΒ²C in raspi-config, load i2c-dev module
Permission denied Add user to i2c group or use sudo
i2c-dev module not loaded Run sudo modprobe i2c-dev, add to /etc/modules for boot
Link errors Verify crumbs::crumbs target linked in CMake
Wrong IΒ²C bus Use i2cdetect -l to list buses, adjust device path

Hardware Wiring

Standard IΒ²C Connection

Controller          Peripheral
---------          ----------
    SDA  ───────────  SDA
    SCL  ───────────  SCL
    GND  ───────────  GND
     |                 |
     β”œβ”€β”€ 4.7kΞ© ── Vcc  (pull-up)
     └── 4.7kΞ© ── Vcc  (pull-up)

Multiple Peripherals

Controller          Peripheral 1 (0x08)    Peripheral 2 (0x09)
---------          ------------------      ------------------
    SDA  ────┬──────  SDA                      SDA
             β”‚
    SCL  ────┼──┬───  SCL                      SCL
             β”‚  β”‚
    GND  ────┼──┼───  GND                      GND
             β”‚  β”‚
       4.7kΞ© β”‚  └── 4.7kΞ© to Vcc
             β”‚
             └────── Vcc (3.3V or 5V)

Important:

  • All devices must share a common ground
  • Only one set of pull-up resistors needed per bus
  • Use 3.3V logic if any device is 3.3V-only
  • Maximum bus length: ~1 meter (longer requires lower pull-up resistance)

Verification and Testing

IΒ²C Bus Scanner (Arduino)

Use the built-in Wire scanner to verify devices are visible:

#include <Wire.h>

void setup() {
    Serial.begin(9600);
    Wire.begin();

    Serial.println("Scanning I2C bus...");
    for (uint8_t addr = 0x08; addr < 0x78; addr++) {
        Wire.beginTransmission(addr);
        if (Wire.endTransmission() == 0) {
            Serial.print("Found device at 0x");
            Serial.println(addr, HEX);
        }
    }
}

void loop() {}

CRUMBS Device Scanner (Arduino)

Verify devices speak CRUMBS protocol:

#include <crumbs_arduino.h>

crumbs_context_t ctx;

void setup() {
    Serial.begin(9600);
    crumbs_arduino_init_controller(&ctx);

    uint8_t found[32];
    int count = crumbs_controller_scan_for_crumbs(
        &ctx, 0x08, 0x77, 1,  // strict mode
        crumbs_arduino_wire_write, crumbs_arduino_read, NULL,
        found, 32, 50000);

    Serial.print("Found ");
    Serial.print(count);
    Serial.println(" CRUMBS devices:");

    for (int i = 0; i < count; i++) {
        Serial.print("  0x");
        Serial.println(found[i], HEX);
    }
}

void loop() {}

IΒ²C Bus Scanner (Linux)

# List IΒ²C buses
i2cdetect -l

# Scan bus 1 for devices
i2cdetect -y 1

CRUMBS Device Scanner (Linux)

# Non-strict mode
sudo ./build/crumbs_simple_linux_controller scan

# Strict mode (safer, read-only)
sudo ./build/crumbs_simple_linux_controller scan strict

Next Steps

Once your platform is set up and basic communication is working:

  1. Work through examples β€” Progressive tutorials in examples/core_usage/
    • Start with hello_peripheral/ (Arduino)
    • Or simple_controller/ (Linux)
  2. Learn handler dispatch β€” Replace switch statements with per-command handlers
  3. Use message helpers β€” Type-safe payload builders
  4. Create command headers β€” Reusable command definitions
    • See examples/handlers_usage/mock_ops.h
  5. Optimize memory β€” Reduce handler table size for constrained devices
    • Set CRUMBS_MAX_HANDLERS via build flags

See Also