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

TWI Master and access to RAM through EEPROM Register

Hello Everyone,

I started to use the NRF52832 recently and wanted to use it with a sensor from Melexis called MLX90632. I am using sdk 15.0.0.

This sensor have a library provided with it that helped me understand better how does the sensor work but i am blocking on the read and write function.

They have an example for the STM32 MCU ( https://github.com/melexis/mlx90632-example) that should be i should be able to replicate using the NRF52 function and drivers but i can't manage to make it work. In theory i should only modify the main file and not the library pre-built function.

While calling the function that i wrote i get the NRF_SUCCESS but i can't get actual values from the functions.

I believe the error might be located in the functions : mlx90632_i2c_read or mlx90632_i2c_write

Here is my main file for better understanding of my issue.

/**
 * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 * 
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 * 
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 * 
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 * 
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */
/** @file
 * @defgroup tw_sensor_example main.c
 * @{
 * @ingroup nrf_twi_example
 * @brief TWI Sensor Example main file.
 *
 * This file contains the source code for a sample application using TWI.
 *
 */

#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_twi_mngr.h"
#include "nrf_twi_sensor.h"


#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

/* Sensor Declarations*/
#include "mlx90632.h"

/* TWI instance ID. */
#define TWI_INSTANCE_ID    1
#define MAX_PENDING_TRANSACTIONS    8
#define NRF_TWI_SENSOR_SEND_BUF_SIZE 8


typedef void(* nrf_twi_sensor_reg_cb_t)(ret_code_t result, void *p_register_data);


/* Common addresses definition for temperature sensor. */
#define SensorAdress          (0x3A>>1) //#define LM75B_ADDR          (0x90U >> 1)




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


NRF_TWI_MNGR_DEF(m_nrf_twi_mngr, MAX_PENDING_TRANSACTIONS, TWI_INSTANCE_ID);
NRF_TWI_SENSOR_DEF(m_nrf_twi_sensor, &m_nrf_twi_mngr, NRF_TWI_SENSOR_SEND_BUF_SIZE);


int temperature_skin = 0;
int raw_temperature=0;



double pre_ambient, pre_object, ambient, object;





void twi_mngr_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_sensor_config = {
       .scl                = I2C_SCL,
       .sda                = I2C_SDA,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_twi_mngr_init(&m_nrf_twi_mngr, &twi_sensor_config);
    printf(nrf_strerror_get(err_code));
    APP_ERROR_CHECK(err_code);
    
}




/* Implementation of I2C read for 16-bit values */
int32_t mlx90632_i2c_read(int16_t register_address, uint16_t *value)
{
	uint8_t data[2];
	int32_t ret;
        ret_code_t err_code;
        nrf_twi_sensor_reg_cb_t user_cb;
	ret = nrf_twi_sensor_reg_read(&m_nrf_twi_sensor,SensorAdress,register_address,user_cb,data,sizeof(data));
        printf(nrf_strerror_get(ret));
	//Endianness
	*value = data[1]|(data[0]<<8);
	return ret;
}

/* Implementation of I2C read for 32-bit values */
int32_t mlx90632_i2c_read32(int16_t register_address, uint32_t *value)
{
	uint8_t data[4];
	int32_t ret;
        nrf_twi_sensor_reg_cb_t user_cb;
	ret = nrf_twi_sensor_reg_read(&m_nrf_twi_sensor,SensorAdress,register_address,user_cb,data,sizeof(data));
        
	//Endianness
	*value = data[2]<<24|data[3]<<16|data[0]<<8|data[1];
	return ret;
}

/* Implementation of I2C write for 16-bit values */
int32_t mlx90632_i2c_write(int16_t register_address, uint16_t value) {
	uint8_t data[2];
	data[0] = value >> 8;
	data[1] = value;
        int32_t ret ;
	return nrf_twi_sensor_reg_write(&m_nrf_twi_sensor,SensorAdress,register_address,data,sizeof(data));
}


/* Implementation of reading all calibration parameters for calucation of Ta and To */
static int mlx90632_read_eeprom(int32_t *PR, int32_t *PG, int32_t *PO, int32_t *PT, int32_t *Ea, int32_t *Eb, int32_t *Fa, int32_t *Fb, int32_t *Ga, int16_t *Gb, int16_t *Ha, int16_t *Hb, int16_t *Ka)
{
	int32_t ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_P_R, (uint32_t *) PR);

	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_P_G, (uint32_t *) PG);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_P_O, (uint32_t *) PO);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_P_T, (uint32_t *) PT);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_Ea, (uint32_t *) Ea);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_Eb, (uint32_t *) Eb);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_Fa, (uint32_t *) Fa);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_Fb, (uint32_t *) Fb);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read32(MLX90632_EE_Ga, (uint32_t *) Ga);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read(MLX90632_EE_Gb, (uint16_t *) Gb);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read(MLX90632_EE_Ha, (uint16_t *) Ha);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read(MLX90632_EE_Hb, (uint16_t *) Hb);
	if(ret < 0)
		return ret;
	ret = mlx90632_i2c_read(MLX90632_EE_Ka, (uint16_t *) Ka);
	if(ret < 0)
		return ret;
	return 0;
}

