From 7466b91fe3305adf16b25e466f33d69d69a1a1a4 Mon Sep 17 00:00:00 2001 From: William Clark Date: Mon, 8 Jan 2024 06:16:29 +0000 Subject: [PATCH] self test --- example/README.md | 7 +-- example/self-test.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ lis3dh.c | 5 ++- lis3dh.h | 8 ++++ 4 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 example/self-test.c diff --git a/example/README.md b/example/README.md index a8aec4b..345e355 100644 --- a/example/README.md +++ b/example/README.md @@ -35,9 +35,6 @@ The LIS3DH can apply its built-in high-pass filter to samples [regular reading, See files: `filter-normal.c`, and `filter-reference.c`. -### file: simple.c -Basic example of how to use this device - # FIFO Instead of polling for every single [x y z] set, a FIFO with programmable capacity ("watermark") can be used, and then dumped into memory once full. @@ -59,6 +56,10 @@ Note: FIFO will not trigger a watermark interrupt (`pin1.wtm`) if the FIFO size Note: to sample data faster than 200 Hz, it is necessary to use the regular data polling functionality using `lis3dh_read()` with the appropriate configuration. See files `simple.c` and `fast.c` for examples. +### file: self-test.c + +Run a device self-test to see if the device is within spec. Mine apparently isn't. (must be at-rest during test). + ### file: single-click.c Set up single-click detection (no latching interrupt possible) diff --git a/example/self-test.c b/example/self-test.c new file mode 100644 index 0000000..1f1eba2 --- /dev/null +++ b/example/self-test.c @@ -0,0 +1,103 @@ +#define _GNU_SOURCE +#include /* usleep() */ +#include +#include +#include "lis3dh.h" +#include "i2c.h" + +/* table 4 of datasheet */ +#define ST_MIN 17 +#define ST_MAX 360 + +/* AN3308 suggests 5 */ +#define ITERATIONS 5 + +int main() { + + lis3dh_t lis; + int32_t x_nost, y_nost, z_nost; /* store avg of measurements before self-test */ + int32_t x_st, y_st, z_st; /* store avg of self-test measurements */ + int32_t xd, yd, zd; /* differences */ + int i; + + lis.dev.init = i2c_init; + lis.dev.read = i2c_read; + lis.dev.write = i2c_write; + lis.dev.sleep = usleep; + lis.dev.deinit = i2c_deinit; + + x_nost = y_nost = z_nost = 0; + x_st = y_st = z_st = 0; + xd = yd = zd = 0; + + /* initialise LIS3DH struct */ + if (lis3dh_init(&lis)) { + /* error handling */ + } + + /* reset device just in case */ + if (lis3dh_reset(&lis)) { + /* error handling */ + } + + lis.cfg.mode = LIS3DH_MODE_NORMAL; + lis.cfg.range = LIS3DH_FS_2G; + lis.cfg.rate = LIS3DH_ODR_50_HZ; + + lis3dh_configure(&lis); + + /* discard first couple of samples as datasheet suggests they are wrong/noisy */ + for(i=0; i<15; i++) lis3dh_read(&lis); + + for(i=0; icfg.rate << 4) | 0x07; ctrl_reg2 = 0; ctrl_reg3 = 0; - ctrl_reg4 = (lis3dh->cfg.range << 4); + ctrl_reg4 = (lis3dh->cfg.range << 4) | (lis3dh->cfg.spi3w & 1); ctrl_reg5 = 0; ctrl_reg6 = 0; fifo_ctrl_reg = 0; @@ -74,6 +74,9 @@ int lis3dh_configure(lis3dh_t *lis3dh) { ctrl_reg0 = 0; temp_cfg_reg = 0; + /* set self-test bits */ + ctrl_reg4 |= (lis3dh->cfg.self_test & 0x03) << 1; + /* determine whether to enable ADC or TEMP sensor */ temp_cfg_reg |= (lis3dh->cfg.en_adc & 1) << 7; temp_cfg_reg |= (lis3dh->cfg.en_temp & 1) << 6; diff --git a/lis3dh.h b/lis3dh.h index 3ebd69b..2a33a35 100644 --- a/lis3dh.h +++ b/lis3dh.h @@ -112,6 +112,10 @@ #define LIS3DH_FILTER_CUTOFF_2 0x02 #define LIS3DH_FILTER_CUTOFF_1 0x03 /* lowest freq */ +/* Positive and negative axis self-test */ +#define LIS3DH_SELF_TEST_0 0x01 +#define LIS3DH_SELF_TEST_1 0x02 + /* Note: IA{1,2} is interrupt activity {1,2} or interrupt generators */ /* user provided functions, init and deinit can be set to NULL and won't be used */ @@ -226,6 +230,8 @@ struct lis3dh_config { * - time_window * - time_latency * used in CLICK) + * + * this is the "1[LSb]" in act_dur calc */ uint8_t int1_dur; /* 7-bit INT 1 duration value */ uint8_t int2_dur; /* 7-bit INT 2 duration value */ @@ -242,6 +248,8 @@ struct lis3dh_config { uint8_t sdo_pullup; /* Use pull-up on SDO. default 0 use */ uint8_t en_adc; /* enable ADC */ uint8_t en_temp; /* enable temp sensor on ADC 3 */ + uint8_t spi3w; /* set to 1 to enable 3-way SPI, default 0 */ + uint8_t self_test; /* set self-test mode */ uint8_t reference; /* HP filter reference */ };