From 05fb2f211fcb44464d7872946648173381e36dfd Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 21 Apr 2026 12:03:43 +0200 Subject: [PATCH] Added BMA456 Support --- components/bma456 | 1 + main/CMakeLists.txt | 2 +- main/bosch456.c | 259 ++++++++++++++++++++++++++++++++++++++++++++ main/bosch456.h | 8 ++ main/hw_test.c | 9 +- 5 files changed, 274 insertions(+), 5 deletions(-) create mode 160000 components/bma456 create mode 100644 main/bosch456.c create mode 100644 main/bosch456.h diff --git a/components/bma456 b/components/bma456 new file mode 160000 index 0000000..e3122bc --- /dev/null +++ b/components/bma456 @@ -0,0 +1 @@ +Subproject commit e3122bc6db442d153928ed82956b2750cc16845f diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 7905d58..6d3621f 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "hw_test.c" +idf_component_register(SRCS "hw_test.c" "bosch456.c" INCLUDE_DIRS ".") diff --git a/main/bosch456.c b/main/bosch456.c new file mode 100644 index 0000000..91f18c4 --- /dev/null +++ b/main/bosch456.c @@ -0,0 +1,259 @@ +#include "bosch456.h" +#include "bma4.h" +#include "bma456h.h" +#include "bma4_defs.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 + +static i2c_master_dev_handle_t bma456_dev_handle; +static struct bma4_dev bma456_struct; + +volatile uint8_t interrupt_status = 0; +uint8_t int_line; +struct bma4_int_pin_config pin_config = {0}; +uint16_t int_status = 0; + +#define BMA4_READ_WRITE_LEN UINT8_C(46) +#define BMA456W_INT_PIN 10 +#define BMA456W_INT_PIN2 9 + +static void interrupt_callback(void *) { + interrupt_status = 1; + //ESP_LOGI("INTERRUPT", "STEP DETECTED"); +} + +/******************************************************************************/ +/*! 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) { + // ESP_ERROR_CHECK(i2c_master_receive(bma456_dev_handle, reg_data, len, -1)); + esp_err_t err = i2c_master_transmit_receive(bma456_dev_handle, ®_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) { + // ESP_ERROR_CHECK(i2c_master_transmit(bma456_dev_handle, reg_data, len, -1)); + // Bei Bosch muss zuerst das Register, dann die Daten in einem Transfer + // gesendet werden + uint8_t *buffer = malloc(len + 1); + if (!buffer) + return BMA4_E_NULL_PTR; + + 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); + + 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) { + uint32_t wait_ms = period / 1000; + uint32_t wait_us = period % 1000; + if (wait_ms) { + vTaskDelay(pdMS_TO_TICKS(wait_ms)); + } + 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) { + ESP_LOGI("BMA4_I2C", "%s\t", api_name); + if (rslt == BMA4_E_NULL_PTR) { + ESP_LOGI("BMA4_I2C", "Error [%d] : Null pointer\r\n", rslt); + } else if (rslt == BMA4_E_COM_FAIL) { + ESP_LOGI("BMA4_I2C", "Error [%d] : Communication failure\r\n", rslt); + } else if (rslt == BMA4_E_CONFIG_STREAM_ERROR) { + ESP_LOGI("BMA4_I2C", "Error [%d] : Invalid configuration stream\r\n", + rslt); + } else if (rslt == BMA4_E_SELF_TEST_FAIL) { + ESP_LOGI("BMA4_I2C", "Error [%d] : Self test failed\r\n", rslt); + } else if (rslt == BMA4_E_INVALID_SENSOR) { + ESP_LOGI("BMA4_I2C", "Error [%d] : Device not found\r\n", rslt); + } else if (rslt == BMA4_E_OUT_OF_RANGE) { + ESP_LOGI("BMA4_I2C", "Error [%d] : Out of Range\r\n", rslt); + } else if (rslt == BMA4_E_AVG_MODE_INVALID_CONF) { + ESP_LOGI("BMA4_I2C", + "Error [%d] : Invalid bandwidth and ODR combination in Accel " + "Averaging mode\r\n", + rslt); + } else { + /* For more error codes refer "*_defs.h" */ + ESP_LOGI("BMA4_I2C", "Error [%d] : Unknown error code\r\n", rslt); + } + } +} + +void read_sensor_task(void *params) { + int8_t ret; + struct bma4_accel sens_data = {0}; + + while (1) { + ret = bma4_read_accel_xyz(&sens_data, &bma456_struct); + bma4_error_codes_print_result("bma4_read_accel_xyz", ret); + + ESP_LOGI("ACC", "X: %d, Y: %d, Z: %d", sens_data.x, sens_data.y, + sens_data.z); + + 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"); + } + } + } + + // ESP_LOGI("i2c", "X:%d, Y%d, Z%d", sens_data.x, sens_data.y, sens_data.z); + vTaskDelay(pdMS_TO_TICKS(100)); + } +} + +void init_bma456(i2c_master_bus_handle_t bus_handle) { + i2c_device_config_t dev_cfg_bma456 = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = BMA456_ADDRESS, + .scl_speed_hz = 100000, + }; + + ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg_bma456, + &bma456_dev_handle)); + + 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; + + int8_t ret; + bma456_struct.chip_id = 0; + + ret = bma456h_init(&bma456_struct); + bma4_error_codes_print_result("I2C Init", ret); + + ESP_LOGI("I2C", "Chip Init ausgelesene CHIP ID %d", bma456_struct.chip_id); + + ret = bma4_soft_reset(&bma456_struct); + bma4_error_codes_print_result("bma4_soft_reset", ret); + vTaskDelay(pdMS_TO_TICKS(20)); // Wartezeit nach Reset + + ret = bma4_set_advance_power_save(BMA4_DISABLE, &bma456_struct); + bma4_error_codes_print_result("bma4_set_advance_power_save", ret); + vTaskDelay(pdMS_TO_TICKS(10)); + + ESP_LOGI("I2C", "Config SIZE %d", bma456_struct.config_size); + ESP_LOGI("I2C", "Config Pointer %p", bma456_struct.config_file_ptr); + + ESP_LOGI("I2C", "Starte Config-File Upload..."); + ret = bma456h_write_config_file(&bma456_struct); + bma4_error_codes_print_result("bma4_write_config_file", ret); + + 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); + bma4_error_codes_print_result("bma4_set_accel_config status", ret); + + /* Enable the accelerometer */ + ret = bma4_set_accel_enable(BMA4_ENABLE, &bma456_struct); + bma4_error_codes_print_result("bma4_set_accel_enable status", ret); + + struct bma456h_multitap_settings tap_settings = {0}; + ret = bma456h_tap_get_parameter(&tap_settings, &bma456_struct); + bma4_error_codes_print_result("bma456h_tap_get_parameter status", ret); + tap_settings.tap_sens_thres = 0; + ret = bma456h_tap_set_parameter(&tap_settings, &bma456_struct); + bma4_error_codes_print_result("bma456h_tap_set_parameter status", ret); + + ret = bma456h_feature_enable( + (BMA456H_SINGLE_TAP_EN | BMA456H_DOUBLE_TAP_EN | BMA456H_TRIPLE_TAP_EN), + BMA4_ENABLE, &bma456_struct); + bma4_error_codes_print_result("bma456w_feature_enable status", ret); + + /* Setting watermark level 1, the output step resolution is 20 steps. + * Eg: 1 means, 1 * 20 = 20. Every 20 steps once output triggers + */ + ret = bma456h_step_counter_set_watermark(1, &bma456_struct); + bma4_error_codes_print_result("bma456w_step_counter_set_watermark status", + ret); + + /* Hardware interrupt configuration */ + int_line = BMA4_INTR2_MAP; + + ret = bma4_get_int_pin_config(&pin_config, int_line, &bma456_struct); + bma4_error_codes_print_result("bma4_get_int_pin_config status", ret); + + ret = bma456h_map_interrupt(int_line, BMA456H_TAP_OUT_INT, BMA4_ENABLE, + &bma456_struct); + + bma4_error_codes_print_result("bma456w_map_interrupt status", ret); + + pin_config.edge_ctrl = BMA4_EDGE_TRIGGER; + pin_config.output_en = BMA4_OUTPUT_ENABLE; + pin_config.lvl = BMA4_ACTIVE_HIGH; + 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); + bma4_error_codes_print_result("bma4_set_int_pin_config status", ret); + + 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_install_isr_service(0); + gpio_isr_handler_add(BMA456W_INT_PIN, interrupt_callback, + (void *)BMA456W_INT_PIN); + + xTaskCreate(read_sensor_task, "READ_SENSOR", 4096, NULL, 1, NULL); +} diff --git a/main/bosch456.h b/main/bosch456.h new file mode 100644 index 0000000..928e72b --- /dev/null +++ b/main/bosch456.h @@ -0,0 +1,8 @@ +#include "driver/i2c_types.h" + +#define TOUCH_1 9 +#define TOUCH_2 8 + +#define BMA456_ADDRESS 0x18 + +void init_bma456(i2c_master_bus_handle_t bus_handle); diff --git a/main/hw_test.c b/main/hw_test.c index f0239d7..5f754d2 100644 --- a/main/hw_test.c +++ b/main/hw_test.c @@ -7,6 +7,7 @@ #include "freertos/task.h" #include "led_strip.h" #include +#include "bosch456.h" #define LED_GPIO 21 #define TASTER_GPIO 12 @@ -17,13 +18,10 @@ #define DIP_MASTER 4 #define I2C_SCL 5 #define I2C_SDA 6 -#define TOUCH_1 9 -#define TOUCH_2 8 #define LED_RING 7 #define I2C_PORT 0 #define IO_EXPANDER_ADDRESS 0x20 -#define BMA456_ADDRESS 0x18 static const char *TAG = "LED_TASK"; static led_strip_handle_t led_strip; @@ -31,7 +29,6 @@ static led_strip_handle_t led_ring; static i2c_master_bus_handle_t bus_handle; static i2c_master_dev_handle_t io_expander; -static i2c_master_dev_handle_t bma456_dev_handle; /* LED Task */ void vTaskLed(void *pvParameters) { @@ -91,8 +88,10 @@ void vTaskRingBlink(void *pvParameters) { if (state) { // GREEN led_strip_set_pixel(led_ring, 0, 25, 0, 0); + led_strip_set_pixel(led_ring, 10, 25, 0, 0); } else { led_strip_set_pixel(led_ring, 0, 0, 0, 0); + led_strip_set_pixel(led_ring, 10, 0, 0, 0); } led_strip_refresh(led_ring); @@ -179,4 +178,6 @@ void app_main(void) { } ESP_LOGI(TAG, "Read INPUT %d", read_val); } + + init_bma456(bus_handle); }