Hi,
I'm working on a custom board with an nRF52840 MCU and a MAX17260 fuel gauge IC interfaced via I2C. The goal is to read the voltage of a battery using the MAX17260. I've verified that my I2C communication is functional, as I'm able to read default values correctly from several registers, such as the DesignCap Register (0x18) which gives output 3000(0xbb8) which is correct as per the datasheet. I attempted to read the MAX1726X_VCELL_REG register (0x09) value with and without any prior configuration of the fuel guage IC(max17260), but the outcome remains the same. I suspect there’s a specific calculation or conversion process required to interpret the read data correctly, but I’m not sure what that is.
Additional Information:
- I’ve verified the I2C communication and the register address.
- I have tried reading the voltage from the MAX1726X_VCELL_REG register (0x09).and applying the formula read_voltage
* 0.0078125 (46613*0.000078125 = 3.641)
, but When I measured the voltage using multimeter across the Vin and GND pin of the battery, it displays 4.02 Volt .this doesn’t match with the read data from the i2c./** @file * @defgroup tw_sensor_example main.c * @{ * @ingroup nrf_twi_example * @brief TWI Sensor Example main file. * * This file contains the source code for a sample application using TWI. * */ #include <stdio.h> #include <string.h> #include "app_error.h" #include "app_util_platform.h" #include "boards.h" #include "nrf_delay.h" #include "nrf_drv_twi.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" /* TWI instance ID. */ #define TWI_INSTANCE_ID 0 #define MAX17260_ADDRESS 0x36 #define MAX1726X_STATUS_REG 0x00 #define MAX1726X_VALRTTH_REG 0x01 #define MAX1726X_TALRTTH_REG 0x02 #define MAX1726X_SALRTTH_REG 0x03 #define MAX1726X_ATRATE_REG 0x04 #define MAX1726X_REPCAP_REG 0x05 #define MAX1726X_REPSOC_REG 0x06 #define MAX1726X_AGE_REG 0x07 #define MAX1726X_TEMP_REG 0x08 #define MAX1726X_VCELL_REG 0x09 #define MAX1726X_CURRENT_REG 0x0A #define MAX1726X_AVGCURRENT_REG 0x0B #define MAX1726X_QRESIDUAL_REG 0x0C #define MAX1726X_MIXSOC_REG 0x0D #define MAX1726X_AVSOC_REG 0x0E #define MAX1726X_REMCAP_REG 0x0F #define MAX1726X_FULLCAPREP_REG 0x10 #define MAX1726X_TTE_REG 0X11 #define MAX1726X_QRTABLE00_REG 0x12 #define MAX1726X_FULLSOCTHR_REG 0x13 #define MAX1726X_RCELL_REG 0x14 // reserved for 0x15 #define MAX1726X_AVGTA_REG 0x16 #define MAX1726X_CYCLES_REG 0x17 #define MAX1726X_DESIGNCAP_REG 0x18 #define MAX1726X_AVGVCELL_REG 0x19 #define MAX1726X_MAXMINTEMP_REG 0x1A #define MAX1726X_MAXMINVOLT_REG 0x1B #define MAX1726X_MAXMINCURR_REG 0x1C #define MAX1726X_CONFIG_REG 0x1D #define MAX1726X_ICHGTERM_REG 0x1E #define MAX1726X_AVCAP_REG 0x1F #define MAX1726X_TTF_REG 0X20 #define MAX1726X_DEVNAME_REG 0x21 #define MAX1726X_QRTABLE10_REG 0x22 #define MAX1726X_FULLCAPNOM_REG 0x23 // reserved for 0x24 // reserved for 0x25 // reserved for 0x26 #define MAX1726X_AIN_REG 0x27 #define MAX1726X_LEARNCFG_REG 0x28 #define MAX1726X_FLITERCFG_REG 0x29 #define MAX1726X_RELAXCFG_REG 0x2A #define MAX1726X_MISCCFG_REG 0x2B #define MAX1726X_TGAIN_REG 0x2C #define MAX1726X_TOFF_REG 0x2D #define MAX1726X_CGAIN_REG 0x2E #define MAX1726X_COFF_REG 0x2F // reserved for 0x30 // reserved for 0x31 #define MAX1726X_QRTABLE20_REG 0x32 // reserved for 0x33 #define MAX1726X_DIETEMP_REG 0x34 #define MAX1726X_FULLCAP_REG 0x35 // reserved for 0x36 // reserved for 0x37 #define MAX1726X_RCOMP0_REG 0x38 #define MAX1726X_TEMPCO_REG 0x39 #define MAX1726X_VEMPTY_REG 0x3A // reserved for 0x3B // reserved for 0x3C #define MAX1726X_FSTAT_REG 0x3D #define MAX1726X_TIMER_REG 0x3E #define MAX1726X_SHDNTIMER_REG 0x3F // reserved for 0x40 // reserved for 0x41 #define MAX1726X_QRTABLE30_REG 0x42 #define MAX1726X_RGAIN_REG 0x43 // reserved for 0x44 #define MAX1726X_DQACC_REG 0x45 #define MAX1726X_DPACC_REG 0x46 // reserved for 0x47 // reserved for 0x48 #define MAX1726X_CONVGCFG_REG 0x49 #define MAX1726X_VFREMCAP_REG 0x4A // reserved for 0x4B // reserved for 0x4C #define MAX1726X_QH_REG 0x4D // reserved for 0x4E // reserved for 0x4F #define MAX1726X_MODELDATA0_START_REG 0x80 #define MAX1726X_MODELDATA1_START_REG 0x90 #define MAX1726X_STATUS2_REG 0xB0 #define MAX1726X_POWER_REG 0xB1 #define MAX1726X_ID_USERMEM2_REG 0xB2 #define MAX1726X_AVGPOWER_REG 0xB3 #define MAX1726X_IALRTTH_REG 0xB4 #define MAX1726X_TTFCFG_REG 0xB5 #define MAX1726X_CVMIXCAP_REG 0xB6 #define MAX1726X_CVHALFIME_REG 0xB7 #define MAX1726X_CGTEMPCO_REG 0xB8 #define MAX1726X_CURVE_REG 0xB9 #define MAX1726X_HIBCFG_REG 0xBA #define MAX1726X_CONFIG2_REG 0xBB #define MAX1726X_VRIPPLE_REG 0xBC #define MAX1726X_RIPPLECFG_REG 0xBD #define MAX1726X_TIMERH_REG 0xBE // reserved for 0xBF #define MAX1726X_RSENSE_USERMEM3_REG 0xD0 #define MAX1726X_SCOCVLIM_REG 0xD1 #define MAX1726X_VGAIN_REG 0xD2 #define MAX1726X_SOCHOLD_REG 0xD3 #define MAX1726X_MAXPEAKPOWER_REG 0xD4 #define MAX1726X_SUSPEAKPOWER_REG 0xD5 #define MAX1726X_PACKRESISTANCE_REG 0xD6 #define MAX1726X_SYSRESISTANCE_REG 0xD7 #define MAX1726X_MINSYSVOLTAGE_REG 0xD8 #define MAX1726X_MPPCURRENT_REG 0xD9 #define MAX1726X_SPPCURRENT_REG 0xDA #define MAX1726X_MODELCFG_REG 0xDB #define MAX1726X_ATQRESIDUAL_REG 0xDC #define MAX1726X_ATTTE_REG 0xDD #define MAX1726X_ATAVSOC_REG 0xDE #define MAX1726X_ATAVCAP_REG 0xDF #define MAX1726X_SERIALNUM0 0xD4 #define MAX1726X_SERIALNUM1 0xD5 #define MAX1726X_SERIALNUM2 0xD9 #define MAX1726X_SERIALNUM3 0xDA #define MAX1726X_SERIALNUM4 0xDC #define MAX1726X_SERIALNUM5 0xDD #define MAX1726X_SERIALNUM6 0xDE #define MAX1726X_SERIALNUM7 0xDF #define MAX1726X_VFOCV_REG 0xFB #define MAX1726X_VFSOC_REG 0xFF /* Indicates if operation on TWI has ended. */ static volatile bool m_xfer_done = false; /* TWI instance. */ static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID); /* Monitor Fuel Gauge Structure */ typedef struct Fuel_Gauge_Monitor { uint16_t voltage; uint16_t design_cap; }Fuel_Gauge_Monitor; #define SWAP_BYTE(data) ((data << 8) & 0xff00) | ((data >> 8) & 0x00ff) typedef int (*interface_read_fn)(uint8_t device_addr, uint8_t* data, uint8_t len); typedef int (*interface_write_fn)(uint8_t device_addr, uint8_t const* data, uint8_t len); /* Fuel gauge Interface Structure */ typedef struct Fuel_Gauge_Interface{ interface_read_fn MAX17260_Read_Data; interface_write_fn MAX17260_Write_Data; }Fuel_Gauge_Interface; /* ----------------------------- Global Variables -------------------------------------*/ Fuel_Gauge_Interface gInterface = {0}; /** * @brief TWI events handler. */ static void twi_handler(nrf_drv_twi_evt_t const *p_event, void *p_context) { switch(p_event->type) { case NRF_DRV_TWI_EVT_DONE : // NRF_LOG_INFO("NRF_DRV_TWI_EVT_DONE\r\n"); m_xfer_done = true; break; case NRF_DRV_TWI_EVT_ADDRESS_NACK: // NRF_LOG_INFO("NRF_DRV_TWI_EVT_ADDRESS_NACK\r\n"); break; case NRF_DRV_TWI_EVT_DATA_NACK: // NRF_LOG_INFO("NRF_DRV_TWI_EVT_DATA_NACK\r\n"); break; default : // NRF_LOG_INFO("default\r\n"); break; } } /** * @brief UART initialization. */ void twi_init (void) { ret_code_t err_code; const nrf_drv_twi_config_t twi_lm75b_config = { .scl = 4, //ARDUINO_SCL_PIN, .sda = 5, // ARDUINO_SDA_PIN, .frequency = NRF_DRV_TWI_FREQ_400K, .interrupt_priority = APP_IRQ_PRIORITY_HIGH, .clear_bus_init = false }; err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, twi_handler, NULL); APP_ERROR_CHECK(err_code); nrf_drv_twi_enable(&m_twi); } int I2C_Write_Data(uint8_t device_addr, uint8_t *data, uint8_t len) { ret_code_t err_code; // Write register address to the MAX17260 err_code = nrf_drv_twi_tx(&m_twi, MAX17260_ADDRESS, &device_addr, 1, true); nrf_delay_ms(100); APP_ERROR_CHECK(err_code); //while (m_xfer_done == false); // Read register data err_code = nrf_drv_twi_rx(&m_twi, MAX17260_ADDRESS, data, 2); nrf_delay_ms(100); NRF_LOG_FLUSH(); return NRF_SUCCESS; } int I2C_Read_Data(uint8_t device_addr, uint8_t *data, uint8_t len) { ret_code_t err_code; err_code = nrf_drv_twi_tx(&m_twi, MAX17260_ADDRESS, &device_addr, 1, true); nrf_delay_ms(100); APP_ERROR_CHECK(err_code); err_code = nrf_drv_twi_rx(&m_twi, MAX17260_ADDRESS, data, len); APP_ERROR_CHECK(err_code); nrf_delay_ms(100); //NRF_LOG_FLUSH(); return NRF_SUCCESS; } /** * @brief MAX17260_Init. * This function intialize interface of fuel gauge. * @param[in] Structure of interface functions. * @return void */ void MAX17260_Init(Fuel_Gauge_Interface interface) { memcpy(&gInterface, &interface, sizeof(Fuel_Gauge_Interface)); } /** * @brief MAX17260_Read_Design_Cap. * This function read initial design capacity. * @param[out] pointer to store read design capacity * @return NRF_SUCCESS on success, otherwise an error code. */ ret_code_t MAX17260_Read_Design_Cap(uint8_t reg, uint16_t* data) { ret_code_t ret = NRF_SUCCESS; ret = gInterface.MAX17260_Read_Data(reg, (uint8_t*)data, sizeof(uint16_t)); if (ret != NRF_SUCCESS){ return ret; } return NRF_SUCCESS; } /** * @brief MAX17260_Read_Voltage. * This function read voltage. * @param[out] pointer to store read voltage * @return NRF_SUCCESS on success, otherwise an error code. */ ret_code_t MAX17260_Read_Voltage(uint8_t reg, uint16_t* data) { ret_code_t ret = NRF_SUCCESS; ret = gInterface.MAX17260_Read_Data(reg, (uint8_t*)data, sizeof(uint16_t)); if (ret != NRF_SUCCESS){ return ret; } return NRF_SUCCESS; } /** * @brief MAX17260_Monitor. * This function read all monitor parameter of battery. * @param[out] Fuel Gauge Monitor parameter structure to store all read value * @return NRF_SUCCESS on success, otherwise an error code. */ ret_code_t MAX17260_Monitor(Fuel_Gauge_Monitor* monitor) { ret_code_t ret = NRF_SUCCESS; ret = MAX17260_Read_Voltage(MAX1726X_VCELL_REG, &monitor->voltage); if (ret != NRF_SUCCESS) { return ret; } ret = MAX17260_Read_Design_Cap(MAX1726X_DESIGNCAP_REG, &monitor->design_cap); if (ret != NRF_SUCCESS) { return ret; } NRF_LOG_INFO("----------------------------------------------------"); NRF_LOG_INFO("Voltage : %d : %x", monitor->voltage); NRF_LOG_INFO("Design cap : %d : %x", monitor->design_cap); NRF_LOG_INFO("----------------------------------------------------"); return NRF_SUCCESS; } /** * @brief Function for main application entry. */ int main(void) { uint8_t rc; Fuel_Gauge_Monitor monitor; APP_ERROR_CHECK(NRF_LOG_INIT(NULL)); NRF_LOG_DEFAULT_BACKENDS_INIT(); NRF_LOG_INFO("TWI sensor example started."); NRF_LOG_FLUSH(); twi_init(); NRF_LOG_INFO("********************* MAX17260_Init *************************\r\n"); Fuel_Gauge_Interface interface = {0}; interface.MAX17260_Read_Data = I2C_Read_Data; interface.MAX17260_Write_Data = I2C_Write_Data; MAX17260_Init(interface); rc = MAX17260_Monitor(&monitor); if (rc != NRF_SUCCESS) { NRF_LOG_INFO("Failed to MAX17260_Monitor\r\n"); } while (true) { nrf_delay_ms(500); NRF_LOG_FLUSH(); } }
Provide guidance on what might be going wrong? Any suggestions or insights would be greatly appreciated.
Thanks in advance!