Skip to content

Commit

Permalink
Update CMakeLists.txt and ina226_driver.h/cpp
Browse files Browse the repository at this point in the history
Add target_compile_features to set C++ and C standards to 23 and add target_compile_options to enable exceptions and RTTI in ina226_driver.cpp
  • Loading branch information
ZivLow committed Jan 25, 2024
1 parent 24850a8 commit a133bc7
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 62 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ idf_component_register(
REQUIRES driver
)

set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 23)
set_property(TARGET ${COMPONENT_LIB} PROPERTY C_STANDARD 17)
target_compile_features(${COMPONENT_LIB} PUBLIC cxx_std_23)
target_compile_features(${COMPONENT_LIB} PUBLIC c_std_23)
target_compile_options(${COMPONENT_LIB} PRIVATE -fexceptions -frtti)
62 changes: 62 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
menu "INA226"

menu "I2C Master"

orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"

config I2C_MASTER_SDA
int "SDA GPIO Num"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 1 if IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2
default 21 if IDF_TARGET_ESP32
default 5
help
GPIO number for I2C Master data line.

config I2C_MASTER_SCL
int "SCL GPIO Num"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 2 if IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2
default 22 if IDF_TARGET_ESP32
default 6
help
GPIO number for I2C Master clock line.

config I2C_MASTER_PORT_NUM
int "Port Number"
default 1 if SOC_I2C_NUM > 1
default 0
help
Port number for I2C Master device.

config I2C_MASTER_FREQUENCY
int "Master Frequency"
default 100000
help
I2C Speed of Master device.

endmenu

menu "INA226 Power Monitor Sensor"

config INA226_I2C_ADDRESS
hex
default 0x40
help
Hardware address of INA226

config INA226_SHUNT_RESISTOR_MILLIOHMS
int "Shunt Resistance"
default 100
help
Shunt resistor value in milliohms.

config INA226_MAX_CURRENT_AMPS
int "Max Current"
default 1
help
Max current in amperes.

endmenu

endmenu
58 changes: 22 additions & 36 deletions interface/ina226_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "ina226_interface.h"
#include <utility>
#include <string>
#include "esp_err.h"

#define I2C_TIMEOUT_MS 100
Expand Down Expand Up @@ -74,58 +75,43 @@ std::expected<uint16_t, std::runtime_error> INA226::I2C_Read(const INA226::Regis
}
}

