Read a register of MAX17260 using TWI

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!

Parents
  • Hi!

    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)

    This looks correct to me. There is also the average voltage you can try to read (AvgVCell Register (19h))

    I see that in Zephyr, the max17262 sensor driver does several steps during initialization, but I'm not sure if that affects the voltage reading or not. 

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.5.99-ncs1/drivers/sensor/max17262/max17262.c#L223

  • Hi Sigurd,
    I have followed the initialization and configuration process as per attached document. https://www.analog.com/media/en/technical-documentation/user-guides/modelgauge-m5-host-side-software-implementation-guide.pdf
    I successfully read the design capacity register, which returns 3000 (0xbb8), matching the datasheet and confirming that my I2C read function is working correctly.
    As suggested I have read MAX1726X_AVGVCELL_REG register (0x19) returns 47600(47600 *0.000078125 = 3.718) as well as the MAX1726X_VCELL_REG voltage register (0x09) returns 47596 (47596 *0.000078125 = 3.718).

    Issue:
    Using a multimeter, the voltage across the Vin and GND pins of the battery measures 4.115V, still does not match the data read via I2C. same as previously discussed.

    /**
     * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @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
    
    #define BAT_DESIGN_CAPACITY 0xBB8         // 3000
    #define BAT_EMPTY_VOLTAGE 0xA561          // 3.3 emplty voltage and 3.88 Recovery voltage
    #define MODEL_CONFIG_VALUE 0x8400         // Model ID 0, Charge voltage higher than 4.2
    #define CHG_TERMINATION_CURRENT 0x0640    // 250mA
    
    /* 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 avg_voltage;
      uint16_t design_cap;
    } Fuel_Gauge_Monitor;
    
    typedef struct {
      uint16_t designcap;
      uint16_t ichgterm;
      uint16_t modelcfg;
      uint16_t vempty;
    } max1726x_ez_config_t;
    
    #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 Writes to a register and verifies the write operation by reading back the value.
     *
     * @param[in] reg_addr The register address to write to.
     * @param[in] reg_data Pointer to the data to write.
     * @return 0 NRF_SUCCESS on success, otherwise an error code.
     */
    uint8_t MAX17260_Write_And_Verify_Reg(uint8_t reg_addr, uint16_t* reg_data) {
      uint8_t i2c_data[2];
      uint16_t readback_data;
      int8_t retry   = 3;
      ret_code_t ret = NRF_SUCCESS;
    
      while (retry > 0) {
        ret = gInterface.MAX17260_Write_Data(reg_addr, (uint8_t*)reg_data, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return 1;    // error
        }
    
        // Delay to ensure the write operation completes
        nrf_delay_ms(100);    // about 10ms
    
        // Read back the written register
        ret = gInterface.MAX17260_Read_Data(reg_addr, (uint8_t*)&readback_data, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return 1;    // error
        }
    
        NRF_LOG_INFO("Write and read back register: %d : %d", readback_data, *reg_data);
    
        // Verify the written data
        if (readback_data == (*reg_data)) {
          return 0;    // no error
        } else {
          retry--;
        }
      }
      return 1;    // error
    }
    
    /**
     * @brief Checks if a power-on reset (POR) has occurred.
     *
     * @return 0 if no power-on reset, 1 if power-on reset, or NRF_SUCCESS on success, otherwise an error code.
     */
    uint8_t MAX17260_Check_POR(void) {
      ret_code_t ret  = NRF_SUCCESS;
      uint16_t status = 0;
    
      ret = gInterface.MAX17260_Read_Data(MAX1726X_STATUS_REG, (uint8_t*)&status, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      if ((status & 0x0002) == 0x0000) {
        return 0;    // No power on reset
      } else {
        return 1;    // Power on reset
      }
    }
    
    /**
     * @brief Clears the power-on reset (POR) flag.
     *
     * @return 0 if successful, 1 if an error occurs.
     */
    uint8_t MAX17260_Clear_POR (void) {
      ret_code_t ret  = NRF_SUCCESS;
      uint16_t status = 0;
    
      ret = gInterface.MAX17260_Read_Data(MAX1726X_STATUS_REG, (uint8_t*)&status, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return 1;    // error
      }
    
      status &= 0xFFFD;    // Clear the POR flag
    
      return MAX17260_Write_And_Verify_Reg(MAX1726X_STATUS_REG, &status);
    }
    
    /**
     * @brief Waits for the data to be ready after power up.
     */
    void MAX17260_Wait_Data_Ready_After_Power_Up(void) {
      ret_code_t ret  = NRF_SUCCESS;
      uint16_t status = 0;
    
      ret = gInterface.MAX17260_Read_Data(MAX1726X_FSTAT_REG, (uint8_t*)&status, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return;    // error, handle as needed
      }
    
      while ((status & 0x0001) == 0x0001) {
        nrf_delay_ms(100);    // about 100ms
        ret = gInterface.MAX17260_Read_Data(MAX1726X_FSTAT_REG, (uint8_t*)&status, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return;    // error, handle as needed
        }
      }
    }
    
    /**
     * @brief Stores the original Hibernate Configuration value.
     *
     * @param[out] hibernate_config Pointer to the variable where the Hibernate Configuration value will be stored.
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Store_Original_HibCFG(uint16_t* hibernate_config) {
      ret_code_t ret = gInterface.MAX17260_Read_Data(MAX1726X_HIBCFG_REG, (uint8_t*)hibernate_config, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Exits Hibernate mode.
     *
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Exit_Hibernate_Mode(void) {
      ret_code_t ret    = NRF_SUCCESS;
      uint16_t tempdata = 0x0090;
    
      ret = gInterface.MAX17260_Write_Data(0x60, (uint8_t*)&tempdata, sizeof(tempdata));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      tempdata = 0x0000;
      ret      = gInterface.MAX17260_Write_Data(MAX1726X_HIBCFG_REG, (uint8_t*)&tempdata, sizeof(tempdata));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(0x60, (uint8_t*)&tempdata, sizeof(tempdata));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Writes the configuration settings to the appropriate registers.
     *
     * @param[in] config Pointer to the configuration structure.
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Write_Configuration(const max1726x_ez_config_t* config) {
      ret_code_t ret = NRF_SUCCESS;
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_DESIGNCAP_REG, (uint8_t*)&config->designcap, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_ICHGTERM_REG, (uint8_t*)&config->ichgterm, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_VEMPTY_REG, (uint8_t*)&config->vempty, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_MODELCFG_REG, (uint8_t*)&config->modelcfg, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Polls the ModelCFG.Refresh bit and waits until it is cleared.
     *
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Wait_For_ModelCFG_Refresh(void) {
      ret_code_t ret        = NRF_SUCCESS;
      uint16_t model_config = 0;
    
      do {
        ret = gInterface.MAX17260_Read_Data(MAX1726X_MODELCFG_REG, (uint8_t*)&model_config, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return ret;
        }
        nrf_delay_ms(100);    // about 10ms
      } while ((model_config & 0x8000) == 0x8000);
    
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Restores the original Hibernate Configuration value.
     *
     * @param[in] hibernate_config Pointer to the variable containing the original Hibernate Configuration value.
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Restore_Original_HibCFG(const uint16_t* hibernate_config) {
      ret_code_t ret = gInterface.MAX17260_Write_Data(MAX1726X_HIBCFG_REG, (uint8_t*)hibernate_config, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Initializes the MAX17260 configuration.
     *
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Initialize_Config(void) {
      ret_code_t ret            = NRF_SUCCESS;
      uint16_t hibernate_config = 0;
      max1726x_ez_config_t max1726x_ez_config;
    
      max1726x_ez_config.designcap = BAT_DESIGN_CAPACITY;
      max1726x_ez_config.ichgterm  = CHG_TERMINATION_CURRENT;
      max1726x_ez_config.modelcfg  = MODEL_CONFIG_VALUE;
      max1726x_ez_config.vempty    = BAT_EMPTY_VOLTAGE;
    
      ret = MAX17260_Store_Original_HibCFG(&hibernate_config);
      ret += MAX17260_Exit_Hibernate_Mode();
      ret += MAX17260_Write_Configuration(&max1726x_ez_config);
      ret += MAX17260_Wait_For_ModelCFG_Refresh();
      ret += MAX17260_Restore_Original_HibCFG(&hibernate_config);
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      return NRF_SUCCESS;
    }
    
    /**
     * @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_Read_Average_Voltage.
     *              This function read voltage.
     * @param[out]  pointer to store read average voltage
     * @return      NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Read_Average_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_Average_Voltage(MAX1726X_AVGVCELL_REG, &monitor->avg_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("Avg Voltage: %d  : %x", monitor->avg_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);
    
      MAX17260_Check_POR();
      MAX17260_Wait_Data_Ready_After_Power_Up();
      MAX17260_Initialize_Config();
      MAX17260_Clear_POR();
    
      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();
      }
    }
    

    Could there be any other reason ? Should I look into any other factors that might be affecting the readings?

    Thanks in advance!

Reply
  • Hi Sigurd,
    I have followed the initialization and configuration process as per attached document. https://www.analog.com/media/en/technical-documentation/user-guides/modelgauge-m5-host-side-software-implementation-guide.pdf
    I successfully read the design capacity register, which returns 3000 (0xbb8), matching the datasheet and confirming that my I2C read function is working correctly.
    As suggested I have read MAX1726X_AVGVCELL_REG register (0x19) returns 47600(47600 *0.000078125 = 3.718) as well as the MAX1726X_VCELL_REG voltage register (0x09) returns 47596 (47596 *0.000078125 = 3.718).

    Issue:
    Using a multimeter, the voltage across the Vin and GND pins of the battery measures 4.115V, still does not match the data read via I2C. same as previously discussed.

    /**
     * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @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
    
    #define BAT_DESIGN_CAPACITY 0xBB8         // 3000
    #define BAT_EMPTY_VOLTAGE 0xA561          // 3.3 emplty voltage and 3.88 Recovery voltage
    #define MODEL_CONFIG_VALUE 0x8400         // Model ID 0, Charge voltage higher than 4.2
    #define CHG_TERMINATION_CURRENT 0x0640    // 250mA
    
    /* 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 avg_voltage;
      uint16_t design_cap;
    } Fuel_Gauge_Monitor;
    
    typedef struct {
      uint16_t designcap;
      uint16_t ichgterm;
      uint16_t modelcfg;
      uint16_t vempty;
    } max1726x_ez_config_t;
    
    #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 Writes to a register and verifies the write operation by reading back the value.
     *
     * @param[in] reg_addr The register address to write to.
     * @param[in] reg_data Pointer to the data to write.
     * @return 0 NRF_SUCCESS on success, otherwise an error code.
     */
    uint8_t MAX17260_Write_And_Verify_Reg(uint8_t reg_addr, uint16_t* reg_data) {
      uint8_t i2c_data[2];
      uint16_t readback_data;
      int8_t retry   = 3;
      ret_code_t ret = NRF_SUCCESS;
    
      while (retry > 0) {
        ret = gInterface.MAX17260_Write_Data(reg_addr, (uint8_t*)reg_data, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return 1;    // error
        }
    
        // Delay to ensure the write operation completes
        nrf_delay_ms(100);    // about 10ms
    
        // Read back the written register
        ret = gInterface.MAX17260_Read_Data(reg_addr, (uint8_t*)&readback_data, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return 1;    // error
        }
    
        NRF_LOG_INFO("Write and read back register: %d : %d", readback_data, *reg_data);
    
        // Verify the written data
        if (readback_data == (*reg_data)) {
          return 0;    // no error
        } else {
          retry--;
        }
      }
      return 1;    // error
    }
    
    /**
     * @brief Checks if a power-on reset (POR) has occurred.
     *
     * @return 0 if no power-on reset, 1 if power-on reset, or NRF_SUCCESS on success, otherwise an error code.
     */
    uint8_t MAX17260_Check_POR(void) {
      ret_code_t ret  = NRF_SUCCESS;
      uint16_t status = 0;
    
      ret = gInterface.MAX17260_Read_Data(MAX1726X_STATUS_REG, (uint8_t*)&status, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      if ((status & 0x0002) == 0x0000) {
        return 0;    // No power on reset
      } else {
        return 1;    // Power on reset
      }
    }
    
    /**
     * @brief Clears the power-on reset (POR) flag.
     *
     * @return 0 if successful, 1 if an error occurs.
     */
    uint8_t MAX17260_Clear_POR (void) {
      ret_code_t ret  = NRF_SUCCESS;
      uint16_t status = 0;
    
      ret = gInterface.MAX17260_Read_Data(MAX1726X_STATUS_REG, (uint8_t*)&status, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return 1;    // error
      }
    
      status &= 0xFFFD;    // Clear the POR flag
    
      return MAX17260_Write_And_Verify_Reg(MAX1726X_STATUS_REG, &status);
    }
    
    /**
     * @brief Waits for the data to be ready after power up.
     */
    void MAX17260_Wait_Data_Ready_After_Power_Up(void) {
      ret_code_t ret  = NRF_SUCCESS;
      uint16_t status = 0;
    
      ret = gInterface.MAX17260_Read_Data(MAX1726X_FSTAT_REG, (uint8_t*)&status, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return;    // error, handle as needed
      }
    
      while ((status & 0x0001) == 0x0001) {
        nrf_delay_ms(100);    // about 100ms
        ret = gInterface.MAX17260_Read_Data(MAX1726X_FSTAT_REG, (uint8_t*)&status, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return;    // error, handle as needed
        }
      }
    }
    
    /**
     * @brief Stores the original Hibernate Configuration value.
     *
     * @param[out] hibernate_config Pointer to the variable where the Hibernate Configuration value will be stored.
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Store_Original_HibCFG(uint16_t* hibernate_config) {
      ret_code_t ret = gInterface.MAX17260_Read_Data(MAX1726X_HIBCFG_REG, (uint8_t*)hibernate_config, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Exits Hibernate mode.
     *
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Exit_Hibernate_Mode(void) {
      ret_code_t ret    = NRF_SUCCESS;
      uint16_t tempdata = 0x0090;
    
      ret = gInterface.MAX17260_Write_Data(0x60, (uint8_t*)&tempdata, sizeof(tempdata));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      tempdata = 0x0000;
      ret      = gInterface.MAX17260_Write_Data(MAX1726X_HIBCFG_REG, (uint8_t*)&tempdata, sizeof(tempdata));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(0x60, (uint8_t*)&tempdata, sizeof(tempdata));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Writes the configuration settings to the appropriate registers.
     *
     * @param[in] config Pointer to the configuration structure.
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Write_Configuration(const max1726x_ez_config_t* config) {
      ret_code_t ret = NRF_SUCCESS;
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_DESIGNCAP_REG, (uint8_t*)&config->designcap, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_ICHGTERM_REG, (uint8_t*)&config->ichgterm, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_VEMPTY_REG, (uint8_t*)&config->vempty, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      ret = gInterface.MAX17260_Write_Data(MAX1726X_MODELCFG_REG, (uint8_t*)&config->modelcfg, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Polls the ModelCFG.Refresh bit and waits until it is cleared.
     *
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Wait_For_ModelCFG_Refresh(void) {
      ret_code_t ret        = NRF_SUCCESS;
      uint16_t model_config = 0;
    
      do {
        ret = gInterface.MAX17260_Read_Data(MAX1726X_MODELCFG_REG, (uint8_t*)&model_config, sizeof(uint16_t));
        if (ret != NRF_SUCCESS) {
          return ret;
        }
        nrf_delay_ms(100);    // about 10ms
      } while ((model_config & 0x8000) == 0x8000);
    
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Restores the original Hibernate Configuration value.
     *
     * @param[in] hibernate_config Pointer to the variable containing the original Hibernate Configuration value.
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Restore_Original_HibCFG(const uint16_t* hibernate_config) {
      ret_code_t ret = gInterface.MAX17260_Write_Data(MAX1726X_HIBCFG_REG, (uint8_t*)hibernate_config, sizeof(uint16_t));
      if (ret != NRF_SUCCESS) {
        return ret;
      }
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Initializes the MAX17260 configuration.
     *
     * @return NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Initialize_Config(void) {
      ret_code_t ret            = NRF_SUCCESS;
      uint16_t hibernate_config = 0;
      max1726x_ez_config_t max1726x_ez_config;
    
      max1726x_ez_config.designcap = BAT_DESIGN_CAPACITY;
      max1726x_ez_config.ichgterm  = CHG_TERMINATION_CURRENT;
      max1726x_ez_config.modelcfg  = MODEL_CONFIG_VALUE;
      max1726x_ez_config.vempty    = BAT_EMPTY_VOLTAGE;
    
      ret = MAX17260_Store_Original_HibCFG(&hibernate_config);
      ret += MAX17260_Exit_Hibernate_Mode();
      ret += MAX17260_Write_Configuration(&max1726x_ez_config);
      ret += MAX17260_Wait_For_ModelCFG_Refresh();
      ret += MAX17260_Restore_Original_HibCFG(&hibernate_config);
      if (ret != NRF_SUCCESS) {
        return ret;
      }
    
      return NRF_SUCCESS;
    }
    
    /**
     * @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_Read_Average_Voltage.
     *              This function read voltage.
     * @param[out]  pointer to store read average voltage
     * @return      NRF_SUCCESS on success, otherwise an error code.
     */
    ret_code_t MAX17260_Read_Average_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_Average_Voltage(MAX1726X_AVGVCELL_REG, &monitor->avg_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("Avg Voltage: %d  : %x", monitor->avg_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);
    
      MAX17260_Check_POR();
      MAX17260_Wait_Data_Ready_After_Power_Up();
      MAX17260_Initialize_Config();
      MAX17260_Clear_POR();
    
      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();
      }
    }
    

    Could there be any other reason ? Should I look into any other factors that might be affecting the readings?

    Thanks in advance!

Children
Related