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

How to setup TWI Scanner

Hey,

I have a custom board with nRF52833. Sensor is connected to:
P0.11 (pin 19)  -  SCL
P1.08 (pin 17)  - SDA

with code below I don't get any `NRF_SUCCESS` back. 

void twi_init(void) {
    const nrfx_twim_config_t twi_config = {
        .scl                = 19,
        .sda                = 17,
        .frequency          = NRF_TWIM_FREQ_100K,
        .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
        .hold_bus_uninit    = false
    };

    nrfx_err_t err_code = nrfx_twim_init(&m_twi, &twi_config, NULL, NULL);
    nrfx_twim_enable(&m_twi);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{   

    int detected_device = 0;
   // nrfx_twim_uninit(&m_twi);
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("TWI scanner started.");
    NRF_LOG_FLUSH();
    twi_init();

    for (uint8_t address = 0; address <= TWI_ADDRESSES; address++) {
        uint8_t sample_data;
        sample_data = 0x00;

        nrfx_err_t err_code = nrfx_twim_rx(&m_twi, address, &sample_data, sizeof(sample_data));
        if (err_code == NRF_SUCCESS) {
            NRF_LOG_INFO("TWI device detected at address 0x%x.", address);
            detected_device = 1;
        }
        else{
            NRF_LOG_INFO("Nothing at 0x%x.", address);
          //  NRF_LOG_INFO("0x%02x x", address);
        }
        NRF_LOG_FLUSH();
        nrf_delay_ms(10);
    }

    if (!detected_device)
    {
        NRF_LOG_INFO("No device was found.");
        NRF_LOG_FLUSH();
    }

  /*  while (true)
    {
      
      
    }*/
}


I saw here that you must define pins (for eg. P1.08 - PIN 17) as 40 (1x32 + 8).
So I tried with addresses: .scl = 11 and .sda = 40.
I got `NRF_SUCCESS` 2 times (on addresses 0x36 and 0xb6) and got exited, but in datasheet address is shown as 0x57.
I was confused so I unplugged the sensor, run the code again and got the NRF_SUCCESS at same addresses. 
I don't know where to go from there.
Sensor is MAX86915, datasheet is not publicly available (I got it via NDA), but datasheet for MAX86916 is almost identical.

Edit: Now I see that if I connect a mini OLED display with i2c to it, even if set to 11 and 40 I don't get any address..
really don't know what is happening.

  • Hello,

    11 and 40 corresponds to P0.11 and P1.08 respectively so your pin assignments appear to be correct at least. But I would still recommend you use the NRF_GPIO_PIN_MAP() macro when assigning pins on PORT 1 as it ensures that the register value always get correctly encoded plus it helps improve the code readability a bit. E.g.

            .scl                = NRF_GPIO_PIN_MAP(0,11), // P0.11
            .sda                = NRF_GPIO_PIN_MAP(1,08), //P1.08

    Is the sensor already mounted on your custom board, or is it connected externally via cables? And do you have the same supply voltage on both the MAX86915 and the nRF52?

    Best regards,

    Vidar

  • Thanks, for some reason if I have connected Macbook Pro M1 via UGREEN USB-C hub and then to j-Link  and J-tag it doesn't go to  SUCCESS but if I have my Dell XPS 15 and connect J-link directly to USB it works Smiley
    Don't know why since debug works fine..
    So now I must find out how to read data from sensor :D Can you maybe help me with that? In the original question I have datasheet for MAX86916 that is almost the same as MAX86915.

    I created 2 functions for reading and writing data to registers:

    uint32_t read_register(uint8_t reg, uint8_t * p_data, uint32_t length)
    {
        uint32_t err_code;
        err_code = nrfx_twim_tx(&m_twi, MAX86915_ADDRESS, &reg, 1, false);
        if(err_code != NRF_SUCCESS) return err_code;
    
        
        err_code = nrfx_twim_rx(&m_twi, MAX86915_ADDRESS, p_data, length);
        if(err_code != NRF_SUCCESS) return err_code;
        return err_code;
    }
    
    uint32_t write_register(uint8_t reg_address, uint8_t data)
    {
        nrfx_err_t err_code; 
        uint8_t buffer_send[2] = {reg_address, data};
    		
        err_code = nrfx_twim_tx(&m_twi, MAX86915_ADDRESS, buffer_send, sizeof(buffer_send), true);
        APP_ERROR_CHECK(err_code);
    	
    }

    Then I have Init and reset functions for it:

    void MAX86915_init (void)
    {
        uint8_t revID; 
        uint8_t partID;
        nrfx_err_t err_code;
        err_code  = read_register (PART_ID, &partID,sizeof(partID));
    		APP_ERROR_CHECK(err_code);
    	
        NRF_LOG_INFO("MAX86915 PART ID: 0x%02x \r\n", partID);
        
    	
        err_code = read_register (REV_ID, &revID,sizeof(revID));
    		APP_ERROR_CHECK(err_code);
    	
        NRF_LOG_INFO("MAX86915 REV ID: 0x%02x \r\n", revID);
    }
    
    void MAX86915_reset (void)
    {	
        write_register(MODE_CONF, 0x40);
    }

    and lastly setup where I set up what should sensor do. I want to measure continuously.

    void MAX86915_setup (void)
    {
        write_register(INT_ENABLE_1, 0xC0);
        
        write_register(FIFO_WR_PTR, 0x00);	// Reset FIFO Write pointer
        write_register(OVERFLOW_CTR, 0x00); // Reset OVERFLOW_CTR pointer
        write_register(FIFO_RD_PTR, 0x00); 	// Reset FIFO READ pointer
        
        write_register(FIFO_CONF, 0x4F); //average sampling  = 4
        write_register(MODE_CONF, 0x03); // ADC range = 4096nA | Sampling Rate = 100 Hz | LED pulseWidth = 411uS
        
        write_register(SPO2_CONF, 0x27); // 400 samples per second
        write_register(LED1_PA, 0x5F); // LED1 current = 19 mA 
        write_register(LED2_PA, 0x5F); // LED2 current = 19 mA 
        write_register(LED3_PA, 0x5F); // LED1 current = 19 mA 
        write_register(LED4_PA, 0x5F); // LED2 current = 19 mA 
        write_register(PILOT_PA, 0x7F); // Pilot LED ~ 25mA
        write_register(LED_SEQ1, 0x21);
        write_register(LED_SEQ2, 0x43); 
    }

    With last 2 lines I enable all leds (LED's do turn on and I can see them)

    So now for measuring:
    As I understand I can see data in FIFO_DATA register at 0x07.
    But how do I read it? I have to create matrix because of 4 samples?
    Is not just as easy as reading (3 bytes per data item - I suppose data item is one led) fifo data register and just take 4 led data from there?

    So I have simple code:

    void read_fifo()
    {
        uint8_t clearINT1;
        uint32_t LEDdata1=0;
        uint32_t LEDdata2=0;
        uint32_t LEDdata3=0;
        uint32_t LEDdata4=0;
        uint8_t dataArray[12];
       
        nrfx_err_t err_code;
    
        //Clear Interrupts
        err_code = read_register(INT_STATUS_1, &clearINT1,sizeof(clearINT1));
        
        //read from FIFO_DATA
        err_code =read_register(FIFO_DATA,dataArray,sizeof(dataArray));
        APP_ERROR_CHECK(err_code);	
    
    
        //Parse data like that?
        LEDdata1=dataArray[0]<<16|dataArray[1]<<8 |dataArray[2];
        LEDdata2=dataArray[3]<<16|dataArray[4]<<8 |dataArray[5];
        LEDdata3=dataArray[6]<<16|dataArray[7]<<8 |dataArray[8];
        LEDdata4=dataArray[9]<<16|dataArray[10]<<8 |dataArray[11];
      
    
        //HERE PUSH IT TO MOBILE PHONE WITH BLE
    }


    I get some weird data, so I suppose this is not the way to fetch data from register.
    I also found this library with read_fifo_data function on line 3266 and it seems I have to do a lot more work?
    so on first pass I get 4 samples for LED1 and on second 4 samples for LED2 etc. or what? I'm a bit lost..

    This is maybe off topic, but I want to send data to my mobile device.. I used to use HC-06 for that and I usually just send data to serial and all data goes to phone.. What could be the best alternative since that is not BT device? 


  • Jdeveloper said:
    Thanks, for some reason if I have connected Macbook Pro M1 via UGREEN USB-C hub and then to j-Link  and J-tag it doesn't go to  SUCCESS but if I have my Dell XPS 15 and connect J-link directly to USB it works 

    This is strange.. I'm afraid I can't think of any possible explanations for this kind of behaviour.

    Jdeveloper said:
    I created 2 functions for reading and writing data to registers:

     Try to make the send and receive buffers 'static' or global. buffer_send in write_register() is currently a stack variable which will be freed as soon as the program exits the function.

    Are you using the TWIM API in blocking or non-blocking mode (see Basic usage)? In case of the latter you have to make sure the previous transaction is complete before starting the next. I.e. you can't have multiple write_register() calls in a row with no delay in-between. The SDK TWI sensor example uses the 'm_xfer_done' for this purpose.

Related