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

Receiving a NACK communicating using TWI interfacing

II'm having issues communicating to the MLX90614, datasheet attached. It seems that I have everything set correctly and the TWI Scanner returns addresses and data. My output messages:

Event Handler was successfully called.
But the Event Handler did not receive a done indication.
TWI device detected at address: 0x0
TWI device rx data: 0x31
Size of:1
Event!! NACK received after sending the address.
Event Handler was successfully called.
TWI device detected at address: 0x1
TWI device rx data: 0x31

It appears things are ok.

However, when I run my normal RAM access to the sensor I get a nack with the below messages:

TWI Init err code: 0
Program initializing!!
Hard Coded Object Temperature: 3700
Running!
Start SMBus Read Memory
Event!! NACK received after sending the address.
Event Handler was successfully called.
But the Event Handler did not receive a done indication.
Tx err_code done: 0
Waiting for tx response...

Below are my key functions, etc which seem to align with what I've been seeing in the forums and documentation for the sensor:

#define TWI_MLX90614_SCL_PIN NRF_GPIO_PIN_MAP(1, 7)
#define TWI_MLX90614_SDA_PIN NRF_GPIO_PIN_MAP(1, 6)

/* TWI instance ID. */
#define TWI_INSTANCE_ID 0

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

/* Indicates if operation on TWI has ended. */
static volatile bool twi_mlx90614_xfer_done = false;

static void twi_mlx90614_init(void)
{
ret_code_t err_code;

nrf_drv_twi_config_t twi_mlx90614_config = NRF_DRV_TWI_DEFAULT_CONFIG;
twi_mlx90614_config.scl = TWI_MLX90614_SCL_PIN,
twi_mlx90614_config.sda = TWI_MLX90614_SDA_PIN,
twi_mlx90614_config.frequency = NRF_TWI_FREQ_100K,
twi_mlx90614_config.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
twi_mlx90614_config.clear_bus_init = false,

err_code = nrf_drv_twi_init(&twi_mlx90614_instance, &twi_mlx90614_config, twi_mlx90614_handler, NULL);

APP_ERROR_CHECK(err_code);
nrf_drv_twi_enable(&twi_mlx90614_instance);
SEGGER_RTT_printf(0,"TWI Init err code: %#u\n", err_code);
}

static void twi_mlx90614_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
switch (p_event->type)
{
case NRF_DRV_TWI_EVT_DONE:
{
if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TX)
{
SEGGER_RTT_printf(0,"Twi mlx90614 tx evt done.\n");
}
else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
{
SEGGER_RTT_printf(0,"Twi mlx90614 rx evt done.\n");
}
else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXRX)
{
printf("Twi mlx90614 txrx evt done.");
SEGGER_RTT_printf(0,"Twi mlx90614 txrx evt done.\n");
}
else if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_TXTX)
{
SEGGER_RTT_printf(0,"Twi mlx90614 txtx evt done.\n");
}
twi_mlx90614_xfer_done = true;
} break;

case NRF_DRV_TWI_EVT_ADDRESS_NACK:
SEGGER_RTT_printf(0,"Event!! NACK received after sending the address.\n");
break;

case NRF_DRV_TWI_EVT_DATA_NACK:
SEGGER_RTT_printf(0,"Event!! NACK received after sending a data byte.\n");
break;
default:
break;
}
SEGGER_RTT_printf(0,"Event Handler was successfully called.\n");
if(twi_mlx90614_xfer_done == false){
SEGGER_RTT_printf(0,"But the Event Handler did not receive a done indication.\n"); 
}else{
SEGGER_RTT_printf(0,"Event Handler received done indication!!!\n"); 
}

}


uint16_t Read_MLX_Memory(uint8_t slave_Address, uint8_t command)
{
ret_code_t err_code;
uint16_t data; // Data storage (DataH:DataL)
uint8_t Pec; // PEC byte storage
uint8_t PecReg; // Calculated PEC byte storage
uint8_t arr[6]; // Buffer for the sent bytes
uint8_t DataL = 0; // Low data byte storage
uint8_t DataH = 0; // High data byte storage
uint8_t rx_data[3] = {0}; // Data received from twi
uint8_t tx_data = {command}; // Data sent from twi . 
slave_Address <<= 1; // 2-7 bits indicate the slave address

do
{

SEGGER_RTT_printf(0,"Start SMBus Read Memory\n");
err_code = nrf_drv_twi_tx(&twi_mlx90614_instance, slave_Address, &tx_data, sizeof(tx_data), true);
nrf_delay_ms(10);
SEGGER_RTT_printf(0,"Tx err_code done:0x%#u\n", err_code);
// APP_ERROR_CHECK(err_code);
twi_mlx90614_xfer_done = false;

SEGGER_RTT_printf(0,"Waiting for tx response...\n");
// while (twi_mlx90614_xfer_done == false);
do
{
__WFE();
} while(twi_mlx90614_xfer_done == false);
SEGGER_RTT_printf(0,"Transmit done, start receive\n");
err_code = nrf_drv_twi_rx(&twi_mlx90614_instance, slave_Address, rx_data, 3);
// APP_ERROR_CHECK(err_code);
twi_mlx90614_xfer_done = false;
do
{
__WFE();
} while(twi_mlx90614_xfer_done == false);
SEGGER_RTT_printf(0,"Receive data done\n");
DataL = rx_data[0];
DataH = rx_data[1];
Pec = rx_data[2];

arr[5] = slave_Address;
arr[4] = command;
arr[3] = slave_Address + 1; 
arr[2] = DataL;
arr[1] = DataH;
arr[0] = 0;
PecReg = PEC_Calculation(arr); // Calculate CRC
} while(PecReg != Pec); // If received and calculated CRC are equal get out of do-while{}

data = (DataH << 8) | DataL; // data = DataH:DataL
SEGGER_RTT_printf(0,"Read Memory done and return data\n");
return data;
}