void usleep(int min_range, int max_range) {
	while(--min_range);
}


void twi_sensor_init(void){
    ret_code_t err_code;
    err_code = nrf_twi_sensor_init(&m_nrf_twi_sensor);
    APP_ERROR_CHECK(err_code);
    printf(nrf_strerror_get(err_code));
}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    int16_t ambient_new_raw;
    int16_t ambient_old_raw=25;
    int16_t object_new_raw;
    int16_t object_old_raw=25;
    int32_t PR = 0x00587f5b;
    int32_t PG = 0x04a10289;
    int32_t PT = 0xfff966f8;
    int32_t PO = 0x00001e0f;
    int32_t Ea = 4859535;
    int32_t Eb = 5686508;
    int32_t Fa = 53855361;
    int32_t Fb = 42874149;
    int32_t Ga = -14556410;
    int16_t Ha = 16384;
    int16_t Hb = 0;
    int16_t Gb = 9728;
    int16_t Ka = 10752;

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("\r\nTWI sensor example started.");
    NRF_LOG_FLUSH();
    twi_mngr_init();

    twi_sensor_init();
    mlx90632_read_eeprom(&PR, &PG, &PO, &PT, &Ea, &Eb, &Fa, &Fb, &Ga, &Gb, &Ha, &Hb, &Ka);
    while (true)
    {   
        
        nrf_delay_ms(1000);
        
       
        
        mlx90632_read_temp_raw(&ambient_new_raw, &ambient_old_raw, &object_new_raw, &object_old_raw);
    
	pre_ambient = mlx90632_preprocess_temp_ambient(ambient_new_raw, ambient_old_raw, Gb);
        pre_object = mlx90632_preprocess_temp_object(object_new_raw, object_old_raw, ambient_new_raw, ambient_old_raw, Ka);
	mlx90632_set_emissivity(1.0);
	ambient = mlx90632_calc_temp_ambient(ambient_new_raw, ambient_old_raw, PT, PR, PG, PO, Gb);
	object = mlx90632_calc_temp_object(pre_object, pre_ambient, Ea, Eb, Ga, Fa, Fb, Ha, Hb);
        printf("\nTemperature of new object : %d Celsius degrees.", object_new_raw);
        printf("\n Temperature of old object: %d Celsius degrees.", object_old_raw);
        
        NRF_LOG_FLUSH();
}}

/** @} */

I hope you can provide some insight on what my issue might be.

Guillaume

Parents
  • Hi Guillaume, 

    We can't really help you to interface with a specific 3rd party sensor, however I would suggest you to: 

    - Use a logic analyzer to capture the TWI transaction and compare it to what you can find in the sensor's datasheet and the sensor's library. 

    - Try to use TWI directly using nrf_drv_twi it may give you more flexibility than the nrf_twi_sensor library.

  • Hello Hung,

    I understand the fact that you can't help much about the 3rd party library but i believe my issue is really accessing the data stored in the eeprom and RAM from the sensor. Is there any template i could relate to because i believe the nrf_drv_twi that you suggested doesn't handle eeprom use.

    Anyway thanks for your help

    Guillaume

  • Hi Guillaume, 

    I don't see anything special about accessing RAM and EEPROM on the MLX90632. It's defined at section 10.2 in the product's datasheet. You can use nrf_drv_twi_rx() and nrf_drv_twi_tx() to read and write. 

  • Hello, I don't see any possible way to add eeprom into the nrf_rdv_twi_rx() or nrf_rdv_twi_tx() . When looking at the documentation (here) You don't have any explanation regarding EEPROM reading.

    When using for example  nrf_drv_twi_rx(), the parameters following the documentation should be :

    • nrf_drv_twi_t const * p_instance ----> &m_twi
    • uint8_t address -----> SensorAdress ( in my case 3A)
    • uint8_t * p_data ------> data 
    • uint8_t length -------> sizeof(data)

    And that's it, there is not explanation on how to handle the EEPROM of the sensor and adding the different addresses.

    I might misunderstand the function so if you have any way of explaining on how to use theses functions to use EEPROM i would be thankful. For example how should i do if i want to access the eeprom address of 0x3001.

    Regards

    Guillaume

  • Hi Guillaume, 

    Please have a look at the example twi_master_with_twis_slave inside \examples\peripheral.  
    In that example there is an emulated EEPROM is used. And it works almost like the MLX90632. Have a look at eeprom_read() function. First we use nrf_drv_twi_tx() to write the address we want to read, and after that we read it out using nrf_drv_twi_rx . Notice that the no_stop argument was set to true. matched with what described in the sensor datasheet.


    Please study section 10.2 in the MLX90632 datasheet. 

Reply
  • Hi Guillaume, 

    Please have a look at the example twi_master_with_twis_slave inside \examples\peripheral.  
    In that example there is an emulated EEPROM is used. And it works almost like the MLX90632. Have a look at eeprom_read() function. First we use nrf_drv_twi_tx() to write the address we want to read, and after that we read it out using nrf_drv_twi_rx . Notice that the no_stop argument was set to true. matched with what described in the sensor datasheet.


    Please study section 10.2 in the MLX90632 datasheet. 

Children
Related