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, ®_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?