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

Arduino TWI to NRF52 TWI conversion

I am still trying to convert properly the Arduino MAX30105 driver to work with NRF52 and managed to come to somewhere... Everything works except the reading of the MAX30105 FIFO data (the data from the sensor).
I have troubles understanding how to do the requests they are doing with the Arduino Wire library using the NRF52 TWI.
Here is the arduino library part that I have trouble converting:

   //Get ready to read a burst of data from the FIFO register
    _i2cPort->beginTransmission(MAX30105_ADDRESS);
    _i2cPort->write(MAX30105_FIFODATA);
    _i2cPort->endTransmission();

    //We may need to read as many as 288 bytes so we read in blocks no larger than I2C_BUFFER_LENGTH
    //I2C_BUFFER_LENGTH changes based on the platform. 64 bytes for SAMD21, 32 bytes for Uno.
    //Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno
    while (bytesLeftToRead > 0)
    {
      int toGet = bytesLeftToRead;
      if (toGet > I2C_BUFFER_LENGTH)
      {
        //If toGet is 32 this is bad because we read 6 bytes (Red+IR * 3 = 6) at a time
        //32 % 6 = 2 left over. We don't want to request 32 bytes, we want to request 30.
        //32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27.

        toGet = I2C_BUFFER_LENGTH - (I2C_BUFFER_LENGTH % (activeLEDs * 3)); //Trim toGet to be a multiple of the samples we need to read
      }

      bytesLeftToRead -= toGet;

      //Request toGet number of bytes from sensor
      _i2cPort->requestFrom(MAX30105_ADDRESS, toGet);
      
      while (toGet > 0)
      {
        sense.head++; //Advance the head of the storage struct
        sense.head %= STORAGE_SIZE; //Wrap condition

        byte temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long
        uint32_t tempLong;

        //Burst read three bytes - RED
        temp[3] = 0;
        temp[2] = _i2cPort->read();
        temp[1] = _i2cPort->read();
        temp[0] = _i2cPort->read();

I am trying to do this like this:

    //Get ready to read a burst of data from the FIFO register
    ret_code_t err_code;
    uint8_t reg_write[1] = {MAX30105_FIFODATA};
    err_code = nrf_drv_twi_tx(&m_twi, MAX30105_ADDRESS, reg_write, sizeof(reg_write), true);
    APP_ERROR_CHECK(err_code);

    //We may need to read as many as 288 uint8_ts so we read in blocks no larger than I2C_BUFFER_LENGTH
    //I2C_BUFFER_LENGTH changes based on the platform. 64 uint8_ts for SAMD21, 32 uint8_ts for Uno.
    //Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno
    while (bytesLeftToRead > 0)
    {
      int toGet = bytesLeftToRead;
      if (toGet > MAX30105_I2C_BUFFER_LENGTH)
      {
        //If toGet is 32 this is bad because we read 6 uint8_ts (Red+IR * 3 = 6) at a time
        //32 % 6 = 2 left over. We don't want to request 32 uint8_ts, we want to request 30.
        //32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27.

        toGet = MAX30105_I2C_BUFFER_LENGTH - (MAX30105_I2C_BUFFER_LENGTH % (MAX30105_activeLEDs * 3)); //Trim toGet to be a multiple of the samples we need to read
      }

      bytesLeftToRead -= toGet;
      //Request toGet number of uint8_ts from sensor
      
    ret_code_t err_code1;
    uint8_t m_sample[sizeof(toGet)];      
      while (toGet > 0)
      {
        sense.head++; //Advance the head of the storage struct
        sense.head %= MAX30105_STORAGE_SIZE; //Wrap condition

        uint8_t temp[sizeof(uint32_t)]; //Array of 4 uint8_ts that we will convert into long
        uint32_t tempLong;

        //Burst read three uint8_ts - RED
        temp[3] = 0;
        err_code1 = nrf_drv_twi_rx(&m_twi, MAX30105_ADDRESS, &m_sample, sizeof(m_sample));                
        APP_ERROR_CHECK(err_code1);
        temp[2] = m_sample;
        err_code1 = nrf_drv_twi_rx(&m_twi, MAX30105_ADDRESS, &m_sample, sizeof(m_sample));                
        APP_ERROR_CHECK(err_code1);
        temp[1] = m_sample;
        err_code1 = nrf_drv_twi_rx(&m_twi, MAX30105_ADDRESS, &m_sample, sizeof(m_sample));                
        APP_ERROR_CHECK(err_code1);
        temp[0] = m_sample;


My question is how can i do the line "_i2cPort->requestFrom(MAX30105_ADDRESS, toGet);" using the NRF52 TWI and is the "nrf_drv_twi_rx(&m_twi, MAX30105_ADDRESS, &m_sample, sizeof(m_sample));" that i am using correct replacement for the "_i2cPort->read();" in arduino?

What i get is constant number which is same for all three LED values:
<info> app: Red: 30840
<info> app: IR: 30840
<info> app: Green: 30840


Any help is welcome. Thanks in advance.

  • I guess what you wanted to do is :

    uint8_t m_sample[sizeof(toGet)];      
          while (toGet > 0)
          {
            sense.head++; //Advance the head of the storage struct
            sense.head %= MAX30105_STORAGE_SIZE; //Wrap condition
    
            uint8_t temp[sizeof(uint32_t)]; //Array of 4 uint8_ts that we will convert into long
            uint32_t tempLong;
    
            //Burst read three uint8_ts - RED
            err_code1 = nrf_drv_twi_rx(&m_twi, MAX30105_ADDRESS, temp, 3);                
            APP_ERROR_CHECK(err_code1);
            templong = ((uint32_t)temp[0] << 16) | ((uint32_t)temp[1]<<8) | temp[2];
            
          }
     

  • Thanks for your replay.
    That worked somewhat.

    Using a red paper over the sensor this is what i get from nrf52 board:

    <info> app: Red: 69110   IR: 69101   Green: 69087
    <info> app: Red: 69090   IR: 69095   Green: 69076
    <info> app: Red: 69036   IR: 69061   Green: 69068
    <info> app: Red: 69052   IR: 69052   Green: 69066
    <info> app: Red: 69039   IR: 69047   Green: 69048
    <info> app: Red: 69003   IR: 69022   Green: 69031
    <info> app: Red: 69055   IR: 69040   Green: 69018
    <info> app: Red: 69035   IR: 69037   Green: 69037
    <info> app: Red: 69056   IR: 69077   Green: 69023
    <info> app: Red: 69081   IR: 68991   Green: 69016
    <info> app: Red: 69049   IR: 69022   Green: 69011
    <info> app: Red: 69019   IR: 68981   Green: 68992
    <info> app: Red: 68934   IR: 68948   Green: 68968
    <info> app: Red: 68951   IR: 68946   Green: 68980

    This is using the same red paper over the sensor from Arduino:

     R[72284] IR[82808] G[1303]
     R[72278] IR[82796] G[1305]
     R[72280] IR[82803] G[1309]
     R[72287] IR[82812] G[1306]
     R[72282] IR[82819] G[1317]
     R[72270] IR[82819] G[1311]
     R[72276] IR[82813] G[1315]
     R[72283] IR[82823] G[1309]
     R[72286] IR[82825] G[1303]
     R[72287] IR[82821] G[1309]
     R[72289] IR[82828] G[1306]
     R[72291] IR[82815] G[1308]
     R[72280] IR[82805] G[1306]
     R[72299] IR[82818] G[1305]
     R[72298] IR[82818] G[1315]
     R[72289] IR[82819] G[1306]
     R[72308] IR[82826] G[1307]
     R[72310] IR[82809] G[1303]

  • if you want to read 9 bytes, then you need to read it in 1 shot.  

  • you were totally correct even in your first reply but i was unable to understand you because of my limited knowledge...

    after reading the sensor datasheet and the twi sdk documentation for more than 100 times after your reply i finally got it what i need to do... the deal was as you said i should have read all 9 bytes at once and then store the result 3 bytes at a time into the value holders of the 3 separate measurement values...

    thanks allot for you help

Related