Skip to content
Permalink
Browse files

drivers: adxl362: fix acceleration sample conversion

This driver uses magic numbers which are incorrect. A correct conversion
is done using the LSB/g scale factors given by Table 1 in the
specifications section of the ADXL362 (Rev. F) datasheet. The entire
conversion has also been consolidated into a signal function.

The sensitivity and offset of the accelerometer values actually vary
with the supply voltage and temperature. Using datasheet provided values
for 25 C and 2.0 V is the best we can do. Users will need to apply
sensitivity and offset corrections for their application.

Signed-off-by: Brett Witherspoon <spoonb@cdspooner.com>
  • Loading branch information...
bwitherspoon authored and MaureenHelm committed May 18, 2019
1 parent 4cc486e commit 935efeb0ce9d521a952d9139cc37614dd9418139
Showing with 40 additions and 19 deletions.
  1. +32 −16 drivers/sensor/adxl362/adxl362.c
  2. +8 −3 drivers/sensor/adxl362/adxl362.h
@@ -250,7 +250,7 @@ static int adxl362_set_range(struct device *dev, u8_t range)
return ret;
}

adxl362_data->selected_range = (1 << range) * 2;
adxl362_data->selected_range = range;
return 0;
}

@@ -550,31 +550,28 @@ static int adxl362_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct adxl362_data *data = dev->driver_data;
u8_t buf[2];
s16_t x, y, z;
int ret;

ret = adxl362_get_reg(dev, buf, ADXL362_REG_XDATA_L, 2);
if (ret) {
return ret;
}

x = (buf[1] << 8) + buf[0];
data->acc_x = (buf[1] << 8) + buf[0];

ret = adxl362_get_reg(dev, buf, ADXL362_REG_YDATA_L, 2);
if (ret) {
return ret;
}

y = (buf[1] << 8) + buf[0];
data->acc_y = (buf[1] << 8) + buf[0];

ret = adxl362_get_reg(dev, buf, ADXL362_REG_ZDATA_L, 2);
if (ret) {
return ret;
}

z = (buf[1] << 8) + buf[0];

data->acc_x = (s32_t)x * (adxl362_data.selected_range);
data->acc_y = (s32_t)y * (adxl362_data.selected_range);
data->acc_z = (s32_t)z * (adxl362_data.selected_range);
data->acc_z = (buf[1] << 8) + buf[0];

ret = adxl362_read_temperature(dev, &data->temp);
if (ret) {
@@ -584,12 +581,31 @@ static int adxl362_sample_fetch(struct device *dev, enum sensor_channel chan)
return 0;
}

static void adxl362_accel_convert(struct sensor_value *val, s16_t value)
static inline int adxl362_range_to_scale(int range)
{
/* See table 1 in specifications section of datasheet */
switch (range) {
case ADXL362_RANGE_2G:
return ADXL362_ACCEL_2G_LSB_PER_G;
case ADXL362_RANGE_4G:
return ADXL362_ACCEL_4G_LSB_PER_G;
case ADXL362_RANGE_8G:
return ADXL362_ACCEL_8G_LSB_PER_G;
default:
return -EINVAL;
}
}

static void adxl362_accel_convert(struct sensor_value *val, int accel,
int range)
{
s32_t micro_ms2 = value * (SENSOR_G / (16 * 1000));
int scale = adxl362_range_to_scale(range);
long micro_ms2 = accel * SENSOR_G / scale;

__ASSERT_NO_MSG(scale != -EINVAL);

val->val1 = micro_ms2 / 100000;
val->val2 = micro_ms2 % 100000;
val->val1 = micro_ms2 / 1000000;
val->val2 = micro_ms2 % 1000000;
}

static int adxl362_channel_get(struct device *dev,
@@ -600,13 +616,13 @@ static int adxl362_channel_get(struct device *dev,

switch (chan) {
case SENSOR_CHAN_ACCEL_X: /* Acceleration on the X axis, in m/s^2. */
adxl362_accel_convert(val, data->acc_x);
adxl362_accel_convert(val, data->acc_x, data->selected_range);
break;
case SENSOR_CHAN_ACCEL_Y: /* Acceleration on the Y axis, in m/s^2. */
adxl362_accel_convert(val, data->acc_y);
adxl362_accel_convert(val, data->acc_y, data->selected_range);
break;
case SENSOR_CHAN_ACCEL_Z: /* Acceleration on the Z axis, in m/s^2. */
adxl362_accel_convert(val, data->acc_z);
adxl362_accel_convert(val, data->acc_z, data->selected_range);
break;
case SENSOR_CHAN_DIE_TEMP: /* Temperature in degrees Celsius. */
val->val1 = data->temp / 1000;
@@ -161,6 +161,11 @@
#define ADXL362_STATUS_CHECK_INACT(x) (((x) >> 5) & 0x1)
#define ADXL362_STATUS_CHECK_ACTIVITY(x) (((x) >> 4) & 0x1)

/* ADXL362 scale factors from specifications */
#define ADXL362_ACCEL_2G_LSB_PER_G 1000
#define ADXL362_ACCEL_4G_LSB_PER_G 500
#define ADXL362_ACCEL_8G_LSB_PER_G 235

struct adxl362_config {
char *spi_name;
u32_t spi_max_frequency;
@@ -183,9 +188,9 @@ struct adxl362_data {
#if defined(DT_ADI_ADXL362_0_CS_GPIO_CONTROLLER)
struct spi_cs_control adxl362_cs_ctrl;
#endif
s32_t acc_x;
s32_t acc_y;
s32_t acc_z;
s16_t acc_x;
s16_t acc_y;
s16_t acc_z;
s32_t temp;
u8_t selected_range;

0 comments on commit 935efeb

Please sign in to comment.
You can’t perform that action at this time.