self test

This commit is contained in:
William Clark 2024-01-08 06:16:29 +00:00
parent 898a0f7ee2
commit 7466b91fe3
4 changed files with 119 additions and 4 deletions

View File

@ -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)

103
example/self-test.c Normal file
View File

@ -0,0 +1,103 @@
#define _GNU_SOURCE
#include <unistd.h> /* usleep() */
#include <stdio.h>
#include <stdlib.h>
#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; i<ITERATIONS; i++) {
lis3dh_read(&lis);
x_nost += lis.acc.x;
y_nost += lis.acc.y;
z_nost += lis.acc.z;
}
x_nost /= ITERATIONS;
y_nost /= ITERATIONS;
z_nost /= ITERATIONS;
lis.cfg.self_test = LIS3DH_SELF_TEST_0;
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; i<ITERATIONS; i++) {
lis3dh_read(&lis);
x_st += lis.acc.x;
y_st += lis.acc.y;
z_st += lis.acc.z;
}
x_st /= ITERATIONS;
y_st /= ITERATIONS;
z_st /= ITERATIONS;
xd = abs(x_st - x_nost);
yd = abs(y_st - y_nost);
zd = abs(z_st - z_nost);
printf("variance min=%d, max=%d\n", ST_MIN, ST_MAX);
printf("xd=%d yd=%d zd=%d\n", xd, yd, zd);
if ((ST_MIN <= xd && xd <= ST_MAX) && (ST_MIN <= yd && yd <= ST_MAX) && (ST_MIN <= zd && zd <= ST_MAX)) {
puts("Pass");
} else {
puts("Fail");
}
lis3dh_reset(&lis);
/* deinitalise struct */
if (lis3dh_deinit(&lis)) {
/* error handling */
}
return 0;
}

View File

@ -57,7 +57,7 @@ int lis3dh_configure(lis3dh_t *lis3dh) {
ctrl_reg1 = (lis3dh->cfg.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;

View File

@ -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 */
};