fix reg order and longer sleep after configure(). Amend notes on usage

This commit is contained in:
William Clark 2024-01-06 01:36:35 +00:00
parent 485922d898
commit 0a0cf2a7aa
6 changed files with 61 additions and 45 deletions

View File

@ -1,5 +0,0 @@
SPI does not work properly
-- writes may go to wrong addr
-- FIFO read out addr 6 loop seems to not work
FIFO WTM/OVRN on INT1 does not fire when FTH (watermark) is not 31 (default/max)

View File

@ -21,7 +21,7 @@ See the `examples/` dir for complete code examples
## Implementation ## Implementation
This driver requires the user to implement the following interface functions: This driver requires the user to implement the following interface functions:
This project has example interface code for I2C and SPI used on Raspberry Pi 4. This project has example interface code for I2C and SPI used on Raspberry Pi 4, and for STM32.
```c ```c
/* initialise the "interface" */ /* initialise the "interface" */
int init(void); int init(void);
@ -40,8 +40,7 @@ If `init` and/or `deinit` are set to `NULL`, they will be ignored. Useful on mic
--- ---
### Using i2c on STM32 ### STM32
Example code because I couldn't previously find working examples.
```c ```c
#define LIS3DH_I2C_ADDR 0x18 #define LIS3DH_I2C_ADDR 0x18

View File

