diff --git a/main/README.md b/main/README.md index abe95d5..b61832a 100644 --- a/main/README.md +++ b/main/README.md @@ -50,13 +50,43 @@ Pins (`powerpod.h`): | UART TX | 3 | | UART RX | 2 | | LED ring | 7 | +| BMA456 INT | 10 | Startup order: 1. Read DIP + IO expander → `app_config` -2. `esp_now_comm_init(&app_config)` — WiFi + ESP-NOW -3. `led_ring_init()` -4. **Master only:** command queue, UART, registered commands (e.g. VERSION) +2. **I2C bus** — IO expander `0x20`; optional **BMA456H** (`init_bma456`, same bus) +3. `esp_now_comm_init(&app_config)` — WiFi + ESP-NOW +4. `led_ring_init()` +5. **Master only:** command queue, UART, registered commands (e.g. VERSION) + +## BMA456 accelerometer (`bosch456.c`) + +Powerpod uses the Bosch **BMA456H** (hearable) variant, not the generic `bma456w` examples in the vendor tree. + +| Item | Value | +|------|--------| +| Project wrapper | `main/bosch456.c`, `main/bosch456.h` | +| Vendor component | `components/bma456` — only `bma4.c` + `bma456h.c` are linked | +| I2C | Shared bus with IO expander (SCL/SDA GPIO 5/6), address **0x18**, **100 kHz** | +| Interrupt | **GPIO 10**, active high, tap events (single / double / triple) | +| Polling | FreeRTOS task `bma456_poll`, **10 Hz** accel read | + +**Boot:** `init_bma456(bus_handle)` runs on **master and slave** after the IO expander. If the sensor is missing or init fails, firmware logs `BMA456 init skipped` and continues (`bma456_is_ready() == false`). + +**Accel logging:** Samples are printed only when any axis changes by more than the **deadzone** (raw LSB) since the last logged sample (default **100**). This is a **software** filter on top of the sensor; it does not change BMA456 hardware thresholds. + +**Configuration paths:** + +| Path | Effect | +|------|--------| +| UART `ACCEL_DEADZONE` with `client_id = 0` | `bma456_set_accel_deadzone()` on the local node | +| ESP-NOW `SET_ACCEL_DEADZONE` | Same on a slave (no-op log path if sensor not installed) | +| `make gotool-deadzone-set DEADZONE=… CLIENT=0` | Host shortcut for local deadzone | + +**Logs:** `[BMA456] ACC X=… Y=… Z=…` when deadzone exceeded; `[BMA456] tap: single|double|triple` on interrupt. + +Regenerate nanopb only when changing protos; sensor code has no code generation step. ## ESP-NOW discovery @@ -177,7 +207,7 @@ Encoding: `uart_send_uart_message()` in `uart_proto.c`. ### ACCEL_DEADZONE command -Filters BMA456 logs: a new accel line is emitted only when any axis changes by more than `deadzone` raw LSB since the last reported sample (default **100**). +Sets the **software** deadzone used by `bosch456.c` when logging accel (see [BMA456 accelerometer](#bma456-accelerometer-bosch456c)). Default **100** LSB. **Request:** framed `06` + nanopb `UartMessage` with `accel_deadzone_request`: @@ -279,6 +309,7 @@ Target: ESP32-S3. Close serial monitor on the UART adapter port before running ` | `cmd_version.c/h` | VERSION handler | | `cmd_client_info.c/h` | CLIENT_INFO handler | | `client_registry.c/h` | Registered slave table | +| `bosch456.c/h` | BMA456H I2C driver, accel poll, tap INT, deadzone filter | | `led_ring.c/h` | LED digit display | | `proto/uart_messages.proto` | UART protocol schema | | `proto/esp_now_messages.proto` | ESP-NOW protocol schema | diff --git a/main/bosch456.c b/main/bosch456.c index 5c82fdf..81d72ae 100644 --- a/main/bosch456.c +++ b/main/bosch456.c @@ -1,134 +1,90 @@ +/** + * BMA456H integration for Powerpod (ESP-IDF I2C master + Bosch SensorAPI). + * + * Polls accelerometer at 10 Hz; tap events arrive on BMA456_INT_GPIO. + * Accel logging is filtered in software (deadzone); see ACCEL_DEADZONE UART command. + */ + #include "bosch456.h" #include "bma4.h" -#include "bma456h.h" #include "bma4_defs.h" +#include "bma456h.h" #include "driver/gpio.h" #include "driver/i2c_master.h" #include "esp_err.h" #include "esp_log.h" #include "freertos/idf_additions.h" -#include "hal/gpio_types.h" #include -#include -#include -#include +#include static const char *TAG = "[BMA456]"; -static i2c_master_dev_handle_t bma456_dev_handle; +#define BMA4_READ_WRITE_LEN UINT8_C(46) +#define BMA4_I2C_MAX_WRITE (1u + BMA4_READ_WRITE_LEN) + +#define SENSOR_POLL_MS 100 + +static i2c_master_dev_handle_t s_bma456_dev; static bool s_bma456_ready; -static struct bma4_dev bma456_struct; +static struct bma4_dev s_bma456; static uint32_t s_accel_deadzone = BMA456_DEFAULT_ACCEL_DEADZONE; static int16_t s_last_x; static int16_t s_last_y; static int16_t s_last_z; static bool s_have_last_sample; -volatile uint8_t interrupt_status = 0; -uint8_t int_line; -struct bma4_int_pin_config pin_config = {0}; -uint16_t int_status = 0; +static volatile bool s_int_pending; -#define BMA4_READ_WRITE_LEN UINT8_C(46) -#define BMA456W_INT_PIN 10 -#define BMA456W_INT_PIN2 9 +static esp_err_t check_bma4(const char *api_name, int8_t rslt); -static void interrupt_callback(void *) { - interrupt_status = 1; - // ESP_LOGI("INTERRUPT", "STEP DETECTED"); -} +/* Bosch SensorAPI platform hooks (intf_ptr → i2c_master_dev_handle_t *). */ -/******************************************************************************/ -/*! User interface functions */ - -/*! - * I2C read function map to ESP platform - */ BMA4_INTF_RET_TYPE bma4_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) { - if (bma456_dev_handle == NULL) { + if (s_bma456_dev == NULL) { return BMA4_E_COM_FAIL; } - esp_err_t err = i2c_master_transmit_receive(bma456_dev_handle, ®_addr, 1, + esp_err_t err = i2c_master_transmit_receive(s_bma456_dev, ®_addr, 1, reg_data, len, -1); return (err == ESP_OK) ? BMA4_OK : BMA4_E_COM_FAIL; - // return BMA4_OK; } -/*! - * I2C write function map to ESP platform - */ BMA4_INTF_RET_TYPE bma4_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) { - if (bma456_dev_handle == NULL) { + (void)intf_ptr; + if (s_bma456_dev == NULL || reg_data == NULL) { + return BMA4_E_COM_FAIL; + } + if (len > BMA4_READ_WRITE_LEN) { return BMA4_E_COM_FAIL; } - uint8_t *buffer = malloc(len + 1); - if (!buffer) - return BMA4_E_NULL_PTR; + uint8_t buffer[BMA4_I2C_MAX_WRITE]; buffer[0] = reg_addr; - - ESP_LOGI("I2CWrite", "Message Length: %d", len); - memcpy(&buffer[1], reg_data, len); - esp_err_t err = i2c_master_transmit(bma456_dev_handle, buffer, len + 1, -1); - free(buffer); - + esp_err_t err = + i2c_master_transmit(s_bma456_dev, buffer, (size_t)(len + 1), -1); return (err == ESP_OK) ? BMA4_OK : BMA4_E_COM_FAIL; - // return BMA4_OK; } -/*! - * Delay function map to ESP platform - */ void bma4_delay_us(uint32_t period, void *intf_ptr) { + (void)intf_ptr; uint32_t wait_ms = period / 1000; uint32_t wait_us = period % 1000; - if (wait_ms) { + if (wait_ms > 0) { vTaskDelay(pdMS_TO_TICKS(wait_ms)); } - ets_delay_us(wait_us); + if (wait_us > 0) { + ets_delay_us(wait_us); + } } -/*! - * @brief Prints the execution status of the APIs. - */ void bma4_error_codes_print_result(const char api_name[], int8_t rslt) { if (rslt == BMA4_OK) { return; } - - ESP_LOGI("BMA4_I2C", "%s\t", api_name); - - switch (rslt) { - case BMA4_E_NULL_PTR: - ESP_LOGI("BMA4_I2C", "Error [%d] : Null pointer\r\n", rslt); - break; - case BMA4_E_COM_FAIL: - ESP_LOGI("BMA4_I2C", "Error [%d] : Communication failure\r\n", rslt); - break; - case BMA4_E_CONFIG_STREAM_ERROR: - ESP_LOGI("BMA4_I2C", "Error [%d] : Invalid configuration stream\r\n", rslt); - break; - case BMA4_E_SELF_TEST_FAIL: - ESP_LOGI("BMA4_I2C", "Error [%d] : Self test failed\r\n", rslt); - break; - case BMA4_E_INVALID_SENSOR: - ESP_LOGI("BMA4_I2C", "Error [%d] : Device not found\r\n", rslt); - break; - case BMA4_E_OUT_OF_RANGE: - ESP_LOGI("BMA4_I2C", "Error [%d] : Out of Range\r\n", rslt); - break; - case BMA4_E_AVG_MODE_INVALID_CONF: - ESP_LOGI("BMA4_I2C", "Error [%d] : Invalid bandwidth/ODR combination\r\n", - rslt); - break; - default: - ESP_LOGI("BMA4_I2C", "Error [%d] : Unknown error code\r\n", rslt); - break; - } + ESP_LOGW(TAG, "%s failed: %d", api_name, (int)rslt); } static esp_err_t check_bma4(const char *api_name, int8_t rslt) { @@ -159,17 +115,14 @@ void bma456_set_accel_deadzone(uint32_t deadzone_lsb) { s_accel_deadzone = deadzone_lsb; s_have_last_sample = false; if (s_bma456_ready) { - ESP_LOGI(TAG, "accel deadzone applied: %lu LSB", (unsigned long)deadzone_lsb); + ESP_LOGI(TAG, "accel deadzone %lu LSB", (unsigned long)deadzone_lsb); } } uint32_t bma456_get_accel_deadzone(void) { return s_accel_deadzone; } void bma456_report_accel_if_changed(int16_t x, int16_t y, int16_t z) { - if (!s_bma456_ready) { - return; - } - if (!sample_exceeds_deadzone(x, y, z)) { + if (!s_bma456_ready || !sample_exceeds_deadzone(x, y, z)) { return; } @@ -182,165 +135,107 @@ void bma456_report_accel_if_changed(int16_t x, int16_t y, int16_t z) { (unsigned long)s_accel_deadzone); } -static void remove_bma456_device(void) { - if (bma456_dev_handle != NULL) { - i2c_master_bus_rm_device(bma456_dev_handle); - bma456_dev_handle = NULL; - } - s_bma456_ready = false; +static void IRAM_ATTR bma456_int_isr(void *arg) { + (void)arg; + s_int_pending = true; } -void read_sensor_task(void *params) { - int8_t ret; - struct bma4_accel sens_data = {0}; +static void handle_tap_interrupt(void) { + uint16_t int_status = 0; + int8_t ret = bma456h_read_int_status(&int_status, &s_bma456); + if (ret != BMA4_OK) { + bma4_error_codes_print_result("bma456h_read_int_status", ret); + return; + } + + struct bma456h_out_state tap_out = {0}; + ret = bma456h_output_state(&tap_out, &s_bma456); + if (ret != BMA4_OK) { + bma4_error_codes_print_result("bma456h_output_state", ret); + return; + } + + if (tap_out.single_tap) { + ESP_LOGI(TAG, "tap: single"); + } else if (tap_out.double_tap) { + ESP_LOGI(TAG, "tap: double"); + } else if (tap_out.triple_tap) { + ESP_LOGI(TAG, "tap: triple"); + } +} + +static void remove_bma456_device(void) { + if (s_bma456_ready) { + gpio_isr_handler_remove(BMA456_INT_GPIO); + } + if (s_bma456_dev != NULL) { + i2c_master_bus_rm_device(s_bma456_dev); + s_bma456_dev = NULL; + } + s_bma456_ready = false; + s_int_pending = false; +} + +static void read_sensor_task(void *param) { + (void)param; if (!s_bma456_ready) { vTaskDelete(NULL); return; } + struct bma4_accel sens_data = {0}; + while (1) { - ret = bma4_read_accel_xyz(&sens_data, &bma456_struct); + int8_t ret = bma4_read_accel_xyz(&sens_data, &s_bma456); if (ret == BMA4_OK) { bma456_report_accel_if_changed(sens_data.x, sens_data.y, sens_data.z); } else { bma4_error_codes_print_result("bma4_read_accel_xyz", ret); } - if (interrupt_status) { - ESP_LOGI("INTERRUPT", "Da war der Interrupt resetting"); - interrupt_status = 0; - ret = bma456h_read_int_status(&int_status, &bma456_struct); - bma4_error_codes_print_result("bma456w_step_counter_output status", ret); - - int8_t rslt; - struct bma456h_out_state tap_out = {0}; - - rslt = bma456h_output_state(&tap_out, &bma456_struct); - - if (BMA4_OK == rslt) { - /* Enters only if the obtained interrupt is single-tap */ - if (tap_out.single_tap) { - ESP_LOGI("INTERRUPT", "Single Tap interrupt occurred\n"); - } - /* Enters only if the obtained interrupt is double-tap */ - else if (tap_out.double_tap) { - ESP_LOGI("INTERRUPT", "Double Tap interrupt occurred\n"); - } - /* Enters only if the obtained interrupt is triple-tap */ - else if (tap_out.triple_tap) { - ESP_LOGI("INTERRUPT", "Triple Tap interrupt occurred\n"); - } - } + if (s_int_pending) { + s_int_pending = false; + handle_tap_interrupt(); } - // ESP_LOGI("i2c", "X:%d, Y%d, Z%d", sens_data.x, sens_data.y, sens_data.z); - vTaskDelay(pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(SENSOR_POLL_MS)); } } -esp_err_t init_bma456(i2c_master_bus_handle_t bus_handle) { - int8_t ret; +static esp_err_t configure_tap_interrupt(void) { esp_err_t err; - - s_bma456_ready = false; - bma456_dev_handle = NULL; - - if (bus_handle == NULL) { - return ESP_ERR_INVALID_ARG; - } - - i2c_device_config_t dev_cfg_bma456 = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = BMA456_ADDRESS, - .scl_speed_hz = 100000, - }; - - err = i2c_master_bus_add_device(bus_handle, &dev_cfg_bma456, &bma456_dev_handle); - if (err != ESP_OK) { - return err; - } - - bma456_struct.intf = BMA4_I2C_INTF; - bma456_struct.bus_read = bma4_i2c_read; - bma456_struct.bus_write = bma4_i2c_write; - bma456_struct.delay_us = bma4_delay_us; - bma456_struct.read_write_len = BMA4_READ_WRITE_LEN; - bma456_struct.intf_ptr = &bma456_dev_handle; - bma456_struct.chip_id = 0; - - ret = bma456h_init(&bma456_struct); - if (check_bma4("bma456h_init", ret) != ESP_OK) { - remove_bma456_device(); - return ESP_ERR_NOT_FOUND; - } - - ESP_LOGI(TAG, "chip id 0x%02x", bma456_struct.chip_id); - - ret = bma4_soft_reset(&bma456_struct); - if (check_bma4("bma4_soft_reset", ret) != ESP_OK) { - goto fail; - } - vTaskDelay(pdMS_TO_TICKS(20)); - - ret = bma4_set_advance_power_save(BMA4_DISABLE, &bma456_struct); - if (check_bma4("bma4_set_advance_power_save", ret) != ESP_OK) { - goto fail; - } - vTaskDelay(pdMS_TO_TICKS(10)); - - ret = bma456h_write_config_file(&bma456_struct); - if (check_bma4("bma456h_write_config_file", ret) != ESP_OK) { - goto fail; - } - - struct bma4_accel_config accel_config; - bma4_get_accel_config(&accel_config, &bma456_struct); - accel_config.range = BMA4_ACCEL_RANGE_2G; - ret = bma4_set_accel_config(&accel_config, &bma456_struct); - if (check_bma4("bma4_set_accel_config", ret) != ESP_OK) { - goto fail; - } - - ret = bma4_set_accel_enable(BMA4_ENABLE, &bma456_struct); - if (check_bma4("bma4_set_accel_enable", ret) != ESP_OK) { - goto fail; - } + int8_t ret; + const uint8_t int_line = BMA4_INTR2_MAP; struct bma456h_multitap_settings tap_settings = {0}; - ret = bma456h_tap_get_parameter(&tap_settings, &bma456_struct); + ret = bma456h_tap_get_parameter(&tap_settings, &s_bma456); if (check_bma4("bma456h_tap_get_parameter", ret) != ESP_OK) { - goto fail; + return ESP_FAIL; } tap_settings.tap_sens_thres = 0; - ret = bma456h_tap_set_parameter(&tap_settings, &bma456_struct); + ret = bma456h_tap_set_parameter(&tap_settings, &s_bma456); if (check_bma4("bma456h_tap_set_parameter", ret) != ESP_OK) { - goto fail; + return ESP_FAIL; } ret = bma456h_feature_enable( (BMA456H_SINGLE_TAP_EN | BMA456H_DOUBLE_TAP_EN | BMA456H_TRIPLE_TAP_EN), - BMA4_ENABLE, &bma456_struct); + BMA4_ENABLE, &s_bma456); if (check_bma4("bma456h_feature_enable", ret) != ESP_OK) { - goto fail; - } - - ret = bma456h_step_counter_set_watermark(1, &bma456_struct); - if (check_bma4("bma456h_step_counter_set_watermark", ret) != ESP_OK) { - goto fail; - } - - int_line = BMA4_INTR2_MAP; - - ret = bma4_get_int_pin_config(&pin_config, int_line, &bma456_struct); - if (check_bma4("bma4_get_int_pin_config", ret) != ESP_OK) { - goto fail; + return ESP_FAIL; } ret = bma456h_map_interrupt(int_line, BMA456H_TAP_OUT_INT, BMA4_ENABLE, - &bma456_struct); + &s_bma456); if (check_bma4("bma456h_map_interrupt", ret) != ESP_OK) { - goto fail; + return ESP_FAIL; + } + + struct bma4_int_pin_config pin_config = {0}; + ret = bma4_get_int_pin_config(&pin_config, int_line, &s_bma456); + if (check_bma4("bma4_get_int_pin_config", ret) != ESP_OK) { + return ESP_FAIL; } pin_config.edge_ctrl = BMA4_EDGE_TRIGGER; @@ -349,36 +244,113 @@ esp_err_t init_bma456(i2c_master_bus_handle_t bus_handle) { pin_config.od = BMA4_PUSH_PULL; pin_config.input_en = BMA4_INPUT_DISABLE; - ret = bma4_set_int_pin_config(&pin_config, int_line, &bma456_struct); + ret = bma4_set_int_pin_config(&pin_config, int_line, &s_bma456); if (check_bma4("bma4_set_int_pin_config", ret) != ESP_OK) { - goto fail; + return ESP_FAIL; } - gpio_reset_pin(BMA456W_INT_PIN); - gpio_set_direction(BMA456W_INT_PIN, GPIO_MODE_INPUT); - gpio_set_pull_mode(BMA456W_INT_PIN, GPIO_PULLDOWN_ENABLE); - gpio_set_intr_type(BMA456W_INT_PIN, GPIO_INTR_POSEDGE); - gpio_intr_enable(BMA456W_INT_PIN); + gpio_reset_pin(BMA456_INT_GPIO); + gpio_set_direction(BMA456_INT_GPIO, GPIO_MODE_INPUT); + gpio_set_pull_mode(BMA456_INT_GPIO, GPIO_PULLDOWN_ONLY); + gpio_set_intr_type(BMA456_INT_GPIO, GPIO_INTR_POSEDGE); err = gpio_install_isr_service(0); if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { - goto fail; + return err; } - err = gpio_isr_handler_add(BMA456W_INT_PIN, interrupt_callback, - (void *)BMA456W_INT_PIN); + err = gpio_isr_handler_add(BMA456_INT_GPIO, bma456_int_isr, NULL); if (err != ESP_OK) { + return err; + } + + return ESP_OK; +} + +esp_err_t init_bma456(i2c_master_bus_handle_t bus_handle) { + int8_t ret; + esp_err_t err; + + s_bma456_ready = false; + s_bma456_dev = NULL; + s_int_pending = false; + + if (bus_handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = BMA456_I2C_ADDR, + .scl_speed_hz = 100000, + }; + + err = i2c_master_bus_add_device(bus_handle, &dev_cfg, &s_bma456_dev); + if (err != ESP_OK) { + return err; + } + + s_bma456.intf = BMA4_I2C_INTF; + s_bma456.bus_read = bma4_i2c_read; + s_bma456.bus_write = bma4_i2c_write; + s_bma456.delay_us = bma4_delay_us; + s_bma456.read_write_len = BMA4_READ_WRITE_LEN; + s_bma456.intf_ptr = &s_bma456_dev; + s_bma456.chip_id = 0; + + ret = bma456h_init(&s_bma456); + if (check_bma4("bma456h_init", ret) != ESP_OK) { + remove_bma456_device(); + return ESP_ERR_NOT_FOUND; + } + + ESP_LOGI(TAG, "chip id 0x%02x", s_bma456.chip_id); + + ret = bma4_soft_reset(&s_bma456); + if (check_bma4("bma4_soft_reset", ret) != ESP_OK) { + goto fail; + } + vTaskDelay(pdMS_TO_TICKS(20)); + + ret = bma4_set_advance_power_save(BMA4_DISABLE, &s_bma456); + if (check_bma4("bma4_set_advance_power_save", ret) != ESP_OK) { + goto fail; + } + vTaskDelay(pdMS_TO_TICKS(10)); + + ret = bma456h_write_config_file(&s_bma456); + if (check_bma4("bma456h_write_config_file", ret) != ESP_OK) { goto fail; } - if (xTaskCreate(read_sensor_task, "READ_SENSOR", 4096, NULL, 1, NULL) != + struct bma4_accel_config accel_config = {0}; + ret = bma4_get_accel_config(&accel_config, &s_bma456); + if (check_bma4("bma4_get_accel_config", ret) != ESP_OK) { + goto fail; + } + accel_config.range = BMA4_ACCEL_RANGE_2G; + ret = bma4_set_accel_config(&accel_config, &s_bma456); + if (check_bma4("bma4_set_accel_config", ret) != ESP_OK) { + goto fail; + } + + ret = bma4_set_accel_enable(BMA4_ENABLE, &s_bma456); + if (check_bma4("bma4_set_accel_enable", ret) != ESP_OK) { + goto fail; + } + + if (configure_tap_interrupt() != ESP_OK) { + goto fail; + } + + if (xTaskCreate(read_sensor_task, "bma456_poll", 4096, NULL, 1, NULL) != pdPASS) { - gpio_isr_handler_remove(BMA456W_INT_PIN); goto fail; } s_bma456_ready = true; - ESP_LOGI(TAG, "initialized"); + ESP_LOGI(TAG, "ready (I2C 0x%02x, INT GPIO%d, poll %d ms)", BMA456_I2C_ADDR, + BMA456_INT_GPIO, SENSOR_POLL_MS); return ESP_OK; fail: diff --git a/main/bosch456.h b/main/bosch456.h index a05cbc6..5faf4af 100644 --- a/main/bosch456.h +++ b/main/bosch456.h @@ -1,17 +1,30 @@ #ifndef BOSCH456_H #define BOSCH456_H +/** + * Powerpod driver for Bosch BMA456H (hearable variant) on the shared I2C bus. + * + * Vendor API: components/bma456 (bma4.c + bma456h.c only). + * Implementation: bosch456.c + */ + #include "driver/i2c_types.h" #include "esp_err.h" -#define TOUCH_1 9 -#define TOUCH_2 8 +/** 7-bit I2C address (SDO low). */ +#define BMA456_I2C_ADDR 0x18 -#define BMA456_ADDRESS 0x18 +/** Sensor interrupt line → ESP32 GPIO (active high, rising edge). */ +#define BMA456_INT_GPIO 10 +/** Software filter: log accel only when |axis - last| > deadzone (raw LSB). */ #define BMA456_DEFAULT_ACCEL_DEADZONE 100u -/** Initialize BMA456 on the shared I2C bus. Returns ESP_OK or logs and skips sensor use. */ +/** + * Probe and configure the sensor on bus_handle (100 kHz device). + * On failure the device is removed and ESP_ERR_NOT_FOUND / ESP_FAIL is returned; + * firmware continues without a sensor (see bma456_is_ready()). + */ esp_err_t init_bma456(i2c_master_bus_handle_t bus_handle); bool bma456_is_ready(void); @@ -19,7 +32,7 @@ bool bma456_is_ready(void); void bma456_set_accel_deadzone(uint32_t deadzone_lsb); uint32_t bma456_get_accel_deadzone(void); -/** Log accel sample only when any axis changed more than deadzone since last report. */ +/** Log accel when any axis moved more than deadzone since last reported sample. */ void bma456_report_accel_if_changed(int16_t x, int16_t y, int16_t z); #endif