-
Notifications
You must be signed in to change notification settings - Fork 3
I2CBus
Raft's I2C bus support is provided by the RaftI2C library. When a bus of type "I2C" is declared in the DevMan configuration, Raft creates a BusI2C instance that manages the complete lifecycle of I2C devices on that bus:
- Automatic device detection through priority-based scanning, including devices behind bus multiplexers
- Device type identification using WHO_AM_I registers and configurable detection sequences
- Device initialization using register-write sequences defined per device type
- Continuous polling of identified devices at configurable intervals
-
Data publishing via the
devjsonanddevbintopics - Bus health management including stuck-bus detection and recovery, and device hot-swapping
The bus runs its own dedicated FreeRTOS task so that scanning and polling activity does not block the main application loop.
The I2C hardware driver is selected automatically based on the target chip:
| Chip | Driver used |
|---|---|
| ESP32, ESP32-S3, ESP32-C3, … |
RaftI2CCentral (Raft native driver) |
| ESP32-C6 |
RaftI2CCentral_ESPIDF (ESP-IDF v5 driver) |
The selection can be overridden at build time by defining I2C_USE_RAFT_I2C or I2C_USE_ESP_IDF_5.
I2C buses are declared inside the Buses array of the DevMan SysType configuration. The type field must be "I2C". All other fields in the bus object are I2C-specific.
{
"DevMan": {
"Buses": [
{
"name": "I2CA",
"type": "I2C",
"sdaPin": "SDA",
"sclPin": "SCL",
"i2cFreq": 400000
}
]
}
}| Parameter | Type | Default | Description |
|---|---|---|---|
name |
string | "" |
Bus name used to identify this bus in REST API calls (e.g. "I2CA"). |
sdaPin |
string | — | SDA pin name (looked up via ConfigPinMap). Required. |
sclPin |
string | — | SCL pin name (looked up via ConfigPinMap). Required. |
i2cPort |
int | 0 |
ESP32 I2C hardware port number (0 or 1). |
i2cFreq |
int | 100000 |
I2C bus clock frequency in Hz. Common values: 100000 (standard), 400000 (fast), 1000000 (fast-plus). |
i2cFilter |
int | driver default | Glitch filter level for the I2C bus (passed directly to the I2C driver). |
The bus runs in a dedicated FreeRTOS task. These parameters control its scheduling:
| Parameter | Type | Default | Description |
|---|---|---|---|
taskCore |
int | 1 | CPU core to pin the task to (0 or 1). |
taskPriority |
int | driver default | FreeRTOS task priority. |
taskStack |
int | driver default | Task stack size in bytes. |
The I2C task yields periodically to allow other tasks to run. The unyield budgets control how long scanning is allowed to run before yielding again:
| Parameter | Type | Default | Description |
|---|---|---|---|
loopYieldMs |
int | driver default | Milliseconds the task yields to other tasks each cycle via vTaskDelay. |
fastScanMaxUnyieldMs |
int | driver default | Maximum milliseconds spent on fast scanning before yielding (internally converted to microseconds). |
slowScanMaxUnyieldMs |
int | driver default | Maximum milliseconds spent on slow scanning before yielding (internally converted to microseconds). |
These parameters control how the bus is scanned for devices. They are read directly from the bus configuration object (no prefix):
| Parameter | Type | Default | Description |
|---|---|---|---|
busScanPeriodMs |
int | ~20000 | Period of the slow background scan in milliseconds. |
scanBoost |
array of strings | [] |
I2C addresses to promote to the highest scan priority (hex strings, e.g. "0x6a"). These are scanned more frequently and detected faster. |
Multiplexer support (e.g. TCA9548A, PCA9548A) is configured under the mux key:
{
"mux": {
"enable": true,
"minAddr": "0x70",
"maxAddr": "0x77",
"rstPin": 5,
"clearCascadeMux": false
}
}| Parameter | Type | Default | Description |
|---|---|---|---|
enable |
bool | false |
Enable multiplexer support. |
minAddr |
string | "0x70" |
Lowest I2C address to probe for multiplexers. |
maxAddr |
string | "0x77" |
Highest I2C address to probe for multiplexers. |
rstPin |
int | -1 |
GPIO pin connected to the multiplexer hardware reset line. -1 = not used. |
clearCascadeMux |
bool | false |
Clear cascaded multiplexer slots when a multiplexer is detected. |
Devices behind multiplexers are addressed using a slot number. See I2C Device Scanning for slot numbering details.
IO expanders connected to the I2C bus (used for bus power switching) are configured under the ioExps key. Refer to the IO expander documentation for specific fields.
An optional power controller allows Raft to power-cycle individual multiplexer slots for stuck-bus recovery. It is only instantiated if the pwr key is present as a JSON object:
{
"pwr": {
...
}
}When present, the power controller setup is delegated to BusPowerController. Refer to the power controller documentation for specific fields.
The following example configures an I2C bus with a 400 kHz clock, a TCA9548A multiplexer, scan boost for two known device addresses, and a 30-second slow scan period:
{
"DevMan": {
"Buses": [
{
"name": "I2CA",
"type": "I2C",
"sdaPin": "SDA",
"sclPin": "SCL",
"i2cPort": 0,
"i2cFreq": 400000,
"taskCore": 1,
"busScanPeriodMs": 30000,
"scanBoost": ["0x6a", "0x36"],
"mux": {
"enable": true,
"minAddr": "0x70",
"maxAddr": "0x77",
"rstPin": 5
}
}
]
}
}The bus runs a background FreeRTOS task (I2CTask) that performs the following work each cycle, in order:
- Yield for
loopYieldMsto allow other tasks to run - Skip remaining work if a hiatus (deliberate pause) is active
- Bus scanning — if a scan is pending, service the scanner within the configured time budget
- Request queue — process any queued raw bus requests (from REST API calls etc.)
- Bus multiplexers — update multiplexer slot state
- Bus power controller — service power switching logic
- IO expanders — flush any pending output-state changes
- Device polling — poll all identified devices that are due
- Stuck-bus handler — check for and attempt recovery from stuck-bus conditions
The bus can be paused and resumed (e.g. during firmware update). While paused, scanning is suspended and polling is skipped, but queued requests are still processed.
Individual device addresses can be temporarily barred from access for a specified period (in milliseconds). This is used internally after commands that require a device to be left alone while processing (e.g. a soft reset). Barred addresses are skipped by both the scanner and the poller until the bar expires.
- I2C Device Scanning — priority-based scanning, multiplexer slot handling, scan modes, hot-swap, and stuck-bus recovery
- I2C Device Identification and Polling — device type detection, initialization sequences, polling configuration, and data decoding
-
Device Data Publishing —
devjsonanddevbinmessage formats and subscription - DeviceManager SysMod — DeviceManager features, device lifecycle, and REST API overview
-
DeviceManager Settings —
BusesandDevicesconfiguration reference - DeviceManager REST API — REST endpoints for raw commands, device config, and type info