01-27-2021 02:59 PM - edited 01-27-2021 03:00 PM
Hi all,
I have a problem using the BMP390L. I have configurated it correctly following the datasheet and a example project that I have found on this forum. But always the sensor returns me values around 975-977mbar and my atmospheric pressure is 940-945mbar aprox (35mbar of difference is so much). The MSB of the pressure data (reg 0x06) is always returning me the value 0x00. It is normal?
The measurement of temperature always returns me 1.5ºC more than real temperature, but I can assume this error.
The compensation coefficientes that I get are those seen in the following image, and I think that they are corrects because they are similar with normal values of calibration.
Furthermore, I have been checking the code of temperature and pressure compensation and the script is OK.
Does someone have any idea about why I can not get the right pressure?
Thank you all!
Solved! Go to Solution.
01-27-2021 07:35 PM
Hello,
Could you share your code?
Thanks,
01-28-2021 07:15 AM - edited 01-28-2021 07:18 AM
I want to make one measurement each second, so I configurated the sensor on "Ultra Low Power". This is the configuration:
ret1 = BMP390L_enable_sensors(st); // Sleep mode. Enable sensors
ret2 = PAWriteReg_BMP390L(st, 0, 0, (uint8_t)BMP390L_INT_CTRL, (uint32_t)BMP390L_REG_SIZE_BYTES, 0x02); // push-pull. INT rising edge. Drdy disable for pressure and temperature
ret3 = PAWriteReg_BMP390L(st, 0, 0, (uint8_t)BMP390L_IF_CONF, (uint32_t)BMP390L_REG_SIZE_BYTES, 0x00); // SPI 4-wire configuration
ret4 = PAWriteReg_BMP390L(st, 0, 0, (uint8_t)BMP390L_OSR, (uint32_t)BMP390L_REG_SIZE_BYTES, 0x00); // Oversamplig x1
ret5 = PAWriteReg_BMP390L(st, 0, 0, (uint8_t)BMP390L_ODR, (uint32_t)BMP390L_REG_SIZE_BYTES, 0x02); // 50Hz -> Ts = 20ms (prescaler = 4)
ret6 = PAWriteReg_BMP390L(st, 0, 0, (uint8_t)BMP390L_CONFIG, (uint32_t)BMP390L_REG_SIZE_BYTES, 0x00); // IRR coefficients = 0
get_compensation_coefficients(st); // Build CALIB_DATA struct
I confirm that I am writting right on the configuration registers.
These are the functions for compensation:
void get_compensation_coefficients(struct BMP390L_state *st)
{
tUint32 tmp;
double potencia; // valores del datahseet que corresponden a la división de las potencias
uint8_t i, addr;
uint8_t regs[21] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
// BMP390L_ReadRegs(regs, 0x31-0x45, 21 registros) - modo BURST para evitar latches en la lectura
addr = 0x31;
for (i = 0; i < 21; i++) {
PAReadReg_BMP390L(st, 0, 0, addr, (uint32_t) BMP390L_CALIBRATION_SIZE_BYTES, &tmp.all);
regs[i] = tmp.ui8.byteLow;
addr++;
}
// Appendix datasheet BMP390L
potencia = pow(2.0, -8.0);
calib_data.par_t1 = ((double)(regs[1] << 8 | regs[0]) / potencia);
potencia = pow(2.0, 30.0);
calib_data.par_t2 = ((double)(regs[3] << 8 | regs[2]) / potencia);
potencia = pow(2.0, 48.0);
calib_data.par_t3 = ((double)regs[4] / potencia);
potencia = pow(2.0, 20.0);
calib_data.par_p1 = (((double)(regs[6] << 8 | regs[5])-(16384.0)) / potencia);
potencia = pow(2.0, 29.0);
calib_data.par_p2 = (((double)(regs[8] << 8 | regs[7])-(16384.0)) / potencia);
potencia = pow(2.0, 32.0);
calib_data.par_p3 = ((double)regs[9] / potencia);
potencia = pow(2.0, 37.0);
calib_data.par_p4 = ((double)regs[10] / potencia);
potencia = pow(2.0, -3.0);
calib_data.par_p5 = ((double)(regs[12] << 8 | regs[11]) / potencia);
potencia = pow(2.0, 6.0);
calib_data.par_p6 = ((double)(regs[14] << 8 | regs[13]) / potencia);
potencia = pow(2.0, 8.0);
calib_data.par_p7 = ((double)regs[15] / potencia);
//potencia = 32768.0;
potencia = pow(2.0, 15.0);
calib_data.par_p8 = ((double)regs[16] / potencia);
potencia = pow(2.0, 48.0);
calib_data.par_p9 = ((double)(regs[18] << 8 | regs[17]) / potencia);
potencia = pow(2.0, 48.0);
calib_data.par_p10 = ((double)regs[19] / potencia);
potencia = pow(2.0, 65.0);
calib_data.par_p11 = ((double)regs[20] / potencia);
}
static double BMP390L_compensate_temperature(uint32_t uncomp_temp, struct BMP390L_calib_data *calib_data)
{
double partial_data1;
double partial_data2;
partial_data1 = (double)(uncomp_temp - calib_data->par_t1);
partial_data2 = (double)(partial_data1 * calib_data->par_t2);
// Update the compensated temperature in calib structure since this is
// needed for pressure calculation
calib_data->t_lin = partial_data2 + (partial_data1 * partial_data1) * calib_data->par_t3;
// Returns compensated temperature
return calib_data->t_lin;
}
static double BMP390L_compensate_pressure(uint32_t uncomp_press, struct BMP390L_calib_data *calib_data)
{
/* Variable to store the compensated pressure */
double comp_press;
/* Temporary variables used for compensation */
double partial_data1;
double partial_data2;
double partial_data3;
double partial_data4;
double partial_out1;
double partial_out2;
partial_data1 = calib_data->par_p6 * calib_data->t_lin;
partial_data2 = calib_data->par_p7 * pow_bmp3(calib_data->t_lin, 2);
partial_data3 = calib_data->par_p8 * pow_bmp3(calib_data->t_lin, 3);
partial_out1 = calib_data->par_p5 + partial_data1 + partial_data2 + partial_data3;
partial_data1 = calib_data->par_p2 * calib_data->t_lin;
partial_data2 = calib_data->par_p3 * pow_bmp3(calib_data->t_lin, 2);
partial_data3 = calib_data->par_p4 * pow_bmp3(calib_data->t_lin, 3);
partial_out2 = uncomp_press * (calib_data->par_p1 + partial_data1 + partial_data2 + partial_data3);
partial_data1 = pow_bmp3((double)uncomp_press, 2);
partial_data2 = calib_data->par_p9 + calib_data->par_p10 * calib_data->t_lin;
partial_data3 = partial_data1 * partial_data2;
partial_data4 = partial_data3 + pow_bmp3((double)uncomp_press, 3) * calib_data->par_p11;
comp_press = partial_out1 + partial_out2 + partial_data4;
return comp_press/100; // comp_press en pascales ------- hPa=mbar=Pa/100.
}
double pow_bmp3(double base, uint8_t power)
{
double pow_output = 1;
while (power != 0)
{
pow_output = (float) base * pow_output;
power--;
}
return pow_output;
}
On my main task, after call configuration functions (1st block of functions on this topic), I do the following to get a new value of pressure and temperature:
double PA_Temp, PA_Pressure;
ret1 = BMP390L_new_measurement(&PA_BMP390LStatus); // Forced mode. Pressure and temperature sensors enabled
TaskWait((uint16_t) 5); // Change Task (wait 25ms to get new measurement, T_adquisition=20ms)
PA_Temp = (double) INVALID_DATA;
while ((PA_Temp < (double) BMP390L_TEMP_VAL_MIN) || (PA_Temp > (double) BMP390L_TEMP_VAL_MAX))
{ // while
PATempRead_BMP390L(&PA_BMP390LStatus, &valTemp);
PA_Temp = BMP390L_compensate_temperature(valTemp, &calib_data);
} // while
PA_Pressure = (double) INVALID_DATA;
while ((PA_Pressure < (double) BMP390L_VAL_MIN) || (PA_Pressure > (double) BMP390L_VAL_MAX))
{
PARead_BMP390L(&PA_BMP390LStatus, &val);
PA_Pressure = BMP390L_compensate_pressure(val, &calib_data);
}
Here it is, on my fisrt measurement (and always), when I get a wrong value of pressure (with difference of 35mbar) and temperature (difference of 1.5ºC).
If you need more information about my program/script, do not hesitate to contact me.
Thank you all again.
01-28-2021 08:36 AM
Hi again Minhwan,
I have solved it. I was doing an incorrect cast when I read the data registers of the compensation coefficients.
Thank u very much for your support.
01-29-2021 12:49 AM
Hello Javierrobledo,
Good to hear that you solved the issue.
Please let me know if you have any questions.
Thanks,