From b17ac96f2fd8bf4f36fb28eba5a1de16c623ec5b Mon Sep 17 00:00:00 2001 From: pulipakaa24 Date: Mon, 9 Mar 2026 16:09:28 -0500 Subject: [PATCH] restructured i2c-max split, added BMS unit test --- include/i2c.h | 4 --- include/max17048.h | 5 ++++ src/CMakeLists.txt | 4 +-- src/i2c.c | 55 --------------------------------------- src/main.cpp | 6 +++-- src/max17048.c | 55 +++++++++++++++++++++++++++++++++++++++ test/bms_test.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++ test/bms_test.hpp | 6 +++++ 8 files changed, 137 insertions(+), 63 deletions(-) create mode 100644 test/bms_test.cpp create mode 100644 test/bms_test.hpp diff --git a/include/i2c.h b/include/i2c.h index 274b7e3..a254780 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -14,10 +14,6 @@ extern "C" { #define I2C_MASTER_TIMEOUT_MS 1000 esp_err_t i2c_init(); -esp_err_t max17048_read_reg(uint8_t reg_addr, uint8_t *MSB, uint8_t *LSB); -esp_err_t max17048_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB); -esp_err_t max17048_friendly_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB, - uint8_t MSBmask, uint8_t LSBmask); #ifdef __cplusplus } diff --git a/include/max17048.h b/include/max17048.h index c48b725..23a1b95 100644 --- a/include/max17048.h +++ b/include/max17048.h @@ -61,6 +61,11 @@ void bms_checker_task(void *pvParameters); #define bms_clear_status() max17048_write_reg(MAX17048_REG_STATUS, 0, 0) #define bms_clear_alrt() max17048_friendly_write_reg(MAX17048_REG_CONFIG, 0, 0, 0, 1<<5) +esp_err_t max17048_read_reg(uint8_t reg_addr, uint8_t *MSB, uint8_t *LSB); +esp_err_t max17048_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB); +esp_err_t max17048_friendly_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB, + uint8_t MSBmask, uint8_t LSBmask); + #ifdef __cplusplus } #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e3e1ef0..9453961 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,8 @@ # This file was automatically generated for projects # without default 'CMakeLists.txt' file. -FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*) +FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.* ${CMAKE_SOURCE_DIR}/test/*.*) idf_component_register(SRCS ${app_sources} - INCLUDE_DIRS "." + INCLUDE_DIRS "." "${CMAKE_SOURCE_DIR}/test" REQUIRES nvs_flash esp-nimble-cpp esp_socketio_client) diff --git a/src/i2c.c b/src/i2c.c index 0548349..9b89a75 100644 --- a/src/i2c.c +++ b/src/i2c.c @@ -18,58 +18,3 @@ esp_err_t i2c_init() { return (i2c_param_config(I2C_MASTER_NUM, &conf) || i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0)); } - -// Helper: Read 16-bit register to 2-byte array (MSB first big endian) -esp_err_t max17048_read_reg(uint8_t reg_addr, uint8_t *MSB, uint8_t *LSB) { - // this is better than converting to little endian for my application - // since I usually need to handle bytes individually. - uint8_t data[2]; - // Write register address - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (MAX17048_ADDR << 1) | I2C_MASTER_WRITE, true); - i2c_master_write_byte(cmd, reg_addr, true); - - // Restart and Read 2 bytes - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (MAX17048_ADDR << 1) | I2C_MASTER_READ, true); - i2c_master_read(cmd, data, 2, I2C_MASTER_LAST_NACK); - i2c_master_stop(cmd); - - esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); - i2c_cmd_link_delete(cmd); - - if (ret == ESP_OK) { - *MSB = data[0]; - *LSB = data[1]; - } - - return ret; -} - -// Write big endian 2-byte array to a 16-bit register -esp_err_t max17048_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB) { - // Write register address - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, (MAX17048_ADDR << 1) | I2C_MASTER_WRITE, true); - i2c_master_write_byte(cmd, reg_addr, true); - i2c_master_write_byte(cmd, MSB, true); - i2c_master_write_byte(cmd, LSB, true); - i2c_master_stop(cmd); - - esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); - i2c_cmd_link_delete(cmd); - return ret; -} - -esp_err_t max17048_friendly_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB, - uint8_t MSBmask, uint8_t LSBmask) { - uint8_t origMSB, origLSB; - esp_err_t err = max17048_read_reg(reg_addr, &origMSB, &origLSB); - MSB &= MSBmask; - LSB &= LSBmask; - MSB |= origMSB & ~MSBmask; - LSB |= origLSB & ~LSBmask; - return err | max17048_write_reg(reg_addr, MSB, LSB); -} diff --git a/src/main.cpp b/src/main.cpp index 6a036d1..93031fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ #include "esp_pm.h" #include "mainEventLoop.hpp" #include "max17048.h" +#include "bms_test.hpp" // Global encoder instances Encoder* topEnc = new Encoder(ENCODER_PIN_A, ENCODER_PIN_B); @@ -53,6 +54,7 @@ void pm_init() { } extern "C" void app_main() { - pm_init(); - mainApp(); + // pm_init(); + // mainApp(); + bms_test_app(); } \ No newline at end of file diff --git a/src/max17048.c b/src/max17048.c index 6477c8e..da4e826 100644 --- a/src/max17048.c +++ b/src/max17048.c @@ -118,3 +118,58 @@ void bms_checker_task(void *pvParameters) { } } } + +// Helper: Read 16-bit register to 2-byte array (MSB first big endian) +esp_err_t max17048_read_reg(uint8_t reg_addr, uint8_t *MSB, uint8_t *LSB) { + // this is better than converting to little endian for my application + // since I usually need to handle bytes individually. + uint8_t data[2]; + // Write register address + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (MAX17048_ADDR << 1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, reg_addr, true); + + // Restart and Read 2 bytes + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (MAX17048_ADDR << 1) | I2C_MASTER_READ, true); + i2c_master_read(cmd, data, 2, I2C_MASTER_LAST_NACK); + i2c_master_stop(cmd); + + esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); + i2c_cmd_link_delete(cmd); + + if (ret == ESP_OK) { + *MSB = data[0]; + *LSB = data[1]; + } + + return ret; +} + +// Write big endian 2-byte array to a 16-bit register +esp_err_t max17048_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB) { + // Write register address + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (MAX17048_ADDR << 1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, reg_addr, true); + i2c_master_write_byte(cmd, MSB, true); + i2c_master_write_byte(cmd, LSB, true); + i2c_master_stop(cmd); + + esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)); + i2c_cmd_link_delete(cmd); + return ret; +} + +esp_err_t max17048_friendly_write_reg(uint8_t reg_addr, uint8_t MSB, uint8_t LSB, + uint8_t MSBmask, uint8_t LSBmask) { + uint8_t origMSB, origLSB; + esp_err_t err = max17048_read_reg(reg_addr, &origMSB, &origLSB); + MSB &= MSBmask; + LSB &= LSBmask; + MSB |= origMSB & ~MSBmask; + LSB |= origLSB & ~LSBmask; + return err | max17048_write_reg(reg_addr, MSB, LSB); +} \ No newline at end of file diff --git a/test/bms_test.cpp b/test/bms_test.cpp new file mode 100644 index 0000000..fddc45c --- /dev/null +++ b/test/bms_test.cpp @@ -0,0 +1,65 @@ +#include "bms_test.hpp" +#include "i2c.h" +#include "max17048.h" + +void bms_test_app() { + vTaskDelay(pdMS_TO_TICKS(5000)); + esp_err_t err = i2c_init(); + + printf("Error after init: %d\n", err); + + gpio_config_t io_conf = { + .pin_bit_mask = (1ULL << maxALRT), + .mode = GPIO_MODE_INPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&io_conf); + + printf("BMS test running. Polling ALRT pin every 1s...\n"); + + + uint8_t msb, lsb; + if (max17048_read_reg(MAX17048_REG_STATUS, &msb, &lsb) == ESP_OK) { + printf(" STATUS before clear: RI=%d\n", !!(msb & RIbit)); + printf(" STATUS reg before clear: RI=%x, %x\n", msb, lsb); + } else { + printf(" STATUS read FAILED\n"); + } + + err = bms_set_alert_bound_voltages(3.3f, 4.2f); + printf("Error after boundV: %d\n", err); + err |= bms_clear_status(); + printf("Error after clearStatus: %d\n", err); + err |= bms_clear_alrt(); + printf("Error after clearALRT: %d\n", err); + + if (max17048_read_reg(MAX17048_REG_STATUS, &msb, &lsb) == ESP_OK) { + printf(" STATUS after clear: RI=%d\n", !!(msb & RIbit)); + printf(" STATUS reg after clear: RI=%x, %x\n", msb, lsb); + } else { + printf(" STATUS read FAILED\n"); + } + + while (true) { + int level = gpio_get_level(maxALRT); + printf("ALRT pin: %s\n", level ? "HIGH (no alert)" : "LOW (alert asserted)"); + + if (level == 0) { + if (max17048_read_reg(MAX17048_REG_STATUS, &msb, &lsb) == ESP_OK) { + printf(" STATUS: VH=%d VL=%d HD=%d SC=%d\n", + !!(msb & VHbit), + !!(msb & VLbit), + !!(msb & HDbit), + !!(msb & SCbit)); + bms_clear_status(); + bms_clear_alrt(); + } else { + printf(" STATUS read FAILED\n"); + } + } + + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} \ No newline at end of file diff --git a/test/bms_test.hpp b/test/bms_test.hpp new file mode 100644 index 0000000..2553ddc --- /dev/null +++ b/test/bms_test.hpp @@ -0,0 +1,6 @@ +#ifndef BMS_TEST_H +#define BMS_TEST_H + +void bms_test_app(); + +#endif \ No newline at end of file