This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NACK from i2c slave

Hello Everyone,

          I am Using Nrf51822 module and s130_nrf51_2.0.1_softdevice . my actual function nrf51822 twi interface with stc3115 Gas gauge IC .read the battery voltage .i upload the twi_scanner . 

my output is TWI device detected at address 0x70  and then i read stc3115 id (address = 0x18 ) . i received err_code = 0x8021(Nack).

please help to correct my error

This is my code:

#include <stdio.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "stc3115_Driver.h"
#define NRF_LOG_MODULE_NAME "APP"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_internal.h"
#include "SEGGER_RTT.h"
//#include "nrf_drv_timer.h"

/* TWI instance ID. */
#define TWI_INSTANCE_ID 0
#define DEBUG
/* Number of possible TWI addresses. */
#define TWI_ADDRESSES 127

/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

static int GasGaugeTimerFinished(void);
static void Delay_ms(unsigned int value);
//void ChangeLowPowerMode(void);

#define TIMER_LIMIT 0x5000

/**
* @brief TWI initialization.
*/
void twi_init (void)
{
ret_code_t err_code;

const nrf_drv_twi_config_t twi_config = {
.scl = ARDUINO_SCL_PIN,   // pin 9
.sda = ARDUINO_SDA_PIN, // pin 8
.frequency = NRF_TWI_FREQ_100K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
.clear_bus_init = false
};

err_code = nrf_drv_twi_init(&m_twi, &twi_config,NULL, NULL);
APP_ERROR_CHECK(err_code);

nrf_drv_twi_enable(&m_twi);
}