std::expected<void, std::runtime_error> INA226::I2C_Init(gpio_num_t sda_io_num, gpio_num_t scl_io_num, uint16_t address) {
esp_err_t err;

i2c_bus_config = {
.i2c_port = -1,
INA226::INA226(const gpio_num_t sda_io_num, const gpio_num_t scl_io_num, const uint16_t address, const uint32_t scl_frequency, const i2c_port_num_t i2c_port_num)
: i2c_bus_config{
.i2c_port = i2c_port_num,
.sda_io_num = sda_io_num,
.scl_io_num = scl_io_num,
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.intr_priority = 0,
.trans_queue_depth = 0, // ESP-IDF v5.2-beta2: Memory leak will occur if trans_queue_depth > 0, as it will use asynchronous i2c
.flags {
.trans_queue_depth = 0,
.flags{
.enable_internal_pullup = true,
},
};

i2c_dev_cfg = {
},
i2c_dev_cfg{
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = address,
.scl_speed_hz = 100000,
};
.scl_speed_hz = scl_frequency,
}

{
esp_err_t err;

err = i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
if (err != ESP_OK) {
return HandleI2CError("I2C bus initialization", err);
}
if (err != ESP_OK)
throw std::runtime_error("I2C bus initialization failed. err = " + std::to_string(err));

err = i2c_master_bus_add_device(i2c_bus_handle, &i2c_dev_cfg, &i2c_dev_handle);
if (err != ESP_OK) {
return HandleI2CError("I2C add device", err);
}
if (err != ESP_OK)
throw std::runtime_error("I2C add device failed. err = " + std::to_string(err));

err = CreateMutex(Lock);
if (err != ESP_OK) {
return HandleI2CError("I2C mutex creation", err);
}

return {};
}
if (err != ESP_OK)
throw std::runtime_error("I2C mutex creation failed. err = " + std::to_string(err));

std::expected<void, std::runtime_error> INA226::HandleI2CError(const std::string &operation, esp_err_t err) {
std::string errorMessage = operation + " failed. err = " + std::to_string(err);
switch (err) {
case ESP_ERR_INVALID_ARG:
return std::unexpected(std::runtime_error(errorMessage + ": invalid argument"));
case ESP_ERR_NO_MEM:
return std::unexpected(std::runtime_error(errorMessage + ": out of memory"));
case ESP_ERR_NOT_FOUND:
return std::unexpected(std::runtime_error(errorMessage + ": no more free I2C bus"));
default:
return std::unexpected(std::runtime_error(errorMessage));
}
auto start_driver = InitDriver();
if (start_driver.has_value() == false)
throw std::runtime_error(std::string("INA226 driver initialization failed. err = ") + start_driver.error().what());
}

esp_err_t INA226::CreateMutex(SemaphoreHandle_t &mutex) {
Expand Down
23 changes: 8 additions & 15 deletions interface/ina226_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@

#pragma once

#include <expected>
#include <stdexcept>
#include "ina226_driver.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "driver/i2c_master.h"
#include <string>


#define DEFAULT_INA226_I2C_ADDRESS 0x40
Expand All @@ -37,12 +38,13 @@ class INA226 : public INA226_Driver {
/**
* @brief Initializes the I2C of ESP-IDF
*
* @param[in] sda_io_num GPIO number of SDA pin
* @param[in] scl_io_num GPIO number of SCL pin
* @param[in] address I2C address of INA226
* @return std::expected<void, std::runtime_error>
* @param[in] sda_io_num GPIO number of SDA pin. Defaults to GPIO 21 for ESP32.
* @param[in] scl_io_num GPIO number of SCL pin. Defaults to GPIO 22 for ESP32.
* @param[in] address I2C address of INA226. Defaults to 0x40.
* @param[in] scl_frequency Frequency of SCL pin. Defaults to 100000.
* @param[in] i2c_port_num I2C port number.
*/
std::expected<void, std::runtime_error> I2C_Init(gpio_num_t sda_io_num = GPIO_NUM_21, gpio_num_t scl_io_num = GPIO_NUM_22, uint16_t address = DEFAULT_INA226_I2C_ADDRESS);
INA226(const gpio_num_t sda_io_num = static_cast<gpio_num_t>(CONFIG_I2C_MASTER_SDA), const gpio_num_t scl_io_num = static_cast<gpio_num_t>(CONFIG_I2C_MASTER_SCL), const uint16_t address = CONFIG_INA226_I2C_ADDRESS, const uint32_t scl_frequency = CONFIG_I2C_MASTER_FREQUENCY, const i2c_port_num_t i2c_port_num = static_cast<i2c_port_num_t>(CONFIG_I2C_MASTER_PORT_NUM));

protected:
/**
Expand All @@ -62,15 +64,6 @@ class INA226 : public INA226_Driver {
*/
std::expected<uint16_t, std::runtime_error> I2C_Read(const Register Register) override;

/**
* @brief Handles I2C related errors.
*
* @param[in] operation The operation that caused the error
* @param[in] err The error code
* @return std::expected<void, std::runtime_error>
*/
std::expected<void, std::runtime_error> HandleI2CError(const std::string &operation, esp_err_t err);

/**
* @brief Creates a mutex for I2C bus
*
Expand Down
9 changes: 2 additions & 7 deletions src/ina226_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
*/

#include "ina226_driver.h"
#include <inttypes.h>
#include <cmath>
#include <format>
#include <utility>
#include "esp_log.h"

enum class INA226_Driver::Const : uint16_t {
BUS_VOLTAGE_LSB_uV = 1250, // 1250 uV/bit
Expand Down Expand Up @@ -56,11 +56,10 @@ enum class INA226_Driver::ConfigOffset : uint8_t {
RESET = 15,
};

std::expected<void, std::runtime_error> INA226_Driver::Init(const uint32_t ShuntResistor_mOhm, const uint32_t MaxCurrent_A) {
std::expected<void, std::runtime_error> INA226_Driver::InitDriver(const uint32_t ShuntResistor_mOhm, const uint32_t MaxCurrent_A) {
Reset();
auto config = GetConfig();
if (config == std::to_underlying(Const::CONFIG_RESET_VALUE)) {
ESP_LOGW("INA226-Driver", "Init calibrating");
Calibrate(ShuntResistor_mOhm, MaxCurrent_A);
return {};
}
Expand All @@ -86,10 +85,8 @@ int32_t INA226_Driver::GetBusVoltage_mV() {
int32_t INA226_Driver::GetCurrent_uA() {
auto result = I2C_Read(Register::CURRENT);
if (result.has_value()) {
ESP_LOGW("INA226-Driver", "GetCurrent_uA has value of %" PRIu16, result.value());
return static_cast<int16_t>(result.value()) * Current_LSB_uA;
}
ESP_LOGW("INA226-Driver", "GetCurrent_uA has no value");
return 0;
}

Expand Down Expand Up @@ -175,9 +172,7 @@ void INA226_Driver::Reset() {

void INA226_Driver::Calibrate(const uint32_t ShuntResistor_mOhm, const uint32_t MaxCurrent_A) {
Current_LSB_uA = std::ceil(MaxCurrent_A * 1000000 / (1 << 15));
ESP_LOGW("INA226_Driver", "Current_LSB_uA = %" PRIu16, Current_LSB_uA);
auto cal = static_cast<uint16_t>(0.00512 / (ShuntResistor_mOhm / 1000.0) / (Current_LSB_uA / 1000000.0));
ESP_LOGW("INA226_Driver", "cal = %" PRIu16, cal);
I2C_Write(Register::CALIBRATION, cal);
}

Expand Down
3 changes: 1 addition & 2 deletions src/ina226_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#pragma once

#include <inttypes.h>
#include <expected>
#include <stdexcept>

Expand Down Expand Up @@ -126,7 +125,7 @@ class INA226_Driver {
* @param[in] MaxCurrent_A Maximum current in Amps. Defaults to 1A.
* @return std::expected<void, std::runtime_error>
*/
std::expected<void, std::runtime_error> Init(const uint32_t ShuntResistor_mOhm = 100, const uint32_t MaxCurrent_A = 1);
std::expected<void, std::runtime_error> InitDriver(const uint32_t ShuntResistor_mOhm = CONFIG_INA226_SHUNT_RESISTOR_MILLIOHMS, const uint32_t MaxCurrent_A = CONFIG_INA226_MAX_CURRENT_AMPS);

/**
* @name Getters
Expand Down

0 comments on commit a133bc7

Please sign in to comment.