rework poll/read and amend examples
This commit is contained in:
parent
0a0cf2a7aa
commit
8648c517f6
@ -7,13 +7,12 @@ Basic example of how to use this device
|
||||
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. All FIFO readings use 10-bit resolution regardless of the mode set in `cfg.mode`. The watermark level can be adjusted to a value [1-32] (0 disables FIFO) by modifying the `cfg.fifo.size` property before calling `lis3dh_configure()`.
|
||||
|
||||
The LIS3DH can optionally apply a HP filter on the sampling to reduce 'static acceleration' from the data.
|
||||
|
||||
Note: `pin1.wtm` will NOT trigger if the FIFO size is 32 (default). Use `pin1.overrun` if you want an interrupt when the FIFO is full at full size (32.)
|
||||
Note: it seems that the highest data rate (ODR) possible using FIFO is 200 Hz, faster than that and it does not want to restart after 1 FIFO buffer. To faster faster, such as at the advertised 5 KHz rate, you have to use `lis3dh_read()`.
|
||||
|
||||
### file: interrupts.c
|
||||
This device supports two different interrupt "output pins," `INT1` and `INT2`. The appropriate flag must be set in either `cfg.pin1` or `cfg.pin2` and the interrupt source must be configured to trigger into `INT1` or `INT2`.
|
||||
|
||||
This file contains example code that listens and receives an interrupt when the FIFO watermark is reached i.e. it is full.
|
||||
This file contains example code that listens and receives an interrupt when the FIFO overrun is reached i.e. it is full. Note: `pin1.wtm` will NOT trigger if the FIFO size is 32 (default). Use `pin1.overrun` if you want an interrupt when the FIFO is full at full size (32.)
|
||||
|
||||
### file: single-click.c
|
||||
|
||||
|
@ -36,15 +36,8 @@ int main() {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* poll fifo register until it reports that the watermark level has
|
||||
been reached, or that it has overwritten old data, whichever
|
||||
happens first. */
|
||||
if (lis3dh_poll_fifo(&lis)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* read as many [x y z] sets as specified by watermark level (fth) */
|
||||
/* copy them to the fifo data struct given below as `fifo' */
|
||||
/* read as many [x y z] sets as specified by watermark level (size) default max/32 */
|
||||
/* copy them to the fifo data struct given below as `data' */
|
||||
if (lis3dh_read_fifo(&lis, &data)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
@ -33,11 +33,6 @@ int main() {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* poll STATUS_REG for new [x y z] data ready */
|
||||
if (lis3dh_poll(&lis)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* read latest [x y z] data, store in the `lis' struct's `acc' field */
|
||||
if (lis3dh_read(&lis)) {
|
||||
/* error handling */
|
||||
|
70
lis3dh.c
70
lis3dh.c
@ -2,6 +2,7 @@
|
||||
#include <string.h>
|
||||
#include "lis3dh.h"
|
||||
#include "registers.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
int lis3dh_init(lis3dh_t *lis3dh) {
|
||||
@ -205,32 +206,6 @@ int lis3dh_configure(lis3dh_t *lis3dh) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* should always return something with valid start configuration */
|
||||
int lis3dh_poll(lis3dh_t *lis3dh) {
|
||||
uint8_t status;
|
||||
int err = 0;
|
||||
|
||||
do {
|
||||
lis3dh->dev.sleep(1000); /* 1 ms */
|
||||
err |= lis3dh->dev.read(REG_STATUS_REG, &status, 1);
|
||||
} while (!err && !((status >> 3) & 1));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* assume fifo configured */
|
||||
int lis3dh_poll_fifo(lis3dh_t *lis3dh) {
|
||||
uint8_t src;
|
||||
int err = 0;
|
||||
|
||||
do {
|
||||
lis3dh->dev.sleep(1000); /* 1 ms */
|
||||
err |= lis3dh->dev.read(REG_FIFO_SRC_REG, &src, 1);
|
||||
} while (!err && !(src >> 6));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* the real size of the int you get back from reading the acc u16
|
||||
depends on the power mode.
|
||||
shift down the 16 bit word by this amount: */
|
||||
@ -255,17 +230,22 @@ static uint8_t acc_sensitivity(uint8_t mode, uint8_t range) {
|
||||
}
|
||||
}
|
||||
|
||||
/* read a single [x y z] set. Assume configured and poll'd */
|
||||
/* read a single [x y z] set. */
|
||||
int lis3dh_read(lis3dh_t *lis3dh) {
|
||||
uint8_t data[6];
|
||||
uint8_t shift, sens;
|
||||
uint8_t shift, sens, status;
|
||||
int err = 0;
|
||||
|
||||
shift = acc_shift(lis3dh->cfg.mode);
|
||||
sens = acc_sensitivity(lis3dh->cfg.mode, lis3dh->cfg.range);
|
||||
|
||||
err |= lis3dh->dev.read(REG_OUT_X_L, data, 6);
|
||||
/* poll STATUS_REG until new data is available */
|
||||
do {
|
||||
err |= lis3dh->dev.read(REG_STATUS_REG, &status, 1);
|
||||
lis3dh->dev.sleep(1000);
|
||||
} while ((!LIS3DH_STATUS_ZYXDA(status) || !LIS3DH_STATUS_ZYXOR(status)) && !err);
|
||||
|
||||
err |= lis3dh->dev.read(REG_OUT_X_L, data, 6);
|
||||
lis3dh->acc.x = ((int16_t)(data[1] | data[0] << 8) >> shift) * sens;
|
||||
lis3dh->acc.y = ((int16_t)(data[3] | data[2] << 8) >> shift) * sens;
|
||||
lis3dh->acc.z = ((int16_t)(data[5] | data[4] << 8) >> shift) * sens;
|
||||
@ -274,24 +254,34 @@ int lis3dh_read(lis3dh_t *lis3dh) {
|
||||
}
|
||||
|
||||
/* assume fifo has been configured and poll'd */
|
||||
/* wait until FIFO is NOT empty, then */
|
||||
/* read groups of the 6 OUT bytes until EMPTY flag in FIFO_SRC is set */
|
||||
int lis3dh_read_fifo(lis3dh_t *lis3dh, struct lis3dh_fifo_data *fifo) {
|
||||
uint8_t data[192]; /* max size */
|
||||
uint8_t sens;
|
||||
uint8_t data[6]; /* max size */
|
||||
uint8_t sens, fifo_src;
|
||||
int err = 0;
|
||||
int i, idx;
|
||||
int idx = 0;
|
||||
|
||||
/* wait until there is at least 1 unread sample in the FIFO */
|
||||
/* otherwise can cause problems at really fast ODRs and calling this */
|
||||
/* function in a loop without delays. */
|
||||
do {
|
||||
err |= lis3dh->dev.read(REG_FIFO_SRC_REG, &fifo_src, 1);
|
||||
lis3dh->dev.sleep(1000);
|
||||
} while (!LIS3DH_FIFO_SRC_UNREAD(fifo_src) && !err);
|
||||
|
||||
/* FIFO is always 10-bit / normal mode */
|
||||
sens = acc_sensitivity(LIS3DH_MODE_NORMAL, lis3dh->cfg.range);
|
||||
|
||||
fifo->size = lis3dh->cfg.fifo.size;
|
||||
do {
|
||||
err |= lis3dh->dev.read(REG_OUT_X_L, data, 6);
|
||||
err |= lis3dh->dev.read(REG_FIFO_SRC_REG, &fifo_src, 1);
|
||||
fifo->x[idx] = ((int16_t)(data[1] | data[0] << 8) >> 6) * sens;
|
||||
fifo->y[idx] = ((int16_t)(data[3] | data[2] << 8) >> 6) * sens;
|
||||
fifo->z[idx] = ((int16_t)(data[5] | data[4] << 8) >> 6) * sens;
|
||||
} while (idx++ < lis3dh->cfg.fifo.size - 1 && !LIS3DH_FIFO_SRC_EMPTY(fifo_src) && !err);
|
||||
|
||||
err |= lis3dh->dev.read(REG_OUT_X_L, data, fifo->size * 6);
|
||||
|
||||
for (i=0, idx=0; i<fifo->size * 6; i+=6, idx++) {
|
||||
fifo->x[idx] = ((int16_t)(data[i+1] | data[i+0] << 8) >> 6) * sens;
|
||||
fifo->y[idx] = ((int16_t)(data[i+3] | data[i+2] << 8) >> 6) * sens;
|
||||
fifo->z[idx] = ((int16_t)(data[i+5] | data[i+4] << 8) >> 6) * sens;
|
||||
}
|
||||
fifo->size = idx;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
18
lis3dh.h
18
lis3dh.h
@ -20,6 +20,22 @@
|
||||
#define LIS3DH_CLICK_SCLICK(c) (!!(c & 0x10)) /* Single-click det. enabled */
|
||||
#define LIS3DH_CLICK_DCLICK(c) (!!(c & 0x20)) /* Double-click det. enabled */
|
||||
|
||||
/* macros for checking FIFO_SRC register */
|
||||
#define LIS3DH_FIFO_SRC_UNREAD(c) (c & 0x1F) /* FSS / current unread samples in FIFO */
|
||||
#define LIS3DH_FIFO_SRC_EMPTY(c) (!!(c & 0x20)) /* FIFO is empty */
|
||||
#define LIS3DH_FIFO_SRC_OVRN(c) (!!(c & 0x40)) /* FIFO has overrun (full 32) */
|
||||
#define LIS3DH_FIFO_SRC_WTM(c) (!!(c & 0x80)) /* FIFO watermark hit (not full 32) */
|
||||
|
||||
/* macros for checking STATUS register */
|
||||
#define LIS3DH_STATUS_XDA(c) (!!(c & 0x01)) /* X-axis data available */
|
||||
#define LIS3DH_STATUS_YDA(c) (!!(c & 0x02)) /* Y-axis data available */
|
||||
#define LIS3DH_STATUS_ZDA(c) (!!(c & 0x04)) /* Z-axis data available */
|
||||
#define LIS3DH_STATUS_ZYXDA(c) (!!(c & 0x08)) /* {Z,Y,X}-axis data available */
|
||||
#define LIS3DH_STATUS_XOR(c) (!!(c & 0x10)) /* X-axis data has overrun (been overwritten) */
|
||||
#define LIS3DH_STATUS_YOR(c) (!!(c & 0x20)) /* Y-axis data has overrun (been overwritten) */
|
||||
#define LIS3DH_STATUS_ZOR(c) (!!(c & 0x40)) /* Z-axis data has overrun (been overwritten) */
|
||||
#define LIS3DH_STATUS_ZYXOR(c) (!!(c & 0x80)) /* {Z,Y,X}-axis data has overrun (been overwritten) */
|
||||
|
||||
/* rates */
|
||||
/* all power modes */
|
||||
#define LIS3DH_ODR_POWEROFF 0x00
|
||||
@ -282,9 +298,7 @@ struct lis3dh_fifo_data {
|
||||
int lis3dh_init(lis3dh_t *lis3dh);
|
||||
int lis3dh_deinit(lis3dh_t *lis3dh);
|
||||
int lis3dh_configure(lis3dh_t *lis3dh);
|
||||
int lis3dh_poll(lis3dh_t *lis3dh);
|
||||
int lis3dh_read(lis3dh_t *lis3dh);
|
||||
int lis3dh_poll_fifo(lis3dh_t *lis3dh);
|
||||
int lis3dh_read_fifo(lis3dh_t *lis3dh, struct lis3dh_fifo_data *fifo);
|
||||
int lis3dh_read_int1(lis3dh_t *lis3dh);
|
||||
int lis3dh_read_int2(lis3dh_t *lis3dh);
|
||||
|
80
main.c
80
main.c
@ -4,17 +4,11 @@
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include "lis3dh.h"
|
||||
#include "interrupt.h"
|
||||
#include "spi.h"
|
||||
|
||||
/* GPIO 12 or Pin 32 */
|
||||
#define GPIO_INTERRUPT_PIN 12
|
||||
|
||||
int main() {
|
||||
|
||||
lis3dh_t lis;
|
||||
struct lis3dh_fifo_data fifo;
|
||||
int i;
|
||||
|
||||
lis.dev.init = spi_init;
|
||||
lis.dev.read = spi_read;
|
||||
@ -22,68 +16,22 @@ int main() {
|
||||
lis.dev.sleep = usleep;
|
||||
lis.dev.deinit = spi_deinit;
|
||||
|
||||
/* initalise LIS3DH struct */
|
||||
if (lis3dh_init(&lis)) {
|
||||
/* error handling */
|
||||
lis3dh_init(&lis);
|
||||
lis3dh_reset(&lis);
|
||||
|
||||
lis.cfg.mode = LIS3DH_MODE_LP;
|
||||
lis.cfg.range = LIS3DH_FS_16G;
|
||||
lis.cfg.rate = LIS3DH_ODR_LP_5376_HZ;
|
||||
|
||||
lis3dh_configure(&lis);
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
lis3dh_read(&lis);
|
||||
printf("x: %4.4d mg, y: %4.4d mg, z: %4.4d mg\n", lis.acc.x, lis.acc.y, lis.acc.z);
|
||||
}
|
||||
|
||||
/* reset device just in case */
|
||||
if (lis3dh_reset(&lis)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* register interrupt */
|
||||
if (int_register(GPIO_INTERRUPT_PIN)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
lis.cfg.mode = LIS3DH_MODE_NORMAL;
|
||||
lis.cfg.range = LIS3DH_FS_2G;
|
||||
lis.cfg.rate = LIS3DH_ODR_100_HZ;
|
||||
lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM;
|
||||
lis.cfg.fifo.trig = LIS3DH_FIFO_TRIG_INT1; /* trigger interrupt into int pin1 */
|
||||
lis.cfg.pin1.overrun = 1; /* trigger upon FIFO overrun */
|
||||
|
||||
/* set up HP filter to remove DC component */
|
||||
lis.cfg.filter.mode = LIS3DH_FILTER_MODE_NORMAL_REF;
|
||||
lis.cfg.filter.cutoff = LIS3DH_FILTER_CUTOFF_4;
|
||||
lis.cfg.filter.fds = 1; /* remove this line, or set to 1 to enable filter */
|
||||
|
||||
/* write device config */
|
||||
if (lis3dh_configure(&lis)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* read REFERENCE to set filter to current accel field */
|
||||
if (lis3dh_reference(&lis)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* wait for interrupt from LIS3DH */
|
||||
if (int_poll(GPIO_INTERRUPT_PIN)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* read as many [x y z] sets as specified by watermark level (fth) */
|
||||
/* copy them to the fifo data struct given below as `fifo' */
|
||||
if (lis3dh_read_fifo(&lis, &fifo)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* above function also writes out the qty of [x y z] sets stored in `fifo' */
|
||||
for(i=0; i<fifo.size; i++) {
|
||||
printf("x: %d mg, y: %d mg, z: %d mg\n", fifo.x[i], fifo.y[i], fifo.z[i]);
|
||||
}
|
||||
|
||||
/* unregister interrupt */
|
||||
if (int_unregister(GPIO_INTERRUPT_PIN)) {
|
||||
/* error handling */
|
||||
}
|
||||
|
||||
/* deinitalise struct */
|
||||
if (lis3dh_deinit(&lis)) {
|
||||
/* error handling */
|
||||
}
|
||||
lis3dh_deinit(&lis);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user