Sparkfun MPRLS pressure sensor not responding to activation byte

nyameaama
Posts: 11
Joined: Fri Jul 28, 2023 7:43 am

Sparkfun MPRLS pressure sensor not responding to activation byte

Postby nyameaama » Thu Mar 21, 2024 6:16 am

Hi, I have a Sparkfun MPRLS pressure sensor breakout board. I have connected it via i2c and I'm attempting to write a driver. See my code below:

Code: Select all

#include "p_module.h"
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include "driver/i2c.h"

#define I2C_MASTER_SCL_IO           22                         /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO           21                         /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          200000                     /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS       1000
      
int16_t ret = 0;

#define MPRLS_DEFAULT_ADDR (0x18)   ///< Most common I2C address
#define MPRLS_READ_TIMEOUT (20)     ///< millis
#define MPRLS_STATUS_POWERED (0x40) ///< Status SPI powered bit
#define MPRLS_STATUS_BUSY (0x20)    ///< Status busy bit
#define MPRLS_STATUS_FAILED (0x04)  ///< Status bit for integrity fail
#define MPRLS_STATUS_MATHSAT (0x01) ///< Status bit for math saturation
#define COUNTS_224 (16777216L)      ///< Constant: 2^24
#define PSI_to_HPA (68.947572932)   ///< Constant: PSI to HPA conversion factor
#define MPRLS_STATUS_MASK (0b01100101) ///< Sensor status mask: only these bits are set

uint16_t _PSI_min = 0; 
uint16_t _PSI_max = 25;
float _OUTPUT_min = 10;
float _OUTPUT_max = 90;
float _K = PSI_to_HPA;

