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

Trying to start developing driver for MAX30105

Hello there.

I am new to Nordic and I want to make MAX30105 sensor to work with my NRF52 DK board (i am using the "nRF5_SDK_15.2.0_9412b96")...

I used the "twi_scanner" example to scan for the sensor and found its address which is 0x75 (which is the correct one judging by the datasheet).

Next I modified the "twi_sensor" example to try with lighting the green led of the sensor as a start.

Here is the modified main function:

int main(void)
{
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("\r\nTWI sensor example started.");
    NRF_LOG_FLUSH();
    twi_init();
    NRF_LOG_INFO("\r\nTWI init finished.");
    NRF_LOG_FLUSH();
    MAX30105_set_mode();
    NRF_LOG_INFO("\r\nMAX30105 set mode finished.");
    NRF_LOG_FLUSH();

    while (true)
    {
        nrf_delay_ms(500);

        do
        {
            __WFE();
        }while (m_xfer_done == false);

        read_sensor_data();
        NRF_LOG_FLUSH();
    }
}

Here is the modified LM75B_set_mode function which i renamed to be MAX30105_set_mode now:

void MAX30105_set_mode(void)
{
    ret_code_t err_code;
    /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
    uint8_t reg[2] = {0x0EU, 0x7FU};
    err_code = nrf_drv_twi_tx(&m_twi,  0x75U, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
    NRF_LOG_INFO("\r\ntest");
    NRF_LOG_FLUSH();
}

"0x0E" is the register for the green led amplitude and "0x7F" is the value to set the led current to 25.4mA.
I didn't modify anything else.
What i get in the serial is this:

"<info> app:
TWI sensor example started.
<info> app:
TWI init finished."

It seems like "m_xfer_done" never becomes "true", with other words the transmission of the configuration i want to send never finishes.
Any help will be greatly appreciated. Thanks in advance.

  • Does the twi_handler() return any event? 

    typedef enum
    {
    NRF_DRV_TWI_EVT_DONE, ///< Transfer completed event.
    NRF_DRV_TWI_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address.
    NRF_DRV_TWI_EVT_DATA_NACK ///< Error event: NACK received after sending a data byte.
    } nrf_drv_twi_evt_type_t;

  • Thanks for the fast reply.

    As I said I am new to nrf52 DK and I really struggled finding a way to debug the return of the handler, so I ended up checking only with what the board was printing out in the serial interface which was the messages I was printing out using the "NRF_LOG_INFO" after each function Disappointed I really cant understand how should I debug the board correctly and check for error codes even after reading all the resources about this that I could find.

    Anyway I got logic analyzer and compared the communication with arduino. What I found out was that instead "0x75" as address of the sensor as noted in the datasheet and as it was defined in the MAX30105 library of the arduino, the arduino was actually sending an address of "0xAE" and I realized that adress is just the original address of "0x75" but bit shifted one bit to the left (i have still to understand how this works and why).

    Also I replaced the default I2C frequency NRF_TWI_FREQ_100K in the twi_sensor example with NRF_TWI_FREQ_400K since in the MAX30105 datasheet it says "SCL Clock Frequency SCL Lower limit not tested 400kHz"

    Another thing is that for connecting the wires to the nrf52 DK board I used this pinout scheme:
    https://www.semiconductorstore.com/images/Items/Nordic/nrf52_dk_002.jpg?fbclid=IwAR1Q5L_QdYo3J2qeF6AucBGDfuis3UXieyOOcby7UclM5I5FLMxO9aRVIu8
    but since that was not working I just switched the SCL and SDA pins of the sensor and I got thru the first successful communication between the sensor and the nrf52 board Slight smile

    Whats strange is that instead using the original address "0x75" in the tests i used "0x57" address by mistake and strangely this is what worked...

    This is the whole code of the example i am using now:

    #include <stdio.h>
    #include "boards.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "nrf_drv_twi.h"
    #include "nrf_delay.h"
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    /* TWI instance ID. */
    #define TWI_INSTANCE_ID     0
    
    /* Common addresses definition for temperature sensor. */
    #define LM75B_ADDR          (0x90U >> 1)
    
    #define LM75B_REG_TEMP      0x00U
    #define LM75B_REG_CONF      0x01U
    #define LM75B_REG_THYST     0x02U
    #define LM75B_REG_TOS       0x03U
    
    /* Mode for LM75B. */
    //#define NORMAL_MODE 0U
    
    /* Indicates if operation on TWI has ended. */
    static volatile bool m_xfer_done = false;
    
    /* TWI instance. */
    static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
    
    /* Buffer for samples read from temperature sensor. */
    static uint8_t m_sample;
    
    /**
     * @brief Function for setting active mode on MMA7660 accelerometer.
     */
    void MAX30105_set_mode(void)
    {
        ret_code_t err_code;
        /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
        uint8_t reg[2] = {0x0C, 0x7F};
        err_code = nrf_drv_twi_tx(&m_twi,  0x57, reg, sizeof(reg), true);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
        NRF_LOG_INFO("\r\ntest");
        NRF_LOG_FLUSH();
    }
    
    /**
     * @brief Function for handling data from temperature sensor.
     *
     * @param[in] temp          Temperature in Celsius degrees read from sensor.
     */
    __STATIC_INLINE void data_handler(uint8_t data)
    {
        NRF_LOG_INFO("Data returned: %d", data);
    }
    
    /**
     * @brief TWI events handler.
     */
    void twi_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_RX)
                {
                    data_handler(m_sample);
                }
                m_xfer_done = true;
                break;
            default:
                break;
        }
    }
    
    /**
     * @brief UART initialization.
     */
    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_MAX30105_config = {
           .scl                = ARDUINO_SCL_PIN,
           .sda                = ARDUINO_SDA_PIN,
           .frequency          = NRF_TWI_FREQ_400K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_MAX30105_config, twi_handler, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_twi);
    }
    
    /**
     * @brief Function for reading data from temperature sensor.
     */
    static void read_sensor_data()
    {
        m_xfer_done = false;
    
        /* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
        ret_code_t err_code = nrf_drv_twi_rx(&m_twi, LM75B_ADDR, &m_sample, sizeof(m_sample));
        APP_ERROR_CHECK(err_code);
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("\r\nTWI sensor example started.");
        NRF_LOG_FLUSH();
        twi_init();
        NRF_LOG_INFO("\r\nTWI init finished.");
        NRF_LOG_FLUSH();
        MAX30105_set_mode();
        NRF_LOG_INFO("\r\nMAX30105 set mode finished.");
        NRF_LOG_FLUSH();
    
        while (true)
        {
            nrf_delay_ms(500);
    
            do
            {
                __WFE();
            }while (m_xfer_done == false);
    
            read_sensor_data();
            NRF_LOG_FLUSH();
        }
    }
    
    /** @} */
    

    The serial output i get now is:


    "<info> app:
    TWI sensor example started.
    <info> app:
    TWI init finished.
    <info> app:
    test
    <info> app:
    MAX30105 set mode finished."

    so I think this confirms that the first communication between the sensor and the board is working.

  • I think you will have to debug a bit more and try to locate the problem. A good idea can be also to let the twi_handler() set m_xfer_done = true; for all twi events (even in nack), so you avoid you get stuck in an infinite loop.

  • i need help with a simple thing. i tried both MAX30105 and MAX30205, and to make them both function i had to level shift their addresses by 0 bytes...

    example MAX30205 has address of 0x49, if i write in the "twi_sensor" example sensor address of 0x49 i get 0x90 address request on the logic analyzer, if i shift it by 1 bytes left (0x49U << 1) then i get 0x92 on the logic analyzer, but if i shift the address by 0 bytes (0x49U << 0) left then i get the correct 0x49 address request coming out of the NRF52DK and the sensors are working... why is this happening? why in the SDK example "twi_sensor" the address is shifted by 1 byte to the right and i need to shift my addresses by 0 bytes to the left?

  • Sometimes the address when defined is shifted '1' bit due to the address is 7bit, while when you look at the twi transfer the address is actually the first 7 bits of the twi transfer (the 8th bit is the write/read bit). 

Related