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

I2C Slave with TWI not sending all data

We have an nRF52840 setup as a slave to communicate with a motor controller. I connected a logic analyzer to the lines to confirm the data being sent across. There are 18 data points that get sent on a read request. I hard coded the values to be sent in order to confirm they are received on the other side. Only the first value sent is received, the rest come across as zeros.

We are using nRF Connect SDK V1.2.0 for board nrf52840_pca10056.

When NRFX_TWIS_EVT_READ_REQ is received in the twis_event_handler, we call a function we call I2C_requestEvent() that steps through each of the data points to send with the nrfx_twis_tx_prepare() function. After each data point called in a tx_prepare function I then serial print out the value to verify what should have been sent.

Here is the code section:

nrfx_err_t I2C_requestEvent()
{  
    nrfx_err_t err;
    volatile uint16_t zero = 0;

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_Idle, sizeof(MsgToPicolo.AM_Idle));
    printk("Idle1= %d ", MsgToPicolo.AM_Idle);
    printk("err= %X\n",err);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, sizeof(zero));
    printk("Idle2= %d ", MsgToPicolo.AM_Idle);
    printk("error= %X\n",err);

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_BrakingStiffness, sizeof(MsgToPicolo.AM_BrakingStiffness));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, sizeof(zero));
    printk("Braking: %d ", MsgToPicolo.AM_BrakingStiffness);
    printk("error= %X\n",err);
    
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_StopRequest, sizeof(MsgToPicolo.AM_StopRequest));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, 1);
    printk("Stop: %d ", MsgToPicolo.AM_StopRequest);
    printk("error= %X\n",err);

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_TopSpeed, sizeof(MsgToPicolo.AM_TopSpeed));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, 1);
    printk("TopSpeed: %d ", MsgToPicolo.AM_TopSpeed);
    printk("error= %X\n",err);

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_AccelerationFactor, sizeof(MsgToPicolo.AM_AccelerationFactor));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, 1);
    printk("Acceleration: %d ", MsgToPicolo.AM_AccelerationFactor);
    printk("error= %X\n",err);

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_UserWeight, sizeof(MsgToPicolo.AM_UserWeight));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, 1);
    printk("Userweight: %d ", MsgToPicolo.AM_UserWeight);
    printk("error= %X\n",err);

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_DriveDuration, sizeof(MsgToPicolo.AM_DriveDuration));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, 1);
    printk("DriveDuration: %d ", MsgToPicolo.AM_DriveDuration);
    printk("error= %X\n",err);

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_GearUp, sizeof(MsgToPicolo.AM_GearUp));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, 1);
    printk("GearUp: %d ", MsgToPicolo.AM_GearUp);
    printk("error= %X\n",err);

    err = nrfx_twis_tx_prepare(&m_twis, (void *)&MsgToPicolo.AM_GearDown, sizeof(MsgToPicolo.AM_GearDown));
    //err = nrfx_twis_tx_prepare(&m_twis, 0, 1);
    err = nrfx_twis_tx_prepare(&m_twis, (void *)&zero, 1);
    printk("GearDown: %d ", MsgToPicolo.AM_GearDown);
    printk("error= %X\n",err);
    printk("Finish transmission\n");
  

  return err;
}

On the Logic analyzer and the drive controller IC in debug mode, I see: 

I2C_Data_Sent

The bottom line is the clock signal, the top is the data. 

The serial print was:

NRFX_TWIS_EVT_WRITE_REQ

Op code 0

Received Event: 8

NRFX_TWIS_EVT_WRITE_DONE

Request event

 

Idle= 4 error= bad0000                             //4 gets sent

Braking: 1 error= bad0000                        //0 gets sent

Stop: 0 error= bad0000                             //0 gets sent

TopSpeed: 4 error= bad0000                    //0 gets sent

Acceleration: 5 error= bad0000                 //0 gets sent

Userweight: 1 error= bad0000                   //0 gets sent

DriveDuration: 6 error= bad0000               //0 gets sent

GearUp: 0 error= bad0000                         //0 gets sent

GearDown: 0 error= bad0000                    //0 gets sent

 

Finish transmission

NRFX_TWIS_EVT_READ_DONE

NRFX_TWIS_EVT_GENERAL_ERROR

The error bad0000 means no error.

I'm not sure what to do.

Parents Reply Children
  • Try to remove the printk's between each nrfx_twis_tx_prepare(), also sizeof(zero) will send "\0".

    A colleague (Jeff4BLE) created a project to demonstrate how to use an I2C Slave in NCS, check it out here:

    blinky-twim.zipblinky-twis.zip

    "This has been tested with ncs v1.5.1. Extract the attached to \zephyr\samples\basic\blinky-twis

     

    To test the attached, use two nrf52840dks. One as a Master and the other as a Slave.

     

    Connect master’s P0.31 (CLK) to the Slaves P0.27.

    Connect master’s P0.20 (SDA) to the slave’s P0.26.

    Be sure that the DK’s share a common ground.

    Connec the virtual com port on each DK.

    To run the tests, first reset the slave and then the master.

     

    TWIM can be built with two configurations. This is selected by changing the value of TWI_LOOPBACK in the main.c (Line 40).

     

    #define TWI_LOOKBACK false.

    The master repeatedly sends “From TWIM” to the slave.

    The slave cycles through a large message that is sent over multiple read requests from the master."

    "#define TWI_LOOPBACK true

    The master will first a message “Begin Loopback.” Subsequent messages will be the last message received from the slave."

    Some few notes:

    1. It’s not a good idea to leave the printk in the twis_event_handler.
    2. The nrfx_twis_init return values are not thoroughly looked into
    3. In blinky-twis’s twis_event_handler, if printk("\nTWIS READ ERROR\n"); and printk("\nTWIS GENERAL ERROR\n"); are uncommented, these messages are printed. This would seem to indicate that the program is getting TWIS_EVT_READ_ERRORS and TWIS_EVT_GENERAL_ERRORs. I have has time to track this down. However, the program appears to work as expected. So it’s not a high priority. This may be related to 1.

    Best regards,

    Simon

  • For ncs v1.6.0, the TWIM’s prj.conf file needs to be modified.

    Replace CONFIG_SPI_1=n with CONFIG_NRFX_SPI1=n in proj.conf

  • We needed to send the full array at one time instead of each byte individually. The tx_prepare is preparing the full 18 bytes to send at one time. We got it working now. Thank you for the help.

  • I'm glad you got it working and I'm happy to help!

Related