//This function is called from main:
static float Read_MLX_Object_Temp(void)
{ 
return Read_MLX_Memory(MLX90614_ADDRESS, (OBJ1_TEMP));
}

Please let me know if you see something incorrect. The project is currently at a stand still. IO

MLX90614ESF-DCA-000-TU.pdf

Parents
  • Hello,

    From the datasheet you provided, the following except regards SD sending NACK:

            "After every received 8 bits the SD should issue ACK or NACK. When a MD initiates communication, it first sends the address of the slave and only the SD which recognizes the address will ACK, the rest will remain silent. In case the SD NACKs one of the bytes, the MD should stop the communication and repeat the message. A NACK could be received after the PEC. This  means that there is an error in the received message and the MD should try sending the message again. The PEC calculation includes all bits except the START, REPEATED START, STOP, ACK, and NACK bits. The PEC is a CRC-8 with polynomial X8+X2+X1+1. The Most Significant Bit of every byte is transferred first."

    What is the content of your tx_data when you first do nrf_drv_twi_tx? Which command are you trying to send?

    The fact that the TWI Scanner example were able to read the address tells us that the hardware connections should be all right, which means we need to take a look at what is being sent, and if it is received successfully.
    However, it seems that the TWI Scanner example is also receiving a NACK? If I have understood you correctly that the first log-exempt is from the TWI scanner example.
    Do you have access to a logical analyzer? 

    Best regards,
    Karl

Reply
  • Hello,

    From the datasheet you provided, the following except regards SD sending NACK:

            "After every received 8 bits the SD should issue ACK or NACK. When a MD initiates communication, it first sends the address of the slave and only the SD which recognizes the address will ACK, the rest will remain silent. In case the SD NACKs one of the bytes, the MD should stop the communication and repeat the message. A NACK could be received after the PEC. This  means that there is an error in the received message and the MD should try sending the message again. The PEC calculation includes all bits except the START, REPEATED START, STOP, ACK, and NACK bits. The PEC is a CRC-8 with polynomial X8+X2+X1+1. The Most Significant Bit of every byte is transferred first."

    What is the content of your tx_data when you first do nrf_drv_twi_tx? Which command are you trying to send?

    The fact that the TWI Scanner example were able to read the address tells us that the hardware connections should be all right, which means we need to take a look at what is being sent, and if it is received successfully.
    However, it seems that the TWI Scanner example is also receiving a NACK? If I have understood you correctly that the first log-exempt is from the TWI scanner example.
    Do you have access to a logical analyzer? 

    Best regards,
    Karl

Children
  • I actually changed my setup to use the Melexis library. The signals are stuck high. Can you confirm that it is OK to use the following pins for TWI?

    #define TWI_SCL_PIN NRF_GPIO_PIN_MAP(1, 7)
    #define TWI_SDA_PIN NRF_GPIO_PIN_MAP(1, 6)

    This is what is being sent:

    ret_code_t ret = nrf_drv_twi_tx (&m_twi, slave_address, &readAddress, 1, true);

    if (ret != NRF_SUCCESS) return -1;

    Then this:


    ret = nrf_drv_twi_rx (&m_twi, slave_address, smbData, 3);

    if (ret != NRF_SUCCESS) return -1;

    The implemetnation works on the nrf 52883 with nothing else.My implementation was based off of the HTS example. Is there anything there that could cause issue with TWI?

  • Hello,

    bfrank said:
    I actually changed my setup to use the Melexis library. The signals are stuck high.

    I am unfamiliar with the Melexis library.
    The signals are stuck high, you are seeing this using a logical analyzer I assume?

    bfrank said:
    Can you confirm that it is OK to use the following pins for TWI?

    I can check this for you if you tell me which nRF device you are using. I see that you have tagged your post with nRF52 and that you mention "nrf52883" in your text - are you using the nRF52833 SoC? Furthermore, are you using a Development Kit or a custom module?

    bfrank said:
    The implemetnation works on the nrf 52883 with nothing else.My implementation was based off of the HTS example. Is there anything there that could cause issue with TWI?

    What do you mean when you say that it works on the nRF with nothing else?
    Are you able to send and receive the correct data over TWI, or what do you mean here?

    As a side note, I would recommend that you use the nrfx_twim driver instead of the nrf_drv_twi_* legacy driver.

    Best regards,
    Karl

Related