groundwork for BMS
This commit is contained in:
0
include/batteryManagement.hpp
Normal file
0
include/batteryManagement.hpp
Normal file
26
include/i2c.h
Normal file
26
include/i2c.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef I2C_HELPER_H
|
||||
#define I2C_HELPER_H
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// I2C Configuration (Match your schematic)
|
||||
#define I2C_MASTER_SCL_IO GPIO_NUM_23 // Example GPIO for C6
|
||||
#define I2C_MASTER_SDA_IO GPIO_NUM_22 // Example GPIO for C6
|
||||
#define I2C_MASTER_NUM 0
|
||||
#define I2C_MASTER_FREQ_HZ 100000 // use standard freq
|
||||
#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
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
38
include/max17048.h
Normal file
38
include/max17048.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef MAX_17_H
|
||||
#define MAX_17_H
|
||||
|
||||
#define MAX17048_ADDR 0x36
|
||||
#define MAX17048_REG_VCELL 0x02 // Voltage
|
||||
#define MAX17048_REG_SOC 0x04 // State of Charge (%)
|
||||
#define MAX17048_REG_MODE 0x06
|
||||
#define MAX17048_REG_VERSION 0x08
|
||||
#define MAX17048_REG_CONFIG 0x0C
|
||||
#define MAX17048_REG_CMD 0xFE // Command (Reset)
|
||||
#define MAX17048_REG_STATUS 0x1A
|
||||
#define MAX17048_REG_VALRT 0x14
|
||||
#define MAX17048_REG_VRST_ID 0x18
|
||||
|
||||
// Commands
|
||||
#define MAX17048_CMD_POR 0x5400 // Power On Reset command
|
||||
#define MAX17048_CMD_QSTRT 0x4000 // Quick Start command
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "driver/i2c.h"
|
||||
|
||||
esp_err_t max17048_init();
|
||||
uint8_t bms_get_soc();
|
||||
esp_err_t bms_set_alert_bound_voltages(float min, float max);
|
||||
esp_err_t bms_set_reset_voltage(float vreset);
|
||||
esp_err_t bms_clear_status();
|
||||
|
||||
#define bms_set_alsc() max17048_friendly_write_reg(MAX17048_REG_CONFIG, 0, 1<<6, 0, 1<<6)
|
||||
#define bms_clear_status() max17048_write_reg(MAX17048_REG_STATUS, 0, 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -132,7 +132,6 @@ CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK=0
|
||||
CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT=8
|
||||
CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x000000007FFFFF00
|
||||
CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y
|
||||
CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y
|
||||
CONFIG_SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP=y
|
||||
CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX=y
|
||||
CONFIG_SOC_CLOCKOUT_HAS_SOURCE_GATE=y
|
||||
@@ -2357,13 +2356,6 @@ CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y
|
||||
#
|
||||
# CONFIG_OPENTHREAD_ENABLED is not set
|
||||
|
||||
#
|
||||
# Thread Console
|
||||
#
|
||||
CONFIG_OPENTHREAD_CLI=y
|
||||
CONFIG_OPENTHREAD_CONSOLE_COMMAND_PREFIX="ot"
|
||||
# end of Thread Console
|
||||
|
||||
#
|
||||
# OpenThread Spinel
|
||||
#
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "BLE.hpp"
|
||||
#include "NimBLEDevice.h"
|
||||
#include "WiFi.hpp"
|
||||
#include "nvs_flash.h"
|
||||
#include "socketIO.hpp"
|
||||
@@ -1,7 +1,7 @@
|
||||
# This file was automatically generated for projects
|
||||
# without default 'CMakeLists.txt' file.
|
||||
|
||||
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.* ${CMAKE_SOURCE_DIR}/include/*.cpp)
|
||||
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
|
||||
10
src/batteryManagement.cpp
Normal file
10
src/batteryManagement.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
// 3. Post Event to System Loop
|
||||
battery_data_t data = { .soc = soc, .voltage = voltage };
|
||||
|
||||
esp_event_post(BATTERY_EVENTS, BATTERY_EVENT_UPDATE, &data, sizeof(data), 0);
|
||||
|
||||
// Optional: Post warnings
|
||||
if (soc < 20.0) {
|
||||
esp_event_post(BATTERY_EVENTS, BATTERY_EVENT_LOW, NULL, 0, 0);
|
||||
}
|
||||
75
src/i2c.c
Normal file
75
src/i2c.c
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "i2c.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_log.h"
|
||||
#include "max17048.h"
|
||||
|
||||
// Helper: Initializes I2C controller at 100kHz, returns 0=success
|
||||
esp_err_t i2c_init() {
|
||||
// 1. Initialize I2C
|
||||
i2c_config_t conf = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
44
src/max17048.c
Normal file
44
src/max17048.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "max17048.h"
|
||||
#include "esp_err.h"
|
||||
#include "i2c.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
static const char *TAG = "BATTERY";
|
||||
uint8_t established_soc;
|
||||
|
||||
esp_err_t max17048_init() {
|
||||
esp_err_t err = ESP_OK;
|
||||
uint8_t status, _;
|
||||
err |= i2c_init();
|
||||
err |= max17048_read_reg(MAX17048_REG_STATUS, &status, &_);
|
||||
err |= bms_set_alert_bound_voltages(3.3, 4.2);
|
||||
err |= bms_set_reset_voltage(3.25);
|
||||
err |= bms_set_alsc();
|
||||
err |= bms_clear_status();
|
||||
|
||||
}
|
||||
|
||||
// Helper: Function reading MAX17048 SOC register, returning battery percentage
|
||||
uint8_t bms_get_soc() {
|
||||
// uint16_t raw_soc, raw_vcell;
|
||||
uint16_t raw_soc;
|
||||
|
||||
// Read SOC (Register 0x04)
|
||||
if (max17048_read_reg(MAX17048_REG_SOC, ((uint8_t*)&raw_soc)+1, (uint8_t*)&raw_soc) == ESP_OK) {
|
||||
return (raw_soc >> 8) + raw_soc & 0x80; // round to the nearest percent
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read MAX17048");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bms_set_alert_bound_voltages(float min, float max) {
|
||||
uint8_t minVal = (uint16_t)((float)min * 1000.0) / 20;
|
||||
uint8_t maxVal = (uint16_t)((float)max * 1000.0) / 20;
|
||||
return max17048_write_reg(MAX17048_REG_VALRT, minVal, maxVal);
|
||||
}
|
||||
|
||||
esp_err_t bms_set_reset_voltage(float vreset) {
|
||||
uint8_t maxVal = (uint16_t)((float)vreset * 1000.0) / 40;
|
||||
max17048_write_reg(MAX17048_REG_VRST_ID, vreset, 0);
|
||||
}
|
||||
Reference in New Issue
Block a user