void PRESSURE::i2c_master_init(void){
  esp_err_t i2c_err;
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = I2C_MASTER_SDA_IO;
    conf.scl_io_num = I2C_MASTER_SCL_IO;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
    conf.clk_flags = 0;


    i2c_err = i2c_param_config(i2c_port_t(i2c_master_port), &conf);
    if(i2c_err != ESP_OK){
      printf("i2c parameter config error code: %d \r\n",i2c_err);
    }
    i2c_err = i2c_driver_install(i2c_port_t(i2c_master_port), conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
    if(i2c_err != ESP_OK){
      printf("i2c driver install error code: %d \r\n ",i2c_err);
    }else{
      printf("i2c driver installed \r\n");
    }
}

esp_err_t PRESSURE::pressure_init(void){
  i2c_master_init();
  return 0;
}

/**
* @brief Read a sequence of bytes from sensor registers
*/
esp_err_t PRESSURE::i2c_read(uint8_t reg_addr, uint8_t *data, size_t len){
    for (size_t i = 0; i < len; i++) {
        ret = i2c_master_write_read_device(i2c_port_t(I2C_MASTER_NUM), MPRLS_DEFAULT_ADDR, &reg_addr, 1,
            data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS );
    }    
    return ret;
}

/**
* @brief Write a byte to sensor register
*/
esp_err_t PRESSURE::i2c_write_byte(uint8_t reg_addr, uint8_t data){
    uint8_t write_buf[2] = {reg_addr, data};

    ret = i2c_master_write_to_device(i2c_port_t(I2C_MASTER_NUM), MPRLS_DEFAULT_ADDR, write_buf, sizeof(write_buf),
                                      I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    return ret;
}

void PRESSURE::i2C_WriteMulti(uint8_t address, uint8_t reg, uint8_t* data, uint16_t count) {
	i2c_cmd_handle_t cmd;
    cmd = i2c_cmd_link_create(); 

    i2c_master_start(cmd); //start I2C transaction
    i2c_master_write_byte(cmd, address , true); //send Address with write Bit
    i2c_master_write_byte(cmd, reg, 1); //Send Register Address
    
	i2c_master_write(cmd, data,count,true);
    i2c_master_stop(cmd);

    i2c_master_cmd_begin(I2C_NUM_0, cmd, 50);
    i2c_cmd_link_delete(cmd);
}

/**************************************************************************/
/*!
    @brief Read and calculate the pressure
    @returns The measured pressure, in hPa on success, NAN on failure

*/
/**************************************************************************/

float PRESSURE::readPressure(void) {
    uint32_t raw_psi = readData();
    if (raw_psi == 0xFFFFFFFF || _OUTPUT_min == _OUTPUT_max) {
        return NAN; // Return NAN if there's an error or configuration issue
    }

    // Calculate the pressure using the calibration data and conversion factor
    float psi = (raw_psi - _OUTPUT_min) * (_PSI_max - _PSI_min);
    psi /= (float)(_OUTPUT_max - _OUTPUT_min);
    psi += _PSI_min;

    // Convert to desired units (e.g., hPa) using the conversion factor _K
    return psi * _K;
}

/**************************************************************************/
/*!
    @brief Read 24 bits of measurement data from the device
    @returns -1 on failure (check status) or 24 bits of raw ADC reading
*/
/**************************************************************************/
uint32_t PRESSURE::readData(void) {
    uint8_t command_buffer[4] = {0xAA, 0, 0, 0};
    uint8_t data_buffer[4];

    // Send the command to start pressure reading
    i2C_WriteMulti(MPRLS_DEFAULT_ADDR, command_buffer[0], &command_buffer[1],3);
    // Now read the full data: status byte + 24-bit pressure data
    i2c_read(MPRLS_DEFAULT_ADDR, data_buffer, 4);
    ESP_LOGI("TAG", "Status Byte Check 1: %02x", data_buffer[0]);

    // Wait for the sensor to complete the measurement
    uint32_t start_time = esp_timer_get_time();
    do {
        if ((esp_timer_get_time() - start_time) > (MPRLS_READ_TIMEOUT * 1000)) {
            ESP_LOGE("TAG", "Timeout waiting for sensor");
            return 0xFFFFFFFF;
        }
        i2c_read(MPRLS_DEFAULT_ADDR, data_buffer, 1);
    } while (data_buffer[0] & MPRLS_STATUS_BUSY);

    // Now read the full data: status byte + 24-bit pressure data
    i2c_read(MPRLS_DEFAULT_ADDR, data_buffer, 4);
    ESP_LOGI("TAG", "Status Byte Check 2: %02x", data_buffer[0]);

    // Check for errors
    if (data_buffer[0] & (MPRLS_STATUS_MATHSAT | MPRLS_STATUS_FAILED)) {
        ESP_LOGE("TAG", "Sensor error: %02x", data_buffer[0]);
        return 0xFFFFFFFF;
    }

    // Extract the 24-bit pressure
    uint32_t pressure = (uint32_t(data_buffer[1]) << 16) | (uint32_t(data_buffer[2]) << 8) | uint32_t(data_buffer[3]);
    ESP_LOGI("TAG", "Pressure: %lu", pressure);
    return pressure;
}

/**************************************************************************/
/*!
    @brief Read just the status byte, see datasheet for bit definitions
    @returns 8 bits of status data
*/
/**************************************************************************/
uint8_t PRESSURE::readStatus(void) {
    uint8_t buffer[1];
    // Just read the status byte from the sensor
    i2c_read(MPRLS_DEFAULT_ADDR, buffer, 1);
    return buffer[0]; // Return the status byte
}



However I get this output:
I (345) main_task: Calling app_main()
i2c driver installed
I (345) TAG: Status Byte Check 1: 60
E (365) TAG: Timeout waiting for sensor
I (345) TAG: Output: -1
I (385) TAG: Status Byte Check 1: 60
E (405) TAG: Timeout waiting for sensor
I (385) TAG: Output: -1
I (415) TAG: Status Byte Check 1: 60
E (435) TAG: Timeout waiting for sensor
I (415) TAG: Output: -1
I (445) TAG: Status Byte Check 1: 60
E (465) TAG: Timeout waiting for sensor
I (445) TAG: Output: -1
I (475) TAG: Status Byte Check 1: 60
E (495) TAG: Timeout waiting for sensor
I (475) TAG: Output: -1
I (505) TAG: Status Byte Check 1: 60
E (525) TAG: Timeout waiting for sensor
I (505) TAG: Output: -1
I (535) TAG: Status Byte Check 1: 60
E (555) TAG: Timeout waiting for sensor
I (535) TAG: Output: -1
I (565) TAG: Status Byte Check 1: 60
E (585) TAG: Timeout waiting for sensor
I (565) TAG: Output: -1
I (595) TAG: Status Byte Check 1: 60
E (615) TAG: Timeout waiting for sensor
I (595) TAG: Output: -1

I have checked my wiring and the i2c address (0x18) but nothing is working. The status byte remains at 0x60 and does not shift to powered 0x40. What could be wrong?

ESP_Sprite
Posts: 9764
Joined: Thu Nov 26, 2015 4:08 am

Re: Sparkfun MPRLS pressure sensor not responding to activation byte

Postby ESP_Sprite » Thu Mar 21, 2024 8:40 am

Not sure how much it matters, but you write 3x '0' after the start command. The datasheet I found only shows 2x '0'.

nyameaama
Posts: 11
Joined: Fri Jul 28, 2023 7:43 am

Re: Sparkfun MPRLS pressure sensor not responding to activation byte

Postby nyameaama » Thu Mar 21, 2024 8:12 pm

Hi, yes I tried appending these combinations but nothing works.

0xAA, 0, 0, 0

0xAA, 0, 0

0xAA, 0x00, 0x00

The sensor is definitely powered but the status byte never leaves 0x60. The driver I’m writing takes heavy inspiration from the Adafruit arduino library. I’m going to try my luck with the sensor using the arduino sdk to figure out if the hardware is the problem or it’s the driver. I do believe the latter is the case though .

ESP_Sprite
Posts: 9764
Joined: Thu Nov 26, 2015 4:08 am

Re: Sparkfun MPRLS pressure sensor not responding to activation byte

Postby ESP_Sprite » Fri Mar 22, 2024 1:07 am

Btw, one thing to note is that you're not zero-initializing your stack variables, especially your configuration structs. I don't think that is it in this case, but better do this:

Code: Select all

    i2c_config_t conf={0};
to make sure any not-mentioned fields are zero-initialized.

Who is online

Users browsing this forum: Baidu [Spider] and 42 guests