From 78cde50f13b0e4fa1578533556fbf4843bd5f67e Mon Sep 17 00:00:00 2001 From: William Clark Date: Mon, 1 Jan 2024 12:05:53 +0000 Subject: [PATCH] single-click detection & fixed examples --- README.md | 12 ++- example/README.md | 10 ++- example/{fifo => }/fifo.c | 0 example/fifo/fifo2.c | 52 ------------- example/{interrupts => }/interrupts.c | 12 ++- example/{simple => }/simple.c | 5 ++ example/simple/simple2.c | 48 ------------ example/single-click.c | 107 ++++++++++++++++++++++++++ 8 files changed, 137 insertions(+), 109 deletions(-) rename example/{fifo => }/fifo.c (100%) delete mode 100644 example/fifo/fifo2.c rename example/{interrupts => }/interrupts.c (75%) rename example/{simple => }/simple.c (87%) delete mode 100644 example/simple/simple2.c create mode 100644 example/single-click.c diff --git a/README.md b/README.md index 5256e8e..ef93a33 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,19 @@ A C89 driver for the 3-axis accelerometer LIS3DH. Supports both i2c and SPI. > ### Features -> - FIFO of varying watermark level, up to 32 -> - HP filter (4 c/o freq) +> - FIFO +> - HP filter > - 2G, 4G, 8G and 16G > - All power modes -> - Interrupt generation (partial) +> - Interrupt generation > - Free-fall detection (soon) -> - Single and double click detection (soon) +> - Single-click detection +> - Double-click detection (soon) > - 4D/6D orientation detection (soon) +## Examples +See the examples/ dir for complete code examples + ## Implementation This driver requires the user to provide pointers to the following abstractely named functions: diff --git a/example/README.md b/example/README.md index 980b52f..4e26d2f 100644 --- a/example/README.md +++ b/example/README.md @@ -1,12 +1,16 @@ # lis3dh/example -### simple/ +### simple.c Basic examples of how to use this device -### fifo/ +### fifo.c Instead of polling for every single [x y z] set, a FIFO with programmable capacity ("watermark") can be used like such: All FIFO readings use 10-bit resolution regardless of the mode set in `lis.cfg.mode`. The watermark level can also be adjusted to a value [0-31] inclusive by modifying the `lis.cfg.fifo.fth` property before calling configure(). The LIS3DH can optionally apply a HP filter on the sample data. It can be used to greatly reduce the "DC acceleration" present. -### interrupts/ +### interrupts.c The LIS3DH supports two different interrupt "output pins," `INT1` and `INT2`. The appropriate flag must be set in either `cfg.int1` or `cfg.int2` (only one of such flags can be set at a time!) and the interrupt source must be configured to trigger into `INT1` or `INT2`. Below is example code that listens and receives an interrupt when the FIFO watermark is reached i.e. it is full. + +### single-click.c + +Set up single-click detection using HP filter \ No newline at end of file diff --git a/example/fifo/fifo.c b/example/fifo.c similarity index 100% rename from example/fifo/fifo.c rename to example/fifo.c diff --git a/example/fifo/fifo2.c b/example/fifo/fifo2.c deleted file mode 100644 index ffe26a3..0000000 --- a/example/fifo/fifo2.c +++ /dev/null @@ -1,52 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include "lis3dh.h" -#include "i2c.h" - -int main() { - - lis3dh_t lis; - struct lis3dh_fifo_data data; - 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; - - if (lis3dh_init(&lis)) { - /* error handling */ - } - - lis.cfg.mode = LIS3DH_MODE_HR; - lis.cfg.range = LIS3DH_FS_4G; - lis.cfg.rate = LIS3DH_ODR_100_HZ; - lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_NORMAL; - lis.cfg.filter.mode = LIS3DH_FILTER_MODE_AUTORESET; - lis.cfg.filter.cutoff = LIS3DH_FILTER_CUTOFF_8; - - if (lis3dh_configure(&lis)) { - /* error handling */ - } - - if (lis3dh_poll_fifo(&lis)) { - /* error handling */ - } - - if (lis3dh_read_fifo(&lis, &data)) { - /* error handling */ - } - - /* read out fifo buffer data */ - for(i=0; i -#include -#include "lis3dh.h" -#include "i2c.h" - -int main() { - - lis3dh_t lis; - 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; - - if (lis3dh_init(&lis)) { - /* error handling */ - } - - lis.cfg.mode = LIS3DH_MODE_HR; - lis.cfg.range = LIS3DH_FS_4G; - lis.cfg.rate = LIS3DH_ODR_100_HZ; - - if (lis3dh_configure(&lis)) { - /* error handling */ - } - - for(i=0; i<10; i++) { - - if (lis3dh_poll(&lis)) { - /* error handling */ - } - - if (lis3dh_read(&lis)) { - /* error handling */ - } - - printf("x: %f, y: %f, z: %f\n", lis.acc.x, lis.acc.y, lis.acc.z); - } - - if (lis3dh_deinit(&lis)) { - /* error handling */ - } - - return 0; -} \ No newline at end of file diff --git a/example/single-click.c b/example/single-click.c new file mode 100644 index 0000000..6ca0524 --- /dev/null +++ b/example/single-click.c @@ -0,0 +1,107 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include "lis3dh.h" +#include "interrupt.h" +#include "i2c.h" + +#define GPIO_INTERRUPT_PIN_INT1 12 + +int main() { + + lis3dh_t lis; + + /* set fn ptrs to rw on bus (i2c or SPI) */ + lis.dev.init = i2c_init; + lis.dev.read = i2c_read; + lis.dev.write = i2c_write; + lis.dev.sleep = usleep; + lis.dev.deinit = i2c_deinit; + + /* initialise LIS3DH struct */ + if (lis3dh_init(&lis)) { + /* error handling */ + } + + /* reset device because it sometimes corrupts itself */ + if (lis3dh_reset(&lis)) { + /* error handling */ + } + + /* register interrupt */ + if (int_register(GPIO_INTERRUPT_PIN_INT1)) { + /* error handling */ + } + + /* set up config */ + lis.cfg.mode = LIS3DH_MODE_HR; + lis.cfg.range = LIS3DH_FS_2G; + lis.cfg.rate = LIS3DH_ODR_400_HZ; /* minimum recommended ODR */ + lis.cfg.filter.mode = LIS3DH_FILTER_MODE_NORMAL; + lis.cfg.filter.cutoff = LIS3DH_FILTER_CUTOFF_8; + lis.cfg.filter.click = 1; /* enable filtering for CLICK function */ + lis.cfg.click.xs = 1; /* enable X axis single click */ + lis.cfg.click.ys = 1; /* enable Y axis single click */ + lis.cfg.click.zs = 1; /* enable Z axis single click */ + lis.cfg.pin1.click = 1; /* enable click int src through pin1 */ + lis.cfg.pin1.latch = 1; /* latch this request I think */ + + /* 1 LSb = 16 mg @ FS_2G + * so a 0.072g 'shock' is 72/16 = 4.5 + * However, the device can have up to +- 40mg read error + * 0.112g => 112/16 = 15 + */ + lis.cfg.click_ths = 7; /* pretty sensitive */ + + /* the 'shock' must be gone after 10 ms let's say .. */ + /* Duration time is measured in N/ODR where: + * --- N = The content of the intX_dur integer + * --- ODR = the data rate, eg 100, 400... + * [ODR] [1 LSb in milliseconds] + * 400 2.5 + * + * At 400 ODR, 10ms/2.5ms = 4 + */ + lis.cfg.time_limit = 4; + + /* write device config */ + if (lis3dh_configure(&lis)) { + /* error handling */ + } + + for(;;) { + + /* poll interrupt on INT1 pin */ + if (int_poll(GPIO_INTERRUPT_PIN_INT1)) { + /* error handling */ + } + + /* read CLICK_SRC when interrupt has fired */ + if (lis3dh_read_click(&lis)) { + /* error handling */ + } + + /* print data gathered from CLICK_SRC */ + printf("Click: X=%d, Y=%d, Z=%d, Sign=%d, S_en=%d, D_en=%d\n", + LIS3DH_CLICK_SRC_X(lis.src.click), + LIS3DH_CLICK_SRC_Y(lis.src.click), + LIS3DH_CLICK_SRC_Z(lis.src.click), + LIS3DH_CLICK_SIGN(lis.src.click), + LIS3DH_CLICK_SCLICK(lis.src.click), + LIS3DH_CLICK_DCLICK(lis.src.click)); + } + + /* unregister interrupt */ + if (int_unregister(GPIO_INTERRUPT_PIN_INT1)) { + /* error handling */ + } + + /* deinitalise struct */ + if (lis3dh_deinit(&lis)) { + /* error handling */ + } + + return 0; +} \ No newline at end of file