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
Method 1: Library Manager (recommended)
- Open Arduino IDE
- Go to Sketch β Include Library β Manage Libraries
- Search for βCRUMBSβ
- Click Install
Method 2: Manual Installation
- Download or clone the CRUMBS repository
- Place the
CRUMBSfolder in your Arduinolibrariesdirectory- Windows:
Documents\Arduino\libraries\ - macOS:
~/Documents/Arduino/libraries/ - Linux:
~/Arduino/libraries/
- Windows:
- 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.
System-wide installation (recommended)
# 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:
- Work through examples β Progressive tutorials in
examples/core_usage/- Start with
hello_peripheral/(Arduino) - Or
simple_controller/(Linux)
- Start with
- Learn handler dispatch β Replace switch statements with per-command handlers
- See
examples/handlers_usage/ - Read API Reference: Handler Dispatch
- See
- Use message helpers β Type-safe payload builders
- Include
crumbs_message_helpers.h - See API Reference: Message Helpers
- Include
- Create command headers β Reusable command definitions
- See
examples/handlers_usage/mock_ops.h
- See
- Optimize memory β Reduce handler table size for constrained devices
- Set
CRUMBS_MAX_HANDLERSvia build flags
- Set
See Also
- API Reference β Complete function documentation
- Protocol Specification β Wire format and versioning
- Examples β Working code for all platforms
- Architecture β Design decisions and internals