diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index fff31a553c..8de08bc8c5 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -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 diff --git a/drivers/sensors/ms56xx_uorb.c b/drivers/sensors/ms56xx_uorb.c index 33249a9135..1306b426ae 100644 --- a/drivers/sensors/ms56xx_uorb.c +++ b/drivers/sensors/ms56xx_uorb.c @@ -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;