diff --git a/.gitmodules b/.gitmodules index 5ca5316..be6503d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "lib/ulog"] path = lib/ulog url = https://github.com/rdpoor/ulog.git +[submodule "lib/ee24"] + path = lib/ee24 + url = git@git.lan:oliver/ee24.git diff --git a/Application/BSP/BSP_EE24.c b/Application/BSP/BSP_EE24.c new file mode 100644 index 0000000..aee5e08 --- /dev/null +++ b/Application/BSP/BSP_EE24.c @@ -0,0 +1,244 @@ +/*** +* @file BSP_EE24.c +* This file contains functions to interact with an EEPROM driver and perform +* read and write operations on it. The driver uses I2C protocol and supports +* multiple partitions, which can be used to store different types of data. +*/ + +#include "BSP_EE24.h" +#include "ee24.h" +#include "i2c.h" +#include "cmsis_os2.h" +#include "gpio.h" + +#define BSP_EE24_I2C &hi2c2 +#define BSP_EE24_ADDRESS EE24_ADDRESS_DEFAULT +#define BSP_EE24_TIMEOUT 500 +#define BSP_EE24_MUTEXT_TIMEOUT osWaitForever + +// Main Pariton Table +static BSP_EE24_Partion PartionTable[__BSP_EE24_PART_MAX__] = { + [BSP_EE24_PART_HEAD_PARTION] = { + .address = -1, + .len = sizeof(BSP_EE24_TableHeader) + }, + [BSP_EE24_PART_GLOBAL_LIGHT] = { + .address = -1, + .len = 64, + }, + [BSP_EE24_PART_RESERVED] = { + .address = -1, + .len = 128, + } +}; +static const uint32_t PartionTableVersion = 1; +static EE24_HandleTypeDef hee24 = {0}; +static osMutexId_t ee24_lock; + +void BSP_EE24_TableMigrate(uint32_t ee_version); + +/** + * Initializes the EEPROM Partition Table. + * + * This function calculates the addresses of each element in the Partition Table + * based on their lengths and the previous element's address. It assumes that the + * Partition Table is ordered by ascending addresses, and that there are no gaps + * between elements. + */ +void BSP_EE24_InitTable() { + uint32_t address = 0; // Start at address 0 + for (int i = 1; i < __BSP_EE24_PART_MAX__; i++) { + if (PartionTable[i].len > 0) { + PartionTable[i].address = address; + address += PartionTable[i].len; + } + } +} + + +/** + * Initializes the EEPROM driver and performs any necessary migrations. + */ +bool BSP_EE24_Init(void) { + // Initialize the EE24 driver with the I2C interface and address + bool status = EE24_Init(&hee24,BSP_EE24_I2C,BSP_EE24_ADDRESS); + if(!status) { + return status; + } + + // os mutext + ee24_lock = osMutexNew(NULL); + + // wc control high disables write + HAL_GPIO_WritePin(EEPROM_WC_GPIO_Port, EEPROM_WC_Pin, GPIO_PIN_SET); + + // Read the Partition Table header from the EEPROM + BSP_EE24_TableHeader header = {0}; + status = BSP_EE24_PartRead(BSP_EE24_PART_HEAD_PARTION, (uint8_t*)&header, sizeof(header)); + if(!status) { + return status; + } + + // Check if the Partition Table version is different from the expected version + uint32_t fw_table_version = PartionTableVersion; + uint32_t ee_table_version = header.version; + if(ee_table_version != fw_table_version) { + BSP_EE24_TableMigrate(ee_table_version); + if(!status) { + return status; + } + } + + return true; +} + + +/** + * Reads data from the EEPROM. + * This function is blocking for the operation to complete. + * + * @param[in] Address The starting address of the data to be read. + * @param[out] Data A pointer to a buffer where the data will be stored. + * @param[in] Len The number of bytes to be read. + * @return true if the operation was successful, false otherwise. + */ +bool BSP_EE24_Read(uint32_t Address, uint8_t *Data, size_t Len) { + osMutexAcquire(ee24_lock,BSP_EE24_MUTEXT_TIMEOUT); + bool status = EE24_Read(&hee24,Address,Data,Len,BSP_EE24_TIMEOUT); + osMutexRelease(ee24_lock); + return status; +} + +/** + * Writes data to the EEPROM. + * This function is blocking for the operation to complete. + * + * @param[in] Address The starting address of the data to be written. + * @param[out] Data A pointer to a buffer containing the data to be written. + * @param[in] Len The number of bytes to be written. + * @return true if the operation was successful, false otherwise. + */ +bool BSP_EE24_Write(uint32_t Address, uint8_t *Data, size_t Len) { + osMutexAcquire(ee24_lock,BSP_EE24_MUTEXT_TIMEOUT); + HAL_GPIO_WritePin(EEPROM_WC_GPIO_Port, EEPROM_WC_Pin, GPIO_PIN_RESET); // low enables write; + bool status = EE24_Write(&hee24,Address,Data,Len,BSP_EE24_TIMEOUT); + HAL_GPIO_WritePin(EEPROM_WC_GPIO_Port, EEPROM_WC_Pin, GPIO_PIN_SET); // high disables write; + osMutexRelease(ee24_lock); + return status; +} + +/** + * Reads data from a specific partition in the EEPROM. + * This function is blocking for the operation to complete. + * + * @param[in] part The identifier of the partition to read from. + * Must be one of the BSP_EE24_PART_* constants. + * @param[out] Data A pointer to a buffer where the data will be stored. + * @param[in] LenBuffer The maximum number of bytes to be read from the partition. + * @return true if the operation was successful, false otherwise. + */ +bool BSP_EE24_PartRead(BSP_EE24_PartionEntry_e part, uint8_t *Data, size_t LenBuffer) { + // Check if the partition is valid and has data to read + if (!(part < __BSP_EE24_PART_MAX__ && PartionTable[part].len > 0)) { + return false; + } + + // Read the Partion address + uint32_t Address = PartionTable[part].address; + + // Calculate the length to be read + uint32_t Len = 0; + if (PartionTable[part].len < LenBuffer) { + Len = PartionTable[part].len; + } else { + Len = LenBuffer; + } + + return BSP_EE24_Read(Address,Data,Len); + +} + +/** + * Writes data to a specific partition in the EEPROM. + * This function is blocking for the operation to complete. + * + * @param[in] part The identifier of the partition to write to. + * Must be one of the BSP_EE24_PART_* constants. + * @param[out] Data A pointer to a buffer containing the data to be written. + * @param[in] LenBuffer The maximum number of bytes to be written to the partition. + * @return true if the operation was successful, false otherwise. + */ +bool BSP_EE24_PartWrite(BSP_EE24_PartionEntry_e part, uint8_t *Data, size_t LenBuffer) { + // Check if the partition is valid and has data to read + if (!(part < __BSP_EE24_PART_MAX__ && PartionTable[part].len > 0)) { + return false; + } + + // Read the Partion address + uint32_t Address = PartionTable[part].address; + + // Calculate the length to be read + uint32_t Len = 0; + if (PartionTable[part].len < LenBuffer) { + Len = PartionTable[part].len; + } else { + Len = LenBuffer; + } + + return BSP_EE24_Write(Address,Data,Len); +} + +static inline size_t MIN_MEM(size_t a, size_t b) { return((a) < (b) ? a : b); } + + +/** + * Clear a new or undefined eeprom + */ +void BSP_EE24_FullClear() { + size_t len = 0; + for (int i = 1; i < __BSP_EE24_PART_MAX__; i++) { + len += PartionTable[i].len; + } + + BSP_EE24_TableHeader header = { + .version = PartionTableVersion, + .used_len = len, + .reserved = {0}, + }; + + // write header + BSP_EE24_PartWrite(BSP_EE24_PART_HEAD_PARTION, (uint8_t*)&header, sizeof(header)); + + // Calculate the start address and length of the clear operation + uint32_t clear_start = PartionTable[BSP_EE24_PART_HEAD_PARTION].address + PartionTable[BSP_EE24_PART_HEAD_PARTION].len; + uint32_t clear_len = header.used_len - PartionTable[BSP_EE24_PART_HEAD_PARTION].len; + + // Use a 16-byte buffer to perform the write operation in chunks of 16 bytes + uint8_t clear_buffer[16] = {0}; + + while (clear_start < header.used_len) { + size_t chunk_size = MIN_MEM(clear_len, sizeof(clear_buffer)); + BSP_EE24_Write(clear_start, clear_buffer, chunk_size); + clear_start += chunk_size; + } + +} + +/** + * migrate form diffrent versions of the eeprom + */ +void BSP_EE24_TableMigrate(uint32_t ee_version) { + + if(ee_version == PartionTableVersion) { + // current fw version, do nothing + return; + } + + switch (ee_version) + { + + default: // undefined write zeros. + BSP_EE24_FullClear(); + break; + } +} \ No newline at end of file diff --git a/Application/BSP/BSP_EE24.h b/Application/BSP/BSP_EE24.h new file mode 100644 index 0000000..5f0ed7f --- /dev/null +++ b/Application/BSP/BSP_EE24.h @@ -0,0 +1,51 @@ +#pragma once +/** +* @file BSP_EE24.h +* This file contains functions to interact with an EEPROM driver and perform +* read and write operations on it. The driver uses I2C protocol and supports +* multiple partitions, which can be used to store different types of data. +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +typedef struct BSP_EE24_Partion_s +{ + uint32_t address; + size_t len; +}BSP_EE24_Partion; + + +typedef struct BSP_EE24_TableHeader_s +{ + uint32_t version; + size_t used_len; + uint8_t reserved[16]; +} BSP_EE24_TableHeader; + + +typedef enum BSP_EE24_PartionEntry { + BSP_EE24_PART_HEAD_PARTION, + BSP_EE24_PART_GLOBAL_LIGHT, + BSP_EE24_PART_RESERVED, + __BSP_EE24_PART_MAX__, +}BSP_EE24_PartionEntry_e; + + +bool BSP_EE24_Init(void); +bool BSP_EE24_Read(uint32_t Address, uint8_t *Data, size_t Len); +bool BSP_EE24_Write(uint32_t Address, uint8_t *Data, size_t Len); + + +bool BSP_EE24_PartRead(BSP_EE24_PartionEntry_e part, uint8_t *Data, size_t LenCheck); +bool BSP_EE24_PartWrite(BSP_EE24_PartionEntry_e part, uint8_t *Data, size_t LenCheck); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/Application/BSP/BSP_GPIO.h b/Application/BSP/BSP_GPIO.h new file mode 100644 index 0000000..0e2b917 --- /dev/null +++ b/Application/BSP/BSP_GPIO.h @@ -0,0 +1,3 @@ +// GPIOs access functions +// External Interrupts +// Shordhand functions to read improtant pins \ No newline at end of file diff --git a/Application/BSP/BSP_INA.c b/Application/BSP/BSP_INA.c new file mode 100644 index 0000000..bf6f3fc --- /dev/null +++ b/Application/BSP/BSP_INA.c @@ -0,0 +1,79 @@ +/** +* @file BSP_INA.c +* @brief Driver for the BSP INA219 module +* +* This file provides a driver for the BSP INA219 module, which is used to measure voltage and current values. +* The driver includes functions for initializing the module, reading the current and voltage values, and calculating the power value. +* All of these functions are wrapped in a mutex lock to ensure consistent reading of the values. +*/ + +#include "BSP_INA.h" +#include "i2c.h" +#include "INA219.h" +#include "cmsis_os2.h" + +#define BSP_INA_I2C &hi2c1 +#define BSP_INA_ADDRESS INA219_ADDRESS | 0x05 +#define BSP_INA_MUTEX_TIMEOUT osWaitForever + +static INA219_t hina = {0}; +static osMutexId_t ina_lock = NULL; + +/** +* @brief Initializes the INA219 module and sets up the I2C bus. +*/ +void BSP_INA_Init(void) { + INA219_Init(&hina, BSP_INA_I2C, BSP_INA_ADDRESS); + + ina_lock = osMutexNew(NULL); + // default done by Init + // INA219_Reset(ina219); + // INA219_setCalibration_32V_2A(&hina); +} + + +/** +* @brief Reads the voltage value from the INA219. +* +* This function acquires a mutex to ensure that the voltage value is read consistently. +* The mutex is released after the value has been read. +* +* @return The voltage value in milli Volts (mV) +*/ +uint16_t BSP_INA_Voltage() { + osMutexAcquire(ina_lock,BSP_INA_MUTEX_TIMEOUT); + uint16_t result = INA219_ReadBusVoltage(&hina); + osMutexRelease(ina_lock); + return result; +} + +/** +* @brief Reads the current value from the INA219. +* +* This function acquires a mutex to ensure that the current value is read consistently. +* The mutex is released after the value has been read. +* +* @return The current value in 10 milli Amperes (10mA) +*/ +uint16_t BSP_INA_Current() { + osMutexAcquire(ina_lock,BSP_INA_MUTEX_TIMEOUT); + uint16_t result = INA219_ReadCurrent(&hina); + osMutexRelease(ina_lock); + return result; +} + +/** +* @brief Reads the power value from the INA219. +* +* This function acquires a mutex to ensure that the power value is read consistently. +* The mutex is released after the value has been read. +* +* @return The power value in micro Watts (uW) +*/ +uint32_t BSP_INA_Power() { + osMutexAcquire(ina_lock,BSP_INA_MUTEX_TIMEOUT); + uint16_t result_current = INA219_ReadCurrent(&hina); + uint16_t result_voltage = INA219_ReadBusVoltage(&hina); + osMutexRelease(ina_lock); + return (result_current*10) * result_voltage; +} diff --git a/Application/BSP/BSP_INA.h b/Application/BSP/BSP_INA.h new file mode 100644 index 0000000..8af84d5 --- /dev/null +++ b/Application/BSP/BSP_INA.h @@ -0,0 +1,18 @@ +#pragma once +/** +* @file BSP_INA.h +* @brief Driver for the BSP INA219 module +* +* This file provides a driver for the BSP INA219 module, which is used to measure voltage and current values. +* The driver includes functions for initializing the module, reading the current and voltage values, and calculating the power value. +* All of these functions are wrapped in a mutex lock to ensure consistent reading of the values. +*/ + +#include + + +void BSP_INA_Init(void); + +uint16_t BSP_INA_Voltage(); +uint16_t BSP_INA_Current(); +uint32_t BSP_INA_Power(); diff --git a/Application/BSP/BSP_POWER.h b/Application/BSP/BSP_POWER.h new file mode 100644 index 0000000..b3d1885 --- /dev/null +++ b/Application/BSP/BSP_POWER.h @@ -0,0 +1,4 @@ +// Driver for standby and sleep managment +// Timer for automatic standby +// Wakeup Pin Setting +// also shutdown procedure \ No newline at end of file diff --git a/Application/BSP/BSP_SDLogger.h b/Application/BSP/BSP_SDLogger.h new file mode 100644 index 0000000..5d11b5d --- /dev/null +++ b/Application/BSP/BSP_SDLogger.h @@ -0,0 +1,4 @@ +// SD logger steam is logged to sd card +// buffernd logger collect logs until some amount of data is collected. +// needs to be flushed before shutdown +// used with ULOG \ No newline at end of file diff --git a/Application/BSP/CMakeLists.txt b/Application/BSP/CMakeLists.txt new file mode 100644 index 0000000..14ee8b5 --- /dev/null +++ b/Application/BSP/CMakeLists.txt @@ -0,0 +1,8 @@ + +add_library(BSP STATIC +BSP_EE24.c +BSP_INA.c +) + +target_include_directories(BSP PUBLIC ./) +target_link_libraries(BSP PRIVATE EE24 INA219) diff --git a/Application/CMakeLists.txt b/Application/CMakeLists.txt index f22926f..e6f5431 100644 --- a/Application/CMakeLists.txt +++ b/Application/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(Tasks) add_subdirectory(CLS_BSP) -add_subdirectory(CLS) \ No newline at end of file +add_subdirectory(CLS) +add_subdirectory(BSP) \ No newline at end of file diff --git a/Application/Tasks/PowerMonitor.Task.h b/Application/Tasks/PowerMonitor.Task.h new file mode 100644 index 0000000..155a74e --- /dev/null +++ b/Application/Tasks/PowerMonitor.Task.h @@ -0,0 +1,2 @@ +// Task to Monitor the Power Usage of the CLS system +// \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 39a53ee..da46c53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,7 @@ include_directories(${PROJECT_BINARY_DIR}) add_executable(${CMAKE_PROJECT_NAME}) target_sources(${CMAKE_PROJECT_NAME} PUBLIC ${sources_SRCS}) -target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tasks CLS CLS_BSP ulog) +target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tasks CLS CLS_BSP BSP EE24 INA219 ulog) #target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC PROTOS) target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC uart_driver) #target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC lwrb) diff --git a/Core/Src/freertos.c b/Core/Src/freertos.c index 2bcd50e..b78e7cc 100644 --- a/Core/Src/freertos.c +++ b/Core/Src/freertos.c @@ -32,6 +32,8 @@ #include "ulog.h" #include "stdio.h" #include "tim.h" +#include "BSP_EE24.h" +#include "BSP_INA.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -57,7 +59,7 @@ osThreadId_t defaultTaskHandle; const osThreadAttr_t defaultTask_attributes = { .name = "defaultTask", - .stack_size = 128 * 4, + .stack_size = 512 * 4, .priority = (osPriority_t) osPriorityNormal, }; @@ -175,11 +177,28 @@ void StartDefaultTask(void *argument) uint8_t light_data[2] = {0}; + BSP_EE24_Init(); + + BSP_INA_Init(); + + char INA_LOG[72]; + /* Infinite loop */ for(;;) { osDelay(1000); + uint16_t current = BSP_INA_Current()*10; + uint16_t voltage = BSP_INA_Voltage(); + uint32_t power = (current * voltage)/1000; // milli watts + float power_W = (float)power/1000.0; + float voltage_V =(float) voltage /1000.0; + + + + snprintf(INA_LOG, sizeof(INA_LOG),"Voltage[mV] %.2f Current[mA] %d P[W]: %.2f", voltage_V, current, power_W); + ULOG_INFO(INA_LOG); + light_data[0]++; light_data[1] = (light_data[0]/10)%4; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 06cc4d2..0acd65e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,4 +1,8 @@ add_subdirectory(lwrb) add_subdirectory(uart_driver) add_subdirectory(nanopb) -add_subdirectory(ulog) \ No newline at end of file +add_subdirectory(ulog) +add_subdirectory(ina219) + +add_library(EE24 STATIC "ee24/ee24.c") +target_include_directories(EE24 PUBLIC "ee24") \ No newline at end of file diff --git a/lib/ee24 b/lib/ee24 new file mode 160000 index 0000000..4a2d795 --- /dev/null +++ b/lib/ee24 @@ -0,0 +1 @@ +Subproject commit 4a2d7958fcccfc64a79850f3234968a115e622d6 diff --git a/lib/ina219/CMakeLists.txt b/lib/ina219/CMakeLists.txt new file mode 100644 index 0000000..7243f38 --- /dev/null +++ b/lib/ina219/CMakeLists.txt @@ -0,0 +1,7 @@ + +add_library(INA219 STATIC +"INA219.c" +"INA219.h" +) + +target_include_directories(INA219 PUBLIC ./) \ No newline at end of file diff --git a/lib/ina219/INA219.c b/lib/ina219/INA219.c new file mode 100644 index 0000000..c6d6f2a --- /dev/null +++ b/lib/ina219/INA219.c @@ -0,0 +1,179 @@ +/* + * INA219.c + * + * Created on: Dec 30, 2020 + * Author: Piotr Smolen + */ + +#include "main.h" +#include "INA219.h" + +uint16_t ina219_calibrationValue =0; +int16_t ina219_currentDivider_mA =0; +int16_t ina219_powerMultiplier_mW=0; + +uint16_t Read16(INA219_t *ina219, uint8_t Register) +{ + uint8_t Value[2] = {0}; + + HAL_I2C_Mem_Read(ina219->ina219_i2c, (ina219->Address<<1), Register, 1, Value, 2, 1000); + + return ((Value[0] << 8) | Value[1]); +} + + +void Write16(INA219_t *ina219, uint8_t Register, uint16_t Value) +{ + uint8_t addr[2]; + addr[0] = (Value >> 8) & 0xff; // upper byte + addr[1] = (Value >> 0) & 0xff; // lower byte + HAL_I2C_Mem_Write(ina219->ina219_i2c, (ina219->Address<<1), Register, 1, (uint8_t*)addr, 2, 1000); +} + +uint16_t INA219_ReadBusVoltage(INA219_t *ina219) +{ + uint16_t result = Read16(ina219, INA219_REG_BUSVOLTAGE); + + return ((result >> 3 ) * 4); + +} + +int16_t INA219_ReadCurrent_raw(INA219_t *ina219) +{ + int16_t result = Read16(ina219, INA219_REG_CURRENT); + + return (result ); +} + +int16_t INA219_ReadCurrent(INA219_t *ina219) +{ + int16_t result = INA219_ReadCurrent_raw(ina219); + + return (result / ina219_currentDivider_mA ); +} + +uint16_t INA219_ReadShuntVolage(INA219_t *ina219) +{ + uint16_t result = Read16(ina219, INA219_REG_SHUNTVOLTAGE); + + return (result * 0.01 ); +} + +void INA219_Reset(INA219_t *ina219) +{ + Write16(ina219, INA219_REG_CONFIG, INA219_CONFIG_RESET); + HAL_Delay(1); +} + +void INA219_setCalibration(INA219_t *ina219, uint16_t CalibrationData) +{ + Write16(ina219, INA219_REG_CALIBRATION, CalibrationData); +} + +uint16_t INA219_getConfig(INA219_t *ina219) +{ + uint16_t result = Read16(ina219, INA219_REG_CONFIG); + return result; +} + +void INA219_setConfig(INA219_t *ina219, uint16_t Config) +{ + Write16(ina219, INA219_REG_CONFIG, Config); +} + +void INA219_setCalibration_32V_2A(INA219_t *ina219) +{ + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + + ina219_calibrationValue = 4096; + ina219_currentDivider_mA = 10; // Current LSB = 100uA per bit (1000/100 = 10) + ina219_powerMultiplier_mW = 2; // Power LSB = 1mW per bit (2/1) + + INA219_setCalibration(ina219, ina219_calibrationValue); + INA219_setConfig(ina219, config); +} + +void INA219_setCalibration_32V_1A(INA219_t *ina219) +{ + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + + ina219_calibrationValue = 10240; + ina219_currentDivider_mA = 25; // Current LSB = 40uA per bit (1000/40 = 25) + ina219_powerMultiplier_mW = 0.8f; // Power LSB = 800uW per bit + + INA219_setCalibration(ina219, ina219_calibrationValue); + INA219_setConfig(ina219, config); +} + +void INA219_setCalibration_16V_400mA(INA219_t *ina219) +{ + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_16V | + INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + + ina219_calibrationValue = 8192; + ina219_currentDivider_mA = 20; // Current LSB = 50uA per bit (1000/50 = 20) + ina219_powerMultiplier_mW = 1.0f; // Power LSB = 1mW per bit + + INA219_setCalibration(ina219, ina219_calibrationValue); + INA219_setConfig(ina219, config); +} + +void INA219_setPowerMode(INA219_t *ina219, uint8_t Mode) +{ + uint16_t config = INA219_getConfig(ina219); + + switch (Mode) { + case INA219_CONFIG_MODE_POWERDOWN: + config = (config & ~INA219_CONFIG_MODE_MASK) | (INA219_CONFIG_MODE_POWERDOWN & INA219_CONFIG_MODE_MASK); + INA219_setConfig(ina219, config); + break; + + case INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED: + config = (config & ~INA219_CONFIG_MODE_MASK) | (INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED & INA219_CONFIG_MODE_MASK); + INA219_setConfig(ina219, config); + break; + + case INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS: + config = (config & ~INA219_CONFIG_MODE_MASK) | (INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS & INA219_CONFIG_MODE_MASK); + INA219_setConfig(ina219, config); + break; + + case INA219_CONFIG_MODE_ADCOFF: + config = (config & ~INA219_CONFIG_MODE_MASK) | (INA219_CONFIG_MODE_ADCOFF & INA219_CONFIG_MODE_MASK); + INA219_setConfig(ina219, config); + break; + } +} + +uint8_t INA219_Init(INA219_t *ina219, I2C_HandleTypeDef *i2c, uint8_t Address) +{ + ina219->ina219_i2c = i2c; + ina219->Address = Address; + + ina219_currentDivider_mA = 0; + ina219_powerMultiplier_mW = 0; + + uint8_t ina219_isReady = HAL_I2C_IsDeviceReady(i2c, (Address << 1), 3, 2); + + if(ina219_isReady == HAL_OK) + { + + INA219_Reset(ina219); + INA219_setCalibration_32V_2A(ina219); + + return 1; + } + + else + { + return 0; + } +} diff --git a/lib/ina219/INA219.h b/lib/ina219/INA219.h new file mode 100644 index 0000000..a89f59f --- /dev/null +++ b/lib/ina219/INA219.h @@ -0,0 +1,97 @@ +/* + * INA219.h + * + * Created on: Dec 30, 2020 + * Author: Piotr Smolen + */ + +#ifndef INC_INA219_H_ +#define INC_INA219_H_ + +#define INA219_ADDRESS (0x40) + +// +// Registers +// +#define INA219_REG_CONFIG (0x00) +#define INA219_REG_SHUNTVOLTAGE (0x01) +#define INA219_REG_BUSVOLTAGE (0x02) +#define INA219_REG_POWER (0x03) +#define INA219_REG_CURRENT (0x04) +#define INA219_REG_CALIBRATION (0x05) +// +#define INA219_CONFIG_RESET (0x8000) +// +#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) // 0-16V Range +#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) // 0-32V Range + +#define INA219_CONFIG_GAIN_1_40MV (0x0000) // Gain 1, 40mV Range +#define INA219_CONFIG_GAIN_2_80MV (0x0800) // Gain 2, 80mV Range +#define INA219_CONFIG_GAIN_4_160MV (0x1000) // Gain 4, 160mV Range +#define INA219_CONFIG_GAIN_8_320MV (0x1800) // Gain 8, 320mV Range + +#define INA219_CONFIG_BADCRES_9BIT (0x0000) // 9-bit bus res = 0..511 +#define INA219_CONFIG_BADCRES_10BIT (0x0080) // 10-bit bus res = 0..1023 +#define INA219_CONFIG_BADCRES_11BIT (0x0100) // 11-bit bus res = 0..2047 +#define INA219_CONFIG_BADCRES_12BIT (0x0180) // 12-bit bus res = 0..4097 +#define INA219_CONFIG_BADCRES_12BIT_2S_1060US (0x0480) // 2 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_4S_2130US (0x0500) // 4 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_8S_4260US (0x0580) // 8 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_16S_8510US (0x0600) // 16 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_32S_17MS (0x0680) // 32 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_64S_34MS (0x0700) // 64 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_128S_69MS (0x0780) // 128 x 12-bit bus samples averaged together + +#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) // 1 x 9-bit shunt sample +#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) // 1 x 10-bit shunt sample +#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) // 1 x 11-bit shunt sample +#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) // 1 x 12-bit shunt sample +#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) // 2 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) // 4 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) // 8 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) // 16 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) // 32 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) // 64 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) // 128 x 12-bit shunt samples averaged together +// +#define INA219_CONFIG_MODE_MASK (0x07) +#define INA219_CONFIG_MODE_POWERDOWN 0x00 /**< power down */ +#define INA219_CONFIG_MODE_SVOLT_TRIGGERED 0x01 /**< shunt voltage triggered */ +#define INA219_CONFIG_MODE_BVOLT_TRIGGERED 0x02 /**< bus voltage triggered */ +#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED 0x03 /**< shunt and bus voltage triggered */ +#define INA219_CONFIG_MODE_ADCOFF 0x04 /**< ADC off */ +#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS 0x05 /**< shunt voltage continuous */ +#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS 0x06 /**< bus voltage continuous */ +#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS 0x07 + +typedef struct +{ + I2C_HandleTypeDef *ina219_i2c; + uint8_t Address; +} INA219_t; + +extern uint16_t ina219_calibrationValue; +extern int16_t ina219_currentDivider_mA; +extern int16_t ina219_powerMultiplier_mW; + +uint8_t INA219_Init(INA219_t *ina219, I2C_HandleTypeDef *i2c, uint8_t Address); +uint16_t INA219_ReadBusVoltage(INA219_t *ina219); +int16_t INA219_ReadCurrent(INA219_t *ina219); +int16_t INA219_ReadCurrent_raw(INA219_t *ina219); +uint16_t INA219_ReadShuntVolage(INA219_t *ina219); + +void INA219_Reset(INA219_t *ina219); +void INA219_setCalibration(INA219_t *ina219, uint16_t CalibrationData); +uint16_t INA219_getConfig(INA219_t *ina219); +void INA219_setConfig(INA219_t *ina219, uint16_t Config); +void INA219_setCalibration_32V_2A(INA219_t *ina219); +void INA219_setCalibration_32V_1A(INA219_t *ina219); +void INA219_setCalibration_16V_400mA(INA219_t *ina219); +void INA219_setPowerMode(INA219_t *ina219, uint8_t Mode); + +uint16_t Read16(INA219_t *ina219, uint8_t Register); +void Write16(INA219_t *ina219, uint8_t Register, uint16_t Value); + + + +#endif /* INC_INA219_H_ */