sensors: mx56xx: Add support for second order compensation

In order to obtain best accuracy over temperature range,
particularly in low temperature, it is recommended to
compensate the non-linearity over the temperature.

ref: ENG_DS_MS5611-01BA03_B3.pdf
     ENG_DS_MS5607-02BA03_B4.pdf

Signed-off-by: Takumi Ando <t-ando@advaly.co.jp>
This commit is contained in:
Takumi Ando 2023-11-28 14:46:48 +09:00 committed by Xiang Xiao
parent 1c9fab65d8
commit ab693b9bec
2 changed files with 66 additions and 3 deletions

View File

@ -764,6 +764,15 @@ config MS56XX_SPI
endchoice # MS5611 Interface
config MS56XX_SECOND_ORDER_COMPENSATE
bool "MS56XX second order compensation support"
default n
---help---
Enables second order compensation.
In order to obtain best accuracy over temperature range,
particularly in low temperature, it is recommended to
compensate the non-linearity over the temperature.
config MS56XX_THREAD_STACKSIZE
int "Worker thread stack size"
default 1024

View File

@ -116,7 +116,8 @@ static int ms56xx_read24(FAR struct ms56xx_dev_s *priv,
static int32_t ms56xx_compensate_temp(FAR struct ms56xx_dev_s *priv,
uint32_t temp, int32_t *deltat);
static uint32_t ms56xx_compensate_press(FAR struct ms56xx_dev_s *priv,
uint32_t press, uint32_t dt);
uint32_t press, uint32_t dt,
int32_t temp);
static unsigned long ms56xx_curtime(void);
@ -350,7 +351,7 @@ static inline void baro_measure_read(FAR struct ms56xx_dev_s *priv,
/* Compensate the temp/press with calibration data */
temp = ms56xx_compensate_temp(priv, temp, &deltat);
press = ms56xx_compensate_press(priv, press, deltat);
press = ms56xx_compensate_press(priv, press, deltat, temp);
baro->timestamp = ms56xx_curtime();
baro->pressure = press / 100.0f;
@ -525,25 +526,78 @@ static int32_t ms56xx_compensate_temp(FAR struct ms56xx_dev_s *priv,
****************************************************************************/
static uint32_t ms56xx_compensate_press(FAR struct ms56xx_dev_s *priv,
uint32_t press, uint32_t dt)
uint32_t press, uint32_t dt,
int32_t temp)
{
struct ms56xx_calib_s *c = &priv->calib;
int64_t off = 0;
int64_t sens = 0;
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
int64_t off2 = 0;
int64_t sens2 = 0;
uint64_t delta;
#endif
switch (priv->model)
{
case MS56XX_MODEL_MS5607:
off = ((int64_t) c->c2 << 17) + ((int64_t) (c->c4 * dt) >> 6);
sens = ((int64_t) c->c1 << 16) + ((int64_t) (c->c3 * dt) >> 7);
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
if (temp < 2000)
{
/* Low temperature */
delta = temp - 2000;
delta *= delta;
off2 = (61 * delta) >> 4;
sens2 = 2 * delta;
if (temp < 1500)
{
/* Very low temperature */
delta = temp + 1500;
delta *= delta;
off2 += 15 * delta;
sens2 += 8 * delta;
}
}
#endif
break;
case MS56XX_MODEL_MS5611:
off = ((int64_t) c->c2 << 16) + ((int64_t) (c->c4 * dt) >> 7);
sens = ((int64_t) c->c1 << 15) + ((int64_t) (c->c3 * dt) >> 8);
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
if (temp < 2000)
{
/* Low temperature */
delta = temp - 2000;
delta *= delta;
off2 = (5 * delta) >> 1;
sens2 = (5 * delta) >> 2;
if (temp < 1500)
{
/* Very low temperature */
delta = temp + 1500;
delta *= delta;
off2 += 7 * delta;
sens2 += (11 * delta) >> 1;
}
}
#endif
break;
}
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
temp -= ((dt * dt) >> 31);
off -= off2;
sens -= sens2;
#endif
press = (((press * sens) >> 21) - off) >> 15;
return press;