@ -4,10 +4,12 @@
Basic example of how to use this device Basic example of how to use this device
### file: fifo.c ### file: fifo.c
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 `lis.cfg.mode`. The watermark level can be adjusted to a value [1-32] (0 disables FIFO) by modifying the `lis.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: `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`.

View File

@ -42,8 +42,7 @@ int main() {
lis.cfg.rate = LIS3DH_ODR_100_HZ; lis.cfg.rate = LIS3DH_ODR_100_HZ;
lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM; lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM;
lis.cfg.fifo.trig = LIS3DH_FIFO_TRIG_INT1; /* trigger interrupt into int pin1 */ lis.cfg.fifo.trig = LIS3DH_FIFO_TRIG_INT1; /* trigger interrupt into int pin1 */
/*lis.cfg.fifo.size = 15;*/ lis.cfg.pin1.overrun = 1; /* trigger upon FIFO overrun */
lis.cfg.pin1.wtm = 1; /* trigger upon FIFO watermark level reached */
/* set up HP filter to remove DC component */ /* set up HP filter to remove DC component */
lis.cfg.filter.mode = LIS3DH_FILTER_MODE_NORMAL_REF; lis.cfg.filter.mode = LIS3DH_FILTER_MODE_NORMAL_REF;

View File

@ -147,7 +147,7 @@ int lis3dh_configure(lis3dh_t *lis3dh) {
fifo_ctrl_reg |= ((lis3dh->cfg.fifo.trig & 1) << 5); fifo_ctrl_reg |= ((lis3dh->cfg.fifo.trig & 1) << 5);
} }
/* set enable filter */ /* set enable filter if mode is set */
if (lis3dh->cfg.filter.mode != 0xFF) { if (lis3dh->cfg.filter.mode != 0xFF) {
ctrl_reg2 |= ((lis3dh->cfg.filter.mode & 0x03) << 6); ctrl_reg2 |= ((lis3dh->cfg.filter.mode & 0x03) << 6);
ctrl_reg2 |= ((lis3dh->cfg.filter.cutoff & 0x03) << 4); ctrl_reg2 |= ((lis3dh->cfg.filter.cutoff & 0x03) << 4);
@ -175,9 +175,10 @@ int lis3dh_configure(lis3dh_t *lis3dh) {
ctrl_reg0 |= 0x10; ctrl_reg0 |= 0x10;
ctrl_reg0 |= (lis3dh->cfg.sdo_pullup & 1) << 7; ctrl_reg0 |= (lis3dh->cfg.sdo_pullup & 1) << 7;
/* Registers have to be set in this order for SPI to function correctly */
err |= lis3dh->dev.write(REG_CTRL_REG4, ctrl_reg4); err |= lis3dh->dev.write(REG_CTRL_REG4, ctrl_reg4);
err |= lis3dh->dev.write(REG_CTRL_REG5, ctrl_reg5); err |= lis3dh->dev.write(REG_CTRL_REG5, ctrl_reg5);
err |= lis3dh->dev.write(REG_FIFO_CTRL_REG, fifo_ctrl_reg); err |= lis3dh->dev.write(REG_FIFO_CTRL_REG, fifo_ctrl_reg);
err |= lis3dh->dev.write(REG_INT1_CFG, int1_cfg); err |= lis3dh->dev.write(REG_INT1_CFG, int1_cfg);
err |= lis3dh->dev.write(REG_INT1_THS, int1_ths); err |= lis3dh->dev.write(REG_INT1_THS, int1_ths);
@ -194,16 +195,13 @@ int lis3dh_configure(lis3dh_t *lis3dh) {
err |= lis3dh->dev.write(REG_ACT_DUR, lis3dh->cfg.act_dur); err |= lis3dh->dev.write(REG_ACT_DUR, lis3dh->cfg.act_dur);
err |= lis3dh->dev.write(REG_TEMP_CFG_REG, temp_cfg_reg); err |= lis3dh->dev.write(REG_TEMP_CFG_REG, temp_cfg_reg);
err |= lis3dh->dev.write(REG_REFERENCE, lis3dh->cfg.reference); err |= lis3dh->dev.write(REG_REFERENCE, lis3dh->cfg.reference);
err |= lis3dh->dev.write(REG_CTRL_REG1, ctrl_reg1);
err |= lis3dh->dev.write(REG_CTRL_REG6, ctrl_reg6); err |= lis3dh->dev.write(REG_CTRL_REG6, ctrl_reg6);
err |= lis3dh->dev.write(REG_CTRL_REG0, ctrl_reg0); err |= lis3dh->dev.write(REG_CTRL_REG0, ctrl_reg0);
err |= lis3dh->dev.write(REG_CTRL_REG2, ctrl_reg2); err |= lis3dh->dev.write(REG_CTRL_REG2, ctrl_reg2);
err |= lis3dh->dev.write(REG_CTRL_REG3, ctrl_reg3); err |= lis3dh->dev.write(REG_CTRL_REG3, ctrl_reg3);
err |= lis3dh->dev.write(REG_CTRL_REG1, ctrl_reg1);
/* sleep for a period TBD ~ ODR */ lis3dh->dev.sleep(100000); /* 100 ms */
lis3dh->dev.sleep(1000); /* 50 ms */
return err; return err;
} }
@ -257,7 +255,7 @@ static uint8_t acc_sensitivity(uint8_t mode, uint8_t range) {
} }
} }
/* read a single [x y z] set. Assume configured and poll'd */
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;

73
main.c
View File

@ -1,14 +1,19 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include "lis3dh.h" #include "lis3dh.h"
#include "i2c.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 data; struct lis3dh_fifo_data fifo;
int i; int i;
lis.dev.init = spi_init; lis.dev.init = spi_init;
@ -17,49 +22,67 @@ int main() {
lis.dev.sleep = usleep; lis.dev.sleep = usleep;
lis.dev.deinit = spi_deinit; lis.dev.deinit = spi_deinit;
/* initialise LIS3DH struct */ /* initalise LIS3DH struct */
if (lis3dh_init(&lis)) { if (lis3dh_init(&lis)) {
puts("init()"); /* error handling */
} }
/* reset device just in case */ /* reset device just in case */
if (lis3dh_reset(&lis)) { if (lis3dh_reset(&lis)) {
puts("reset()"); /* error handling */
} }
lis.cfg.mode = LIS3DH_MODE_HR; /* register interrupt */
if (int_register(GPIO_INTERRUPT_PIN)) {
/* error handling */
}
lis.cfg.mode = LIS3DH_MODE_NORMAL;
lis.cfg.range = LIS3DH_FS_2G; lis.cfg.range = LIS3DH_FS_2G;
lis.cfg.rate = LIS3DH_ODR_400_HZ; lis.cfg.rate = LIS3DH_ODR_100_HZ;
lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM_TO_FIFO; lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM;
lis.cfg.fifo.size = 20; 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 */ /* write device config */
if (lis3dh_configure(&lis)) { if (lis3dh_configure(&lis)) {
puts("configure()"); /* error handling */
} }
A: /* read REFERENCE to set filter to current accel field */
/* poll fifo register until it reports that the watermark level has if (lis3dh_reference(&lis)) {
been reached, or that it has overwritten old data, whichever /* error handling */
happens first. */ }
if (lis3dh_poll_fifo(&lis)) {
puts("poll_fifo()"); /* 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) */ /* read as many [x y z] sets as specified by watermark level (fth) */
/* copy them to the fifo data struct given below as `fifo' */ /* copy them to the fifo data struct given below as `fifo' */
if (lis3dh_read_fifo(&lis, &data)) { if (lis3dh_read_fifo(&lis, &fifo)) {
puts("read_fifo()"); /* error handling */
} }
/* read out fifo buffer data */ /* above function also writes out the qty of [x y z] sets stored in `fifo' */
for(i=0; i<data.size; i++) { for(i=0; i<fifo.size; i++) {
printf("x: %d mg, y: %d mg, z: %d mg\n", data.x[i], data.y[i], data.z[i]); printf("x: %d mg, y: %d mg, z: %d mg\n", fifo.x[i], fifo.y[i], fifo.z[i]);
} }
goto A;
/* deinitialise struct */ /* unregister interrupt */
if (int_unregister(GPIO_INTERRUPT_PIN)) {
/* error handling */
}
/* deinitalise struct */
if (lis3dh_deinit(&lis)) { if (lis3dh_deinit(&lis)) {
puts("deinit()"); /* error handling */
} }
return 0; return 0;