Wireless/Bluetooth
[ble]
To enable BLE, add enabled = true under the [ble] section.
Host connection PHY
[ble].use_2m_phy requests 2M (true, default) or 1M (false) for host connections on all supported BLE chips.
To request 1M:
The use_1m_phy Cargo feature overrides this setting to request 1M. Dongle and split links always request 2M.
Passkey entry
RMK supports typing a BLE passkey directly on the keyboard during pairing. This is disabled by default, and requires the passkey_entry Cargo feature of the rmk crate in addition to the configuration below.
During passkey mode, the keyboard intercepts all keypresses. Only the following keys are recognized:
All other keys are silently discarded while passkey mode is active.
Battery configuration
Battery configuration controls voltage measurement, charging-state detection, and an optional indicator LED. These features also work with BLE disabled.
Choose the table for the board you are configuring:
Configure each split board separately. Use only the split battery tables for a split keyboard; the top-level [battery] table is not accepted.
Battery fields
All three tables accept the same fields. Omit inputs and outputs that your board does not have.
For unibody keyboards, omitted fields use the board preset; an empty [battery] table keeps those defaults.
For split keyboards, an omitted side table uses the board preset. An explicit table replaces it entirely; an empty table disables that side's battery inputs.
Set both divider values in the same units. For example, a divider with 806 kΩ between the battery and ADC input and 2 MΩ between the input and ground uses 2000 and 2806. Both values must be greater than zero. With battery_adc_pin = "vddh", RMK uses the internal 1:5 divider and ignores these two fields.
On nRF52 chips with an ADC, RMK sets up voltage measurement automatically. The examples below use nRF52840 pins; replace them and the divider values to match your board.
With only charge_state configured, RMK reports charging state without a battery percentage. The indicator LED stays on while charging, blinks below 10% when not charging, and stays off otherwise.
Unibody keyboard
Add [battery] to keyboard.toml. This example measures voltage through an external divider and reads a charging-status pin:
Split battery ADC configuration
Add a battery table to override the preset for that side. Place each [split.peripheral.battery] table after the corresponding [[split.peripheral]] entry and before the next peripheral entry. Keep each board's existing matrix and connection settings.
For an existing configuration with battery fields under [ble] or directly under a split board, see Migrate battery configuration.
RP2040 battery input
Set battery_adc_pin to an ADC-capable pin, such as PIN_26, and set the divider values to match your board. RP2040 voltage measurement assumes a 3.3 V ADC reference.
For a unibody board with a 1:2 divider:
For a split board, put these fields in its central or peripheral battery table. RMK waits 30 seconds before each sample, including the first. If a read fails, it keeps the previous reading and retries at the next sampling interval. Boards with a different ADC reference need a custom Rust reader that publishes ADC input millivolts.
ESP32 battery input
Set battery_adc_pin to an ADC1-capable GPIO for your chip and set the divider values to match your board. RMK uses calibrated voltage readings and waits 30 seconds before each sample, including the first.
For an ESP32-C3 unibody board with a 1:2 divider:
For a split board, put these fields in its central or peripheral battery table. GPIO numbering and ADC support vary by chip; the pin in this example is for ESP32-C3.
Battery measurement reserves ADC1. This configuration requires RMK's ESP32 BLE initialization, which enables the radio before using the hardware random-number generator.
Peripheral battery reporting over BLE GATT
When peripherals are configured to sample their batteries (see above), their levels are forwarded to the central over the split BLE links and re-exposed to the host through standard Battery Service instances (UUID 0x180F) on the central's GATT server. The host sees one Battery Service instance for:
- the central's own battery level, and
- each peripheral with
battery_adc_pinset by its own table or the board preset.
Set battery_user_description in each board's battery table to give its battery a name such as "Left" or "Right". The host determines whether these names and separate battery levels appear in its interface.
The split feature uses trouble-host's default client ATT table size. To reserve more space for client-specific attributes such as CCCDs, set TROUBLE_HOST_CLIENT_ATT_TABLE_SIZE in the project environment, for example in .cargo/config.toml:
This project-wide override takes precedence over trouble-host Cargo feature settings and can be set to the size required by the enabled services.