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()`.
|
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.
|
The LIS3DH can optionally apply a HP filter on the sampling to reduce 'static acceleration' from the data.
|
||||||
|
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()`.
|
||||||
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: interrupts.c
|
### 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 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
|
### file: single-click.c
|
||||||
|
|
||||||
|
@ -36,15 +36,8 @@ int main() {
|
|||||||
/* error handling */
|
/* error handling */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* poll fifo register until it reports that the watermark level has
|
/* read as many [x y z] sets as specified by watermark level (size) default max/32 */
|
||||||
been reached, or that it has overwritten old data, whichever
|
/* copy them to the fifo data struct given below as `data' */
|
||||||
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' */
|
|
||||||
if (lis3dh_read_fifo(&lis, &data)) {
|
if (lis3dh_read_fifo(&lis, &data)) {
|
||||||
/* error handling */
|
/* error handling */
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,6 @@ int main() {
|
|||||||
/* error handling */
|
/* 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 */
|
/* read latest [x y z] data, store in the `lis' struct's `acc' field */
|
||||||
if (lis3dh_read(&lis)) {
|
if (lis3dh_read(&lis)) {
|
||||||
/* error handling */
|
/* error handling */
|
||||||
|
70
lis3dh.c
70
lis3dh.c
@ -2,6 +2,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "lis3dh.h"
|
#include "lis3dh.h"
|
||||||
#include "registers.h"
|
#include "registers.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
int lis3dh_init(lis3dh_t *lis3dh) {
|
int lis3dh_init(lis3dh_t *lis3dh) {
|
||||||
@ -205,32 +206,6 @@ int lis3dh_configure(lis3dh_t *lis3dh) {
|
|||||||
return err;
|
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
|
/* the real size of the int you get back from reading the acc u16
|
||||||
depends on the power mode.
|
depends on the power mode.
|
||||||
shift down the 16 bit word by this amount: */
|
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) {
|
int lis3dh_read(lis3dh_t *lis3dh) {
|
||||||
uint8_t data[6];
|
uint8_t data[6];
|
||||||
uint8_t shift, sens;
|
uint8_t shift, sens, status;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
shift = acc_shift(lis3dh->cfg.mode);
|
shift = acc_shift(lis3dh->cfg.mode);
|
||||||
sens = acc_sensitivity(lis3dh->cfg.mode, lis3dh->cfg.range);
|
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.x = ((int16_t)(data[1] | data[0] << 8) >> shift) * sens;
|
||||||
lis3dh->acc.y = ((int16_t)(data[3] | data[2] << 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;
|
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 */
|
/* 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) {
|
int lis3dh_read_fifo(lis3dh_t *lis3dh, struct lis3dh_fifo_data *fifo) {
|
||||||
uint8_t data[192]; /* max size */
|
uint8_t data[6]; /* max size */
|
||||||
uint8_t sens;
|
uint8_t sens, fifo_src;
|
||||||
int err = 0;
|
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 */
|
/* FIFO is always 10-bit / normal mode */
|
||||||
sens = acc_sensitivity(LIS3DH_MODE_NORMAL, lis3dh->cfg.range);
|
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);
|
fifo->size = idx;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
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_SCLICK(c) (!!(c & 0x10)) /* Single-click det. enabled */
|
||||||
#define LIS3DH_CLICK_DCLICK(c) (!!(c & 0x20)) /* Double-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 */
|
/* rates */
|
||||||
/* all power modes */
|
/* all power modes */
|
||||||
#define LIS3DH_ODR_POWEROFF 0x00
|
#define LIS3DH_ODR_POWEROFF 0x00
|
||||||
@ -282,9 +298,7 @@ struct lis3dh_fifo_data {
|
|||||||
int lis3dh_init(lis3dh_t *lis3dh);
|
int lis3dh_init(lis3dh_t *lis3dh);
|
||||||
int lis3dh_deinit(lis3dh_t *lis3dh);
|
int lis3dh_deinit(lis3dh_t *lis3dh);
|
||||||
int lis3dh_configure(lis3dh_t *lis3dh);
|
int lis3dh_configure(lis3dh_t *lis3dh);
|
||||||
int lis3dh_poll(lis3dh_t *lis3dh);
|
|
||||||
int lis3dh_read(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_fifo(lis3dh_t *lis3dh, struct lis3dh_fifo_data *fifo);
|
||||||
int lis3dh_read_int1(lis3dh_t *lis3dh);
|
int lis3dh_read_int1(lis3dh_t *lis3dh);
|
||||||
int lis3dh_read_int2(lis3dh_t *lis3dh);
|
int lis3dh_read_int2(lis3dh_t *lis3dh);
|
||||||
|
80
main.c
80
main.c
@ -4,17 +4,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "lis3dh.h"
|
#include "lis3dh.h"
|
||||||
#include "interrupt.h"
|
|
||||||
#include "spi.h"
|
#include "spi.h"
|
||||||
|
|
||||||
/* GPIO 12 or Pin 32 */
|
|
||||||
#define GPIO_INTERRUPT_PIN 12
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
lis3dh_t lis;
|
lis3dh_t lis;
|
||||||
struct lis3dh_fifo_data fifo;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
lis.dev.init = spi_init;
|
lis.dev.init = spi_init;
|
||||||
lis.dev.read = spi_read;
|
lis.dev.read = spi_read;
|
||||||
@ -22,68 +16,22 @@ int main() {
|
|||||||
lis.dev.sleep = usleep;
|
lis.dev.sleep = usleep;
|
||||||
lis.dev.deinit = spi_deinit;
|
lis.dev.deinit = spi_deinit;
|
||||||
|
|
||||||
/* initalise LIS3DH struct */
|
lis3dh_init(&lis);
|
||||||
if (lis3dh_init(&lis)) {
|
lis3dh_reset(&lis);
|
||||||
/* error handling */
|
|
||||||
|
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 */
|
lis3dh_deinit(&lis);
|
||||||
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 */
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user