/**
* @brief Function for main application entry.
*/
int main(void)
{
int res;
ret_code_t err_code;
uint8_t address;
uint8_t sample_data;
bool detected_device = false;
STC3115_ConfigData_TypeDef STC3115_ConfigData;
STC3115_BatteryData_TypeDef STC3115_BatteryData;
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
// SEGGER_RTT_WriteString(0,"TWI scanner.\r\n");
nrf_drv_twi_uninit(&m_twi);
NRF_LOG_FLUSH();
twi_init();
int status;
volatile char GasGauge_HardwareShutDown = 0; //Optional: set to 1 when the user power down the hardware, and no need to monitor the battery
volatile char GasGauge_UnknowError = 0; //Optional: set to 1 by the application when unknow gas gauge error occurs
//volatile char GasGauge_ChangeLowPowerMode = 0; //Optional: set to 1 by the application when need to decrease the gas gauge power consumption (ie. switch to voltage mode only monitoring)
int CounterValue;
int i;
// nrf_drv_twi_uninit(&m_twi);

/* for (address = 1; address <= TWI_ADDRESSES; address++)
{
err_code = nrf_drv_twi_rx(&m_twi,address, &sample_data, sizeof(sample_data));

if (err_code == NRF_SUCCESS)
{
detected_device = true;
SEGGER_RTT_printf(0,"TWI device detected at address 0x%x.\r\n", address);
}
// NRF_LOG_FLUSH();
}*/

GasGauge_Restart:
SEGGER_RTT_WriteString(0,"STC3115 fuel gauge driver init ...\n");

//----------------------------------------------------------------------
//Check I2C is working and Fuel gauge device connected

status = STC3115_CheckI2cDeviceId();

SEGGER_RTT_printf(0, "status1:0x%x\n", status);

if (status != 0) //error
{
if(status == -1)
{
SEGGER_RTT_WriteString(0,"STC3115: I2C error\n");
#ifdef DEBUG
//wait to simulate the whole application restart
// while( GasGaugeTimerFinished() != 1);
nrf_delay_ms(1000);
goto GasGauge_Restart;
#endif
}
else if(status == -2)
SEGGER_RTT_WriteString(0,"STC3115: Wrong device detected\n");
else
SEGGER_RTT_WriteString(0,"STC3115: Unknown Hardware error\n");

return -1; //return on error
}


//----------------------------------------------------------------------
//Check Gasgauge is powered up & ready, and first measurement (V, I) is done (i.e. wait CounterValue is 3 or more)

for(i=0; i<20; i++) //check for 20*100ms = 2s
{
CounterValue = STC3115_GetRunningCounter();
if(CounterValue >= 3) //ok, device ready
{
break; //exit loop
}
else if(CounterValue < 0) //communication Error
{
SEGGER_RTT_WriteString(0,"STC3115: Error power up.\n");
goto GasGauge_Restart;
}
else
{
//wait
Delay_ms(100);
}
}

if(CounterValue < 3) //timeout, the devise has not started
{
SEGGER_RTT_WriteString(0,"STC3115: Error power up.\n");
//goto GasGauge_Restart;
}

//----------------------------------------------------------------------
//Call STC3115 driver init&start function
status = GasGauge_Initialization(&STC3115_ConfigData, &STC3115_BatteryData);
if(status!=0 && status!=-2)
{
SEGGER_RTT_WriteString(0,"STC3115: Error in GasGauge_Initialization\n");
return -1; //return on error
}


#ifdef DEBUG
//----------------------------------------------------------------------
//Check Gasgauge is running (also checked in GasGauge_Task)

for(i=0; i<20; i++)
{
CounterValue = STC3115_GetRunningCounter();

if(CounterValue > 3) //Gas gauge COUNTER stays at value '3' after power up or Soft Reset, if not running
{
break; //exit loop
}
else
{
//wait
Delay_ms(100);
}
}

if(CounterValue <= 3)
{
printf("STC3115: Error, GasGauge not running. Check your hardware.\n");
goto GasGauge_Restart;
}
#endif

//----------------------------------------------------------------------
while(1) //main infinite loop
{
if(GasGauge_HardwareShutDown == 1) //Completely shutdown the platform and the Gas gauge. (not recommended, it is better to let the Gas Gauge running connected to battery)
{
GasGauge_HardwareShutDown = 0;
status = GasGauge_Stop(); //stop the Gas gauge but keep its RAM content
if(status != 0)SEGGER_RTT_WriteString(0,"STC3115: Error in GasGauge_Stop\n");

#ifdef DEBUG
//wait to simulate the application is powered off for a couple of time
while( GasGaugeTimerFinished() != 1);
goto GasGauge_Restart;
#endif
return 0;
}
else if(GasGauge_UnknowError == 1)
{
GasGauge_UnknowError = 0;
status = GasGauge_Reset(); //Reset the Gasgauge without disconnecting the battery
if(status != 0) SEGGER_RTT_WriteString(0,"STC3115: Error in GasGauge_Reset\n");

goto GasGauge_Restart;
}
else //normal case
{
if(GasGaugeTimerFinished() == 1) //every 5s
{
/* if(GasGauge_ChangeLowPowerMode == 1) //switch between Voltage mode and Mixed mode
{
ChangeLowPowerMode();
GasGauge_ChangeLowPowerMode = 0;
}*/

//Call task function
status = GasGauge_Task(&STC3115_ConfigData, &STC3115_BatteryData); /* process gas gauge algorithm, returns results */

if (status > 0) //OK, new data available
{
/* printf("Battery: SoC=%i %%, Vbat=%i mV, I=%i mA, Cap=%i mAh, T=%i °C, Pres=%i ALM=%i , CCounter=%d, Time=%d s \r\n",
STC3115_BatteryData.SOC * 0.1,
STC3115_BatteryData.Voltage,
STC3115_BatteryData.Current,
STC3115_BatteryData.ChargeValue,
STC3115_BatteryData.Temperature,
STC3115_BatteryData.Presence,
STC3115_BatteryData.StatusWord >> 13,
STC3115_BatteryData.ConvCounter,
STC3115_BatteryData.ConvCounter * 0.5 //elapsed time since gas gauge started
);*/
SEGGER_RTT_printf(0,"Vbat=%i mV",STC3115_BatteryData.Voltage);
}
else if(status == 0) //only previous SOC, OCV and voltage are valid
{
/*printf("Battery: Previous_SoC=%i %%, Vbat=%i mV, OCV=%i mV, T=%i °C \r\n",
STC3115_BatteryData.SOC * 0.1,
STC3115_BatteryData.Voltage,
STC3115_BatteryData.OCV,
STC3115_BatteryData.Temperature);*/
SEGGER_RTT_printf(0,"Vbat=%i mV",STC3115_BatteryData.Voltage);
}
else if(status == -1) //error occured
{
if(STC3115_BatteryData.Presence == 0)
{ /* Battery disconnection has been detected */
SEGGER_RTT_WriteString(0,"STC3115 Error: Battery disconnected, or BATD pin level is over 1.61, or Vcc is below 2.7V \r\n");
}
else
{
printf("STC3115: I2C failure \r\n");
}
}
} // END Timer finished
else
{
//Do other Tasks here ...
}
} //END normal case
}//END loop

return 0;
}


/*void ChangeLowPowerMode(void)
{
static int mode = 0;
int status;

if(mode == 0)
{
mode = !mode;
status = STC3115_SetPowerSavingMode();
if(status != 0) printf("STC3115: Error in SetPowerSavingMode\n");
}
else
{
mode = !mode;
status = STC3115_StopPowerSavingMode();
if(status != 0) printf("STC3115: Error in StopPowerSavingMode\n");
}
}*/


static int GasGaugeTimerFinished(void)
{
//dummy implementation. Better use a Hardware Timer.

static unsigned int i = 1;

i--;
if( i == 0)
{
i = TIMER_LIMIT;
return 1;
}
else
{
return 0;
}
}


static void Delay_ms(unsigned int value)
{
//quick and dirty delay function implementation

unsigned int i,j;
volatile int dummy = 0;

for(i=0; i<value; i++)
{
for(j=0; j<2000; j++) //pseudo 1ms
{
// waste function, volatile makes sure it is not being optimized out by compiler
dummy++;
}
}
}


